Merge branch 'dev-v2' of github.com:dataease/dataease into dev-v2
This commit is contained in:
commit
b02232be7f
2
.gitignore
vendored
2
.gitignore
vendored
@ -48,3 +48,5 @@ core/core-frontend/src/assets/fsSvg.html
|
||||
/sdk/dataease-plugin-filter/
|
||||
/sdk/dataease-plugin-interface/
|
||||
/sdk/dataease-plugin-view/
|
||||
/extensions/
|
||||
.vite/
|
||||
|
||||
@ -2,9 +2,9 @@ FROM registry.cn-qingdao.aliyuncs.com/dataease/alpine-openjdk17-jre
|
||||
|
||||
ARG IMAGE_TAG
|
||||
|
||||
RUN mkdir -p /opt/apps/config /opt/dataease/drivers/ /opt/dataease2.0/cache/ /opt/dataease2.0/data/map /opt/dataease2.0/data/static-resource/
|
||||
RUN mkdir -p /opt/apps/config /opt/dataease2.0/drivers/ /opt/dataease2.0/cache/ /opt/dataease2.0/data/map /opt/dataease2.0/data/static-resource/
|
||||
|
||||
ADD drivers/* /opt/dataease/drivers/
|
||||
ADD drivers/* /opt/dataease2.0/drivers/
|
||||
ADD mapFiles/ /opt/dataease2.0/data/map/
|
||||
ADD staticResource/ /opt/dataease2.0/data/static-resource/
|
||||
|
||||
|
||||
11
README.md
11
README.md
@ -15,7 +15,9 @@
|
||||
|
||||
DataEase 是开源的数据可视化分析工具,帮助用户快速分析数据并洞察业务趋势,从而实现业务的改进与优化。DataEase 支持丰富的数据源连接,能够通过拖拉拽方式快速制作图表,并可以方便的与他人分享。
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
**DataEase 的优势:**
|
||||
|
||||
@ -52,11 +54,8 @@ DataEase 是开源的数据可视化分析工具,帮助用户快速分析数
|
||||
|
||||
## DataEase 快速入门
|
||||
|
||||
- [安装部署教程](https://dataease.io/docs/installation/installation_mode/)
|
||||
- [快速入门视频](https://www.bilibili.com/video/BV1qG4y1F7uc/)
|
||||
- [完整在线文档](https://dataease.io/docs/)
|
||||
- [中文社区论坛](https://bbs.fit2cloud.com/c/de/6)
|
||||
- [模板应用市场](https://dataease.io/templates/)
|
||||
- [在线文档](https://dataease.io/docs/)
|
||||
- [社区论坛](https://bbs.fit2cloud.com/c/de/6)
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
package io.dataease.chart.manage;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import io.dataease.api.chart.dto.*;
|
||||
import io.dataease.api.chart.request.ChartDrillRequest;
|
||||
import io.dataease.api.chart.request.ChartExtRequest;
|
||||
import io.dataease.api.dataset.dto.SqlVariableDetails;
|
||||
import io.dataease.api.dataset.union.DatasetGroupInfoDTO;
|
||||
import io.dataease.api.dataset.union.model.SQLMeta;
|
||||
import io.dataease.api.permissions.auth.api.InteractiveAuthApi;
|
||||
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
|
||||
import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO;
|
||||
import io.dataease.chart.constant.ChartConstants;
|
||||
@ -30,6 +28,7 @@ import io.dataease.engine.utils.Utils;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.result.ResultCode;
|
||||
import io.dataease.system.manage.CorePermissionManage;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
@ -37,7 +36,6 @@ import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@ -65,8 +63,9 @@ public class ChartDataManage {
|
||||
private ChartViewManege chartViewManege;
|
||||
@Resource
|
||||
private PermissionManage permissionManage;
|
||||
@Autowired(required = false)
|
||||
private InteractiveAuthApi interactiveAuthApi;
|
||||
|
||||
@Resource
|
||||
private CorePermissionManage corePermissionManage;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(ChartDataManage.class);
|
||||
|
||||
@ -140,11 +139,12 @@ public class ChartDataManage {
|
||||
DEException.throwException(ResultCode.DATA_IS_WRONG.code(), Translator.get("i18n_no_ds"));
|
||||
}
|
||||
// check permission
|
||||
if (interactiveAuthApi != null) {
|
||||
BusiPerCheckDTO dto = new BusiPerCheckDTO();
|
||||
dto.setId(table.getId());
|
||||
dto.setAuthEnum(AuthEnum.READ);
|
||||
interactiveAuthApi.checkAuth(dto);
|
||||
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
|
||||
|
||||
@ -9,8 +9,6 @@ import io.dataease.api.dataset.union.DatasetGroupInfoDTO;
|
||||
import io.dataease.api.dataset.union.UnionDTO;
|
||||
import io.dataease.api.dataset.vo.DataSetBarVO;
|
||||
import io.dataease.api.ds.vo.DatasourceDTO;
|
||||
import io.dataease.api.permissions.user.api.UserApi;
|
||||
import io.dataease.api.permissions.user.vo.UserFormVO;
|
||||
import io.dataease.commons.constants.OptConstants;
|
||||
import io.dataease.dataset.dao.auto.entity.CoreDatasetGroup;
|
||||
import io.dataease.dataset.dao.auto.entity.CoreDatasetTable;
|
||||
@ -31,11 +29,11 @@ import io.dataease.license.config.XpackInteract;
|
||||
import io.dataease.model.BusiNodeRequest;
|
||||
import io.dataease.model.BusiNodeVO;
|
||||
import io.dataease.operation.manage.CoreOptRecentManage;
|
||||
import io.dataease.system.manage.CoreUserManage;
|
||||
import io.dataease.utils.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@ -68,8 +66,10 @@ public class DatasetGroupManage {
|
||||
private CoreDatasetTableMapper coreDatasetTableMapper;
|
||||
@Resource
|
||||
private CoreDatasourceMapper coreDatasourceMapper;
|
||||
@Autowired(required = false)
|
||||
private UserApi userApi;
|
||||
|
||||
|
||||
@Resource
|
||||
private CoreUserManage coreUserManage;
|
||||
|
||||
@Resource
|
||||
private CoreOptRecentManage coreOptRecentManage;
|
||||
@ -88,13 +88,9 @@ public class DatasetGroupManage {
|
||||
CoreDatasetGroup coreDatasetGroup = coreDatasetGroupMapper.selectById(datasetGroupInfoDTO.getId());
|
||||
datasetGroupInfoDTO.setPid(coreDatasetGroup.getPid());
|
||||
}
|
||||
if (userApi == null) {
|
||||
checkName(datasetGroupInfoDTO);
|
||||
}
|
||||
if (userApi != null) {
|
||||
datasetGroupInfoDTO.setUpdateBy(userApi.info().getId() + "");
|
||||
datasetGroupInfoDTO.setLastUpdateTime(System.currentTimeMillis());
|
||||
}
|
||||
checkName(datasetGroupInfoDTO);
|
||||
datasetGroupInfoDTO.setUpdateBy(AuthUtils.getUser().getUserId() + "");
|
||||
datasetGroupInfoDTO.setLastUpdateTime(System.currentTimeMillis());
|
||||
if (StringUtils.equalsIgnoreCase(datasetGroupInfoDTO.getNodeType(), leafType)) {
|
||||
if (!rename && ObjectUtils.isEmpty(datasetGroupInfoDTO.getAllFields())) {
|
||||
DEException.throwException(Translator.get("i18n_no_fields"));
|
||||
@ -112,10 +108,8 @@ public class DatasetGroupManage {
|
||||
if (ObjectUtils.isEmpty(datasetGroupInfoDTO.getId())) {
|
||||
isCreate = true;
|
||||
datasetGroupInfoDTO.setId(IDUtils.snowID());
|
||||
if (userApi != null) {
|
||||
datasetGroupInfoDTO.setCreateBy(userApi.info().getId() + "");
|
||||
datasetGroupInfoDTO.setUpdateBy(userApi.info().getId() + "");
|
||||
}
|
||||
datasetGroupInfoDTO.setCreateBy(AuthUtils.getUser().getUserId() + "");
|
||||
datasetGroupInfoDTO.setUpdateBy(AuthUtils.getUser().getUserId() + "");
|
||||
datasetGroupInfoDTO.setCreateTime(time);
|
||||
datasetGroupInfoDTO.setLastUpdateTime(time);
|
||||
datasetGroupInfoDTO.setPid(datasetGroupInfoDTO.getPid() == null ? 0L : datasetGroupInfoDTO.getPid());
|
||||
@ -152,21 +146,19 @@ public class DatasetGroupManage {
|
||||
CoreDatasetGroup coreDatasetGroup = BeanUtils.copyBean(new CoreDatasetGroup(), datasetGroupInfoDTO);
|
||||
coreDatasetGroup.setLastUpdateTime(System.currentTimeMillis());
|
||||
coreDatasetGroupMapper.updateById(coreDatasetGroup);
|
||||
coreOptRecentManage.saveOpt(datasetGroupInfoDTO.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET,OptConstants.OPT_TYPE.UPDATE);
|
||||
coreOptRecentManage.saveOpt(datasetGroupInfoDTO.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET, OptConstants.OPT_TYPE.UPDATE);
|
||||
}
|
||||
|
||||
@XpackInteract(value = "authResourceTree", before = false)
|
||||
public void innerSave(DatasetGroupInfoDTO datasetGroupInfoDTO) {
|
||||
CoreDatasetGroup coreDatasetGroup = BeanUtils.copyBean(new CoreDatasetGroup(), datasetGroupInfoDTO);
|
||||
coreDatasetGroupMapper.insert(coreDatasetGroup);
|
||||
coreOptRecentManage.saveOpt(coreDatasetGroup.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET,OptConstants.OPT_TYPE.NEW);
|
||||
coreOptRecentManage.saveOpt(coreDatasetGroup.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET, OptConstants.OPT_TYPE.NEW);
|
||||
}
|
||||
|
||||
@XpackInteract(value = "authResourceTree", before = false)
|
||||
public DatasetGroupInfoDTO move(DatasetGroupInfoDTO datasetGroupInfoDTO) {
|
||||
if (userApi == null) {
|
||||
checkName(datasetGroupInfoDTO);
|
||||
}
|
||||
checkName(datasetGroupInfoDTO);
|
||||
if (datasetGroupInfoDTO.getPid() != 0) {
|
||||
checkMove(datasetGroupInfoDTO);
|
||||
}
|
||||
@ -174,12 +166,10 @@ public class DatasetGroupManage {
|
||||
long time = System.currentTimeMillis();
|
||||
CoreDatasetGroup coreDatasetGroup = new CoreDatasetGroup();
|
||||
BeanUtils.copyBean(coreDatasetGroup, datasetGroupInfoDTO);
|
||||
if (userApi != null) {
|
||||
datasetGroupInfoDTO.setUpdateBy(userApi.info().getId() + "");
|
||||
}
|
||||
datasetGroupInfoDTO.setUpdateBy(AuthUtils.getUser().getUserId() + "");
|
||||
coreDatasetGroup.setLastUpdateTime(time);
|
||||
coreDatasetGroupMapper.updateById(coreDatasetGroup);
|
||||
coreOptRecentManage.saveOpt(coreDatasetGroup.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET,OptConstants.OPT_TYPE.UPDATE);
|
||||
coreOptRecentManage.saveOpt(coreDatasetGroup.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET, OptConstants.OPT_TYPE.UPDATE);
|
||||
return datasetGroupInfoDTO;
|
||||
}
|
||||
|
||||
@ -190,7 +180,7 @@ public class DatasetGroupManage {
|
||||
DEException.throwException("resource not exist");
|
||||
}
|
||||
Objects.requireNonNull(CommonBeanFactory.getBean(this.getClass())).recursionDel(id);
|
||||
coreOptRecentManage.saveOpt(coreDatasetGroup.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET,OptConstants.OPT_TYPE.DELETE);
|
||||
coreOptRecentManage.saveOpt(coreDatasetGroup.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASET, OptConstants.OPT_TYPE.DELETE);
|
||||
}
|
||||
|
||||
public void recursionDel(Long id) {
|
||||
@ -231,15 +221,13 @@ public class DatasetGroupManage {
|
||||
public DataSetBarVO queryBarInfo(Long id) {
|
||||
DataSetBarVO dataSetBarVO = coreDataSetExtMapper.queryBarInfo(id);
|
||||
// get creator
|
||||
if (userApi != null) {
|
||||
UserFormVO userFormVO = userApi.queryById(Long.valueOf(dataSetBarVO.getCreateBy()));
|
||||
if (userFormVO != null) {
|
||||
dataSetBarVO.setCreator(userFormVO.getName());
|
||||
}
|
||||
UserFormVO userFormVOUpdateBy = userApi.queryById(Long.valueOf(dataSetBarVO.getUpdateBy()));
|
||||
if (userFormVOUpdateBy != null) {
|
||||
dataSetBarVO.setUpdater(userFormVOUpdateBy.getName());
|
||||
}
|
||||
String userName = coreUserManage.getUserName(Long.valueOf(dataSetBarVO.getCreateBy()));
|
||||
if (StringUtils.isNotBlank(userName)) {
|
||||
dataSetBarVO.setCreator(userName);
|
||||
}
|
||||
String updateUserName = coreUserManage.getUserName(Long.valueOf(dataSetBarVO.getUpdateBy()));
|
||||
if (StringUtils.isNotBlank(updateUserName)) {
|
||||
dataSetBarVO.setUpdater(updateUserName);
|
||||
}
|
||||
dataSetBarVO.setDatasourceDTOList(getDatasource(id));
|
||||
return dataSetBarVO;
|
||||
@ -254,13 +242,13 @@ public class DatasetGroupManage {
|
||||
|
||||
QueryWrapper<CoreDatasource> datasourceQueryWrapper = new QueryWrapper<>();
|
||||
datasourceQueryWrapper.in("id", ids);
|
||||
List<DatasourceDTO> datasourceDTOList = coreDatasourceMapper.selectList(datasourceQueryWrapper).stream().map(ele -> {
|
||||
List<DatasourceDTO> datasourceDTOList = coreDatasourceMapper.selectList(datasourceQueryWrapper).stream().map(ele -> {
|
||||
DatasourceDTO dto = new DatasourceDTO();
|
||||
BeanUtils.copyBean(dto, ele);
|
||||
dto.setConfiguration(null);
|
||||
return dto;
|
||||
}).collect(Collectors.toList());
|
||||
if(ids.size() != datasourceDTOList.size()){
|
||||
if (ids.size() != datasourceDTOList.size()) {
|
||||
DEException.throwException("由于数据集所用的数据源已被删除,无法显示数据集");
|
||||
}
|
||||
return datasourceDTOList;
|
||||
@ -366,15 +354,13 @@ public class DatasetGroupManage {
|
||||
DatasetGroupInfoDTO dto = new DatasetGroupInfoDTO();
|
||||
BeanUtils.copyBean(dto, coreDatasetGroup);
|
||||
// get creator
|
||||
if (userApi != null) {
|
||||
UserFormVO userFormVO = userApi.queryById(Long.valueOf(dto.getCreateBy()));
|
||||
if (userFormVO != null) {
|
||||
dto.setCreator(userFormVO.getName());
|
||||
}
|
||||
UserFormVO userFormVOUpdateBy = userApi.queryById(Long.valueOf(dto.getUpdateBy()));
|
||||
if (userFormVOUpdateBy != null) {
|
||||
dto.setUpdater(userFormVOUpdateBy.getName());
|
||||
}
|
||||
String userName = coreUserManage.getUserName(Long.valueOf(dto.getCreateBy()));
|
||||
if (StringUtils.isNotBlank(userName)) {
|
||||
dto.setCreator(userName);
|
||||
}
|
||||
String updateUserName = coreUserManage.getUserName(Long.valueOf(dto.getUpdateBy()));
|
||||
if (StringUtils.isNotBlank(updateUserName)) {
|
||||
dto.setUpdater(updateUserName);
|
||||
}
|
||||
dto.setUnionSql(null);
|
||||
if (StringUtils.equalsIgnoreCase(dto.getNodeType(), "dataset")) {
|
||||
@ -440,8 +426,8 @@ public class DatasetGroupManage {
|
||||
for (CoreDatasetTable datasetTable : datasetTables) {
|
||||
if (StringUtils.isNotEmpty(datasetTable.getSqlVariableDetails())) {
|
||||
List<SqlVariableDetails> defaultsSqlVariableDetails = JsonUtil.parseList(datasetTable.getSqlVariableDetails(), listTypeReference);
|
||||
if(CollectionUtil.isNotEmpty(defaultsSqlVariableDetails)){
|
||||
List<String> fullName = new ArrayList<>();
|
||||
if (CollectionUtil.isNotEmpty(defaultsSqlVariableDetails)) {
|
||||
List<String> fullName = new ArrayList<>();
|
||||
geFullName(id, fullName);
|
||||
List<String> finalFullName = CollectionUtil.reverse(fullName);
|
||||
defaultsSqlVariableDetails.forEach(sqlVariableDetails -> {
|
||||
|
||||
@ -6,12 +6,10 @@ import io.dataease.api.dataset.dto.DatasetTableDTO;
|
||||
import io.dataease.api.dataset.dto.SqlVariableDetails;
|
||||
import io.dataease.api.dataset.union.*;
|
||||
import io.dataease.api.dataset.union.model.SQLObj;
|
||||
import io.dataease.api.permissions.auth.api.InteractiveAuthApi;
|
||||
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
|
||||
import io.dataease.commons.utils.SqlparserUtils;
|
||||
import io.dataease.constant.AuthEnum;
|
||||
import io.dataease.dataset.constant.DatasetTableType;
|
||||
import io.dataease.dataset.dao.auto.mapper.CoreDatasetTableMapper;
|
||||
import io.dataease.dataset.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.dataset.utils.DatasetTableTypeConstants;
|
||||
import io.dataease.dataset.utils.SqlUtils;
|
||||
@ -24,6 +22,7 @@ import io.dataease.engine.constant.ExtFieldConstant;
|
||||
import io.dataease.engine.constant.SQLConstants;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.system.manage.CorePermissionManage;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import jakarta.annotation.Resource;
|
||||
@ -31,7 +30,6 @@ import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@ -44,16 +42,14 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Component
|
||||
public class DatasetSQLManage {
|
||||
@Resource
|
||||
private CoreDatasetTableMapper coreDatasetTableMapper;
|
||||
@Resource
|
||||
private DatasetTableFieldManage datasetTableFieldManage;
|
||||
|
||||
@Resource
|
||||
private CoreDatasourceMapper coreDatasourceMapper;
|
||||
@Resource
|
||||
private EngineServer engineServer;
|
||||
@Autowired(required = false)
|
||||
private InteractiveAuthApi interactiveAuthApi;
|
||||
|
||||
@Resource
|
||||
private CorePermissionManage corePermissionManage;
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(DatasetSQLManage.class);
|
||||
|
||||
@ -328,17 +324,15 @@ public class DatasetSQLManage {
|
||||
|
||||
private String putObj2Map(Map<Long, DatasourceSchemaDTO> dsMap, DatasetTableDTO ds) throws Exception {
|
||||
// 通过datasource id校验数据源权限
|
||||
if (interactiveAuthApi != null) {
|
||||
BusiPerCheckDTO dto = new BusiPerCheckDTO();
|
||||
dto.setId(ds.getDatasourceId());
|
||||
dto.setAuthEnum(AuthEnum.READ);
|
||||
try {
|
||||
interactiveAuthApi.checkAuth(dto);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(Translator.get("i18n_no_datasource_permission"));
|
||||
}
|
||||
BusiPerCheckDTO dto = new BusiPerCheckDTO();
|
||||
dto.setId(ds.getDatasourceId());
|
||||
dto.setAuthEnum(AuthEnum.READ);
|
||||
boolean checked = corePermissionManage.checkAuth(dto);
|
||||
if (!checked) {
|
||||
DEException.throwException(Translator.get("i18n_no_datasource_permission"));
|
||||
}
|
||||
|
||||
|
||||
String schemaAlias;
|
||||
if (StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.DB) || StringUtils.equalsIgnoreCase(ds.getType(), DatasetTableType.SQL)) {
|
||||
CoreDatasource coreDatasource = coreDatasourceMapper.selectById(ds.getDatasourceId());
|
||||
|
||||
@ -87,6 +87,13 @@ public class DataSourceManage {
|
||||
coreOptRecentManage.saveOpt(coreDatasource.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASOURCE,OptConstants.OPT_TYPE.UPDATE);
|
||||
}
|
||||
|
||||
@XpackInteract(value = "datasourceResourceTree", before = false)
|
||||
public void innerEditStatus(CoreDatasource coreDatasource) {
|
||||
UpdateWrapper<CoreDatasource> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.eq("id", coreDatasource.getId());
|
||||
coreDatasourceMapper.update(coreDatasource, updateWrapper);
|
||||
}
|
||||
|
||||
@XpackInteract(value = "datasourceResourceTree", before = false)
|
||||
public void move(DatasourceDTO dataSourceDTO) {
|
||||
Long id = dataSourceDTO.getId();
|
||||
|
||||
@ -319,7 +319,7 @@ public class ApiUtils {
|
||||
}
|
||||
}
|
||||
for (JsonNode node : jsonArray) {
|
||||
handleStr(apiDefinition, node.toString(), childrenField, rootPath + "." + fieldName + "[*]");
|
||||
handleStr(apiDefinition, node.toString(), childrenField, rootPath + "." + String.format(path, fieldName) + "[*]");
|
||||
}
|
||||
o.put("children", childrenField);
|
||||
o.put("childrenDataType", "LIST");
|
||||
|
||||
@ -47,15 +47,14 @@ import java.util.stream.Collectors;
|
||||
@Component("calciteProvider")
|
||||
public class CalciteProvider {
|
||||
|
||||
//TODO mongo impala es hive
|
||||
@Resource
|
||||
protected CoreDatasourceMapper coreDatasourceMapper;
|
||||
@Resource
|
||||
private EngineServer engineServer;
|
||||
protected ExtendedJdbcClassLoader extendedJdbcClassLoader;
|
||||
private Map<Long, ExtendedJdbcClassLoader> customJdbcClassLoaders = new HashMap<>();
|
||||
private final String FILE_PATH = "/opt/dataease/drivers";
|
||||
private final String CUSTOM_PATH = "/opt/dataease/custom-drivers/";
|
||||
private final String FILE_PATH = "/opt/dataease2.0/drivers";
|
||||
private final String CUSTOM_PATH = "/opt/dataease2.0/custom-drivers/";
|
||||
private static String split = "DE";
|
||||
|
||||
@Resource
|
||||
@ -93,7 +92,7 @@ public class CalciteProvider {
|
||||
schemas.add(resultSet.getString(1));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return schemas;
|
||||
}
|
||||
@ -107,7 +106,7 @@ public class CalciteProvider {
|
||||
tables.add(getTableDesc(datasourceRequest, resultSet));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
}
|
||||
return tables;
|
||||
@ -145,15 +144,11 @@ public class CalciteProvider {
|
||||
String querySql = getTablesSql(datasourceRequest).get(0);
|
||||
try (Connection con = getConnection(datasourceRequest.getDatasource()); Statement statement = getStatement(con, 30); ResultSet resultSet = statement.executeQuery(querySql)) {
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return "Success";
|
||||
}
|
||||
|
||||
public List<TableField> getTableFields(DatasourceRequest datasourceRequest) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, Object> fetchResultField(DatasourceRequest datasourceRequest) throws DEException {
|
||||
List<TableField> datasetTableFields = new ArrayList<>();
|
||||
List<String[]> list = new LinkedList<>();
|
||||
@ -242,7 +237,7 @@ public class CalciteProvider {
|
||||
Class.forName("org.apache.calcite.jdbc.Driver");
|
||||
connection = DriverManager.getConnection("jdbc:calcite:", info);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
@ -433,7 +428,7 @@ public class CalciteProvider {
|
||||
list.add(row);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@ -573,7 +568,7 @@ public class CalciteProvider {
|
||||
Driver driverClass = (Driver) jdbcClassLoader.loadClass(driverClassName).newInstance();
|
||||
conn = driverClass.connect(configuration.getJdbc(), props);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
@ -587,7 +582,7 @@ public class CalciteProvider {
|
||||
stat = connection.createStatement();
|
||||
stat.setQueryTimeout(queryTimeout);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
@ -640,7 +635,7 @@ public class CalciteProvider {
|
||||
customJdbcClassLoaders.put(coreDriver.getId(), customJdbcClassLoader);
|
||||
return customJdbcClassLoader;
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -691,7 +686,7 @@ public class CalciteProvider {
|
||||
SchemaPlus rootSchema = buildSchema(datasourceRequest, calciteConnection);
|
||||
addCustomFunctions(rootSchema);
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -709,7 +704,7 @@ public class CalciteProvider {
|
||||
rootSchema.removeSubSchema(datasourceSchemaDTO.getSchemaAlias());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DEException.throwException(e);
|
||||
DEException.throwException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class ExcelUtils {
|
||||
public static final String UFEFF = "\uFEFF";
|
||||
private static String path = "/opt/dataease/data/excel/";
|
||||
private static String path = "/opt/dataease2.0/data/excel/";
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private static TypeReference<List<TableField>> TableFieldListTypeReference = new TypeReference<List<TableField>>() {
|
||||
|
||||
@ -31,7 +31,7 @@ import java.util.*;
|
||||
@RequestMapping("/datasourceDriver")
|
||||
public class DatasourceDriverServer implements DatasourceDriverApi {
|
||||
|
||||
private final static String DRIVER_PATH = "/opt/dataease/custom-drivers/";
|
||||
private final static String DRIVER_PATH = "/opt/dataease2.0/custom-drivers/";
|
||||
|
||||
@Resource
|
||||
private CoreDriverMapper coreDriverMapper;
|
||||
|
||||
@ -12,10 +12,6 @@ import io.dataease.api.dataset.dto.DatasetTableDTO;
|
||||
import io.dataease.api.dataset.dto.PreviewSqlDTO;
|
||||
import io.dataease.api.ds.DatasourceApi;
|
||||
import io.dataease.api.ds.vo.*;
|
||||
import io.dataease.api.permissions.auth.api.InteractiveAuthApi;
|
||||
import io.dataease.api.permissions.auth.dto.BusiResourceEditor;
|
||||
import io.dataease.api.permissions.user.api.UserApi;
|
||||
import io.dataease.api.permissions.user.vo.UserFormVO;
|
||||
import io.dataease.commons.constants.TaskStatus;
|
||||
import io.dataease.commons.utils.CommonThreadPool;
|
||||
import io.dataease.constant.DataSourceType;
|
||||
@ -34,18 +30,17 @@ import io.dataease.datasource.provider.ApiUtils;
|
||||
import io.dataease.datasource.provider.CalciteProvider;
|
||||
import io.dataease.datasource.provider.ExcelUtils;
|
||||
import io.dataease.datasource.request.DatasourceRequest;
|
||||
import io.dataease.datasource.type.Pg;
|
||||
import io.dataease.engine.constant.SQLConstants;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.license.config.XpackInteract;
|
||||
import io.dataease.model.BusiNodeRequest;
|
||||
import io.dataease.model.BusiNodeVO;
|
||||
import io.dataease.system.manage.CoreUserManage;
|
||||
import io.dataease.utils.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@ -89,10 +84,10 @@ public class DatasourceServer implements DatasourceApi {
|
||||
private CoreDsFinishPageMapper coreDsFinishPageMapper;
|
||||
@Resource
|
||||
private DatasetDataManage datasetDataManage;
|
||||
@Autowired(required = false)
|
||||
private UserApi userApi;
|
||||
@Autowired(required = false)
|
||||
private InteractiveAuthApi interactiveAuthApi;
|
||||
|
||||
|
||||
@Resource
|
||||
private CoreUserManage coreUserManage;
|
||||
|
||||
@Override
|
||||
public List<DatasourceDTO> query(String keyWord) {
|
||||
@ -125,10 +120,12 @@ public class DatasourceServer implements DatasourceApi {
|
||||
if (Objects.equals(dataSourceDTO.getId(), dataSourceDTO.getPid())) {
|
||||
DEException.throwException(Translator.get("i18n_pid_not_eq_id"));
|
||||
}
|
||||
List<Long> ids = new ArrayList<>();
|
||||
getParents(dataSourceDTO.getPid(), ids);
|
||||
if (ids.contains(dataSourceDTO.getId())) {
|
||||
DEException.throwException(Translator.get("i18n_pid_not_eq_id"));
|
||||
if (dataSourceDTO.getPid() != 0) {
|
||||
List<Long> ids = new ArrayList<>();
|
||||
getParents(dataSourceDTO.getPid(), ids);
|
||||
if (ids.contains(dataSourceDTO.getId())) {
|
||||
DEException.throwException(Translator.get("i18n_pid_not_eq_id"));
|
||||
}
|
||||
}
|
||||
dataSourceManage.move(dataSourceDTO);
|
||||
}
|
||||
@ -309,16 +306,16 @@ public class DatasourceServer implements DatasourceApi {
|
||||
|
||||
private static void checkParams(String configurationStr) {
|
||||
DatasourceConfiguration configuration = JsonUtil.parseObject(configurationStr, DatasourceConfiguration.class);
|
||||
if(configuration.getInitialPoolSize() < configuration.getMinPoolSize()){
|
||||
if (configuration.getInitialPoolSize() < configuration.getMinPoolSize()) {
|
||||
DEException.throwException("初始连接数不能小于最小连接数!");
|
||||
}
|
||||
if(configuration.getInitialPoolSize() > configuration.getMaxPoolSize()){
|
||||
if (configuration.getInitialPoolSize() > configuration.getMaxPoolSize()) {
|
||||
DEException.throwException("初始连接数不能大于最大连接数!");
|
||||
}
|
||||
if(configuration.getMaxPoolSize() < configuration.getMinPoolSize()){
|
||||
if (configuration.getMaxPoolSize() < configuration.getMinPoolSize()) {
|
||||
DEException.throwException("最大连接数不能小于最小连接数!");
|
||||
}
|
||||
if(configuration.getQueryTimeout() < 0){
|
||||
if (configuration.getQueryTimeout() < 0) {
|
||||
DEException.throwException("查询超时不能小于0!");
|
||||
}
|
||||
}
|
||||
@ -538,12 +535,8 @@ public class DatasourceServer implements DatasourceApi {
|
||||
}
|
||||
datasourceDTO.setConfiguration(new String(Base64.getEncoder().encode(datasourceDTO.getConfiguration().getBytes())));
|
||||
|
||||
if (userApi != null) {
|
||||
UserFormVO userFormVO = userApi.queryById(Long.valueOf(datasourceDTO.getCreateBy()));
|
||||
if (userFormVO != null) {
|
||||
datasourceDTO.setCreator(userFormVO.getName());
|
||||
}
|
||||
}
|
||||
datasourceDTO.setCreator(coreUserManage.getUserName(Long.valueOf(datasourceDTO.getCreateBy())));
|
||||
|
||||
return datasourceDTO;
|
||||
}
|
||||
|
||||
@ -620,14 +613,12 @@ public class DatasourceServer implements DatasourceApi {
|
||||
record.setStatus(coreDatasource.getStatus());
|
||||
QueryWrapper<CoreDatasource> wrapper = new QueryWrapper<>();
|
||||
wrapper.eq("id", coreDatasource.getId());
|
||||
datasourceMapper.update(record, wrapper);
|
||||
if (interactiveAuthApi != null) {
|
||||
BusiResourceEditor editor = new BusiResourceEditor();
|
||||
editor.setId((long) coreDatasource.getId());
|
||||
editor.setName(coreDatasource.getName());
|
||||
editor.setExtraFlag(getExtraFlag(coreDatasource.getType(), coreDatasource.getStatus()));
|
||||
interactiveAuthApi.editResource(editor);
|
||||
CoreDatasource originData = datasourceMapper.selectById(coreDatasource.getId());
|
||||
String originStatus = originData.getStatus();
|
||||
if (StringUtils.equals(coreDatasource.getStatus(), originStatus)) {
|
||||
return datasourceDTO;
|
||||
}
|
||||
dataSourceManage.innerEditStatus(coreDatasource);
|
||||
return datasourceDTO;
|
||||
}
|
||||
|
||||
@ -880,7 +871,7 @@ public class DatasourceServer implements DatasourceApi {
|
||||
List<DatasetTableDTO> datasetTableDTOS = ApiUtils.getTables(datasourceRequest);
|
||||
for (int i = 0; i < pager.getRecords().size(); i++) {
|
||||
for (int i1 = 0; i1 < datasetTableDTOS.size(); i1++) {
|
||||
if(pager.getRecords().get(i).getTableName().equalsIgnoreCase(datasetTableDTOS.get(i1).getTableName())){
|
||||
if (pager.getRecords().get(i).getTableName().equalsIgnoreCase(datasetTableDTOS.get(i1).getTableName())) {
|
||||
pager.getRecords().get(i).setName(datasetTableDTOS.get(i1).getName());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package io.dataease.datasource.type;
|
||||
|
||||
import io.dataease.api.ds.vo.DatasourceConfiguration;
|
||||
import io.dataease.exception.DEException;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -25,7 +26,7 @@ public class Mysql extends DatasourceConfiguration {
|
||||
} else {
|
||||
for (String illegalParameter : illegalParameters) {
|
||||
if (getExtraParams().toLowerCase().contains(illegalParameter.toLowerCase())) {
|
||||
throw new RuntimeException("Illegal parameter: " + illegalParameter);
|
||||
DEException.throwException("Illegal parameter: " + illegalParameter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package io.dataease.system.manage;
|
||||
|
||||
import io.dataease.api.permissions.auth.dto.BusiPerCheckDTO;
|
||||
import io.dataease.license.config.XpackInteract;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CorePermissionManage {
|
||||
|
||||
@XpackInteract(value = "corePermissionManage", replace = true)
|
||||
public boolean checkAuth(BusiPerCheckDTO dto) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package io.dataease.system.manage;
|
||||
|
||||
import io.dataease.license.config.XpackInteract;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CoreUserManage {
|
||||
|
||||
|
||||
@XpackInteract(value = "coreUserManage", replace = true)
|
||||
public String getUserName(Long uid) {
|
||||
return "管理员";
|
||||
}
|
||||
}
|
||||
@ -53,3 +53,4 @@ i18n_schema_is_empty=schema \u4E3A\u7A7A\uFF01
|
||||
i18n_table_name_repeat=\u540D\u79F0\u91CD\u590D:
|
||||
i18n_sql_not_empty=sql \u4E0D\u80FD\u4E3A\u7A7A
|
||||
i18n_menu.parameter=\u7CFB\u7EDF\u53C2\u6570
|
||||
i18n_user_old_pwd_error=\u539F\u59CB\u5BC6\u7801\u9519\u8BEF
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="icon_file-add_outlined">
|
||||
<path id="Subtract" fill-rule="evenodd" clip-rule="evenodd" d="M4.16667 2.50001H13.3333V4.59959C13.3333 4.7101 13.3772 4.81608 13.4554 4.89422C13.5335 4.97236 13.6395 5.01626 13.75 5.01626H15.8333V10.8333H17.5V4.09626C17.5001 3.87532 17.4124 3.66341 17.2563 3.50709L14.8275 1.07751C14.7501 1.00007 14.6582 0.938651 14.557 0.896756C14.4558 0.85486 14.3474 0.833312 14.2379 0.833344H3.33333C3.11232 0.833344 2.90036 0.921141 2.74408 1.07742C2.5878 1.2337 2.5 1.44566 2.5 1.66668V18.3333C2.5 18.5544 2.5878 18.7663 2.74408 18.9226C2.90036 19.0789 3.11232 19.1667 3.33333 19.1667H10V17.5H4.16667V2.50001Z"/>
|
||||
<path id="Vector" d="M14.5833 12.5C14.3532 12.5 14.1667 12.6865 14.1667 12.9167V15H12.0833C11.8532 15 11.6667 15.1865 11.6667 15.4167V16.25C11.6667 16.4801 11.8532 16.6667 12.0833 16.6667H14.1667V18.75C14.1667 18.9801 14.3532 19.1667 14.5833 19.1667H15.4167C15.6468 19.1667 15.8333 18.9801 15.8333 18.75V16.6667H17.9167C18.1468 16.6667 18.3333 16.4801 18.3333 16.25V15.4167C18.3333 15.1865 18.1468 15 17.9167 15H15.8333V12.9167C15.8333 12.6865 15.6468 12.5 15.4167 12.5H14.5833Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -152,8 +152,8 @@ eventBus.on('clearCanvas', clearCanvas)
|
||||
</div>
|
||||
<div class="middle-area"></div>
|
||||
</template>
|
||||
<template v-else-if="!isDataEaseBi">
|
||||
<el-icon class="custom-el-icon back-icon" @click="backToMain()">
|
||||
<template v-else>
|
||||
<el-icon v-if="!isDataEaseBi" class="custom-el-icon back-icon" @click="backToMain()">
|
||||
<Icon class="toolbar-icon" name="icon_left_outlined" />
|
||||
</el-icon>
|
||||
<div class="left-area">
|
||||
|
||||
@ -184,6 +184,7 @@ onMounted(() => {
|
||||
emitter.on(`addQueryCriteria${element.value.id}`, addCriteriaConfigOut)
|
||||
emitter.on(`editQueryCriteria${element.value.id}`, editQueryCriteria)
|
||||
emitter.on(`updateQueryCriteria${element.value.id}`, updateQueryCriteria)
|
||||
updateQueryCriteria()
|
||||
})
|
||||
|
||||
const dragover = () => {
|
||||
|
||||
@ -364,6 +364,16 @@ const init = (queryId: string) => {
|
||||
|
||||
const datasetMapKeyList = Object.keys(datasetMap)
|
||||
|
||||
getSqlParams([
|
||||
...new Set(
|
||||
datasetFieldList.value
|
||||
.map(ele => ele.tableId)
|
||||
.filter(ele => !datasetMapKeyList.includes(ele) && ele)
|
||||
)
|
||||
]).then(res => {
|
||||
parameters.value = res || []
|
||||
})
|
||||
|
||||
if (datasetFieldIdList.every(ele => datasetMapKeyList.includes(ele))) {
|
||||
fields.value = datasetFieldList.value
|
||||
.map(ele => {
|
||||
@ -400,15 +410,6 @@ const init = (queryId: string) => {
|
||||
.finally(() => {
|
||||
handleCheckedFieldsChange(curComponent.value.checkedFields)
|
||||
})
|
||||
getSqlParams([
|
||||
...new Set(
|
||||
datasetFieldList.value
|
||||
.map(ele => ele.tableId)
|
||||
.filter(ele => !datasetMapKeyList.includes(ele) && ele)
|
||||
)
|
||||
]).then(res => {
|
||||
parameters.value = res || []
|
||||
})
|
||||
}
|
||||
|
||||
const weightlessness = () => {
|
||||
@ -729,10 +730,17 @@ defineExpose({
|
||||
value="0"
|
||||
/>
|
||||
<el-option
|
||||
v-if="curComponent.displayType === '2'"
|
||||
:disabled="curComponent.displayType !== '2'"
|
||||
label="数字下拉"
|
||||
value="2"
|
||||
/>
|
||||
<el-option
|
||||
v-else
|
||||
:disabled="curComponent.displayType !== '5'"
|
||||
label="数字下拉"
|
||||
value="5"
|
||||
/>
|
||||
<el-option
|
||||
:disabled="!['1', '7'].includes(curComponent.displayType)"
|
||||
label="时间"
|
||||
@ -802,7 +810,7 @@ defineExpose({
|
||||
<el-icon size="18px" v-if="data.leaf">
|
||||
<Icon name="icon_dataset"></Icon>
|
||||
</el-icon>
|
||||
<span class="label" style="margin-left: 8px" :title="node.label">{{
|
||||
<span class="label ellipsis" style="margin-left: 8px" :title="node.label">{{
|
||||
node.label
|
||||
}}</span>
|
||||
</div>
|
||||
@ -1287,9 +1295,10 @@ defineExpose({
|
||||
align-items: center;
|
||||
.label {
|
||||
margin-left: 5px;
|
||||
width: calc(100% - 45px);
|
||||
}
|
||||
}
|
||||
|
||||
max-width: 321px;
|
||||
.ed-select-dropdown__item.selected {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@ -230,6 +230,7 @@ export default {
|
||||
manage: '管理',
|
||||
auth: '授权',
|
||||
resource_name: '资源名称',
|
||||
menu_name: '菜单名称',
|
||||
from_role: '继承自以下角色:',
|
||||
auth_alone: '单独授权',
|
||||
org_role_empty: '组织管理员已拥有所有资源的权限,无需再授权',
|
||||
@ -263,7 +264,7 @@ export default {
|
||||
data_source_table: '数据源表',
|
||||
auth_method: '认证方式',
|
||||
passwd: '用户名密码',
|
||||
kerbers_info: '请确保 krb5.Conf、Keytab Key,已经添加到路径:/opt/dataease/conf',
|
||||
kerbers_info: '请确保 krb5.Conf、Keytab Key,已经添加到路径:/opt/dataease2.0/conf',
|
||||
client_principal: 'Client Principal',
|
||||
keytab_Key_path: 'Keytab Key Path',
|
||||
please_select_left: '请从左侧选择',
|
||||
@ -1429,8 +1430,9 @@ export default {
|
||||
auth_num: '授权数量',
|
||||
version: '版本',
|
||||
version_num: '版本号',
|
||||
standard: '标准版',
|
||||
standard: '社区版',
|
||||
enterprise: '企业版',
|
||||
Embedded: '嵌入式版',
|
||||
support: '获取技术支持',
|
||||
update_success: '更新成功',
|
||||
serial_no: '序列号',
|
||||
|
||||
21
core/core-frontend/src/models/chart/editor.d.ts
vendored
21
core/core-frontend/src/models/chart/editor.d.ts
vendored
@ -86,4 +86,25 @@ declare interface ChartEditorForm<T> {
|
||||
* 是否渲染图表
|
||||
*/
|
||||
render: boolean
|
||||
/**
|
||||
* 子属性
|
||||
*/
|
||||
prop?: string
|
||||
}
|
||||
/**
|
||||
* 轴编辑表单
|
||||
*/
|
||||
declare interface AxisEditForm {
|
||||
/**
|
||||
* 轴类型
|
||||
*/
|
||||
axisType: AxisType
|
||||
/**
|
||||
* 变更内容
|
||||
*/
|
||||
axis: Axis[]
|
||||
/**
|
||||
* 变更类型
|
||||
*/
|
||||
editType: 'add' | 'remove' | 'update'
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ import AppElement from './App.vue'
|
||||
import { setupI18n } from '@/plugins/vue-i18n'
|
||||
import { setupStore } from '@/store'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
import { setupElementPlus } from '@/plugins/element-plus'
|
||||
import { setupElementPlus, setupElementPlusIcons } from '@/plugins/element-plus'
|
||||
import { setupRouter } from '@/router'
|
||||
|
||||
const setupAll = async (dom: string, componentName: string): Promise<App<Element>> => {
|
||||
@ -66,6 +66,7 @@ const setupAll = async (dom: string, componentName: string): Promise<App<Element
|
||||
setupStore(app)
|
||||
setupRouter(app)
|
||||
setupElementPlus(app)
|
||||
setupElementPlusIcons(app)
|
||||
const userStore = useUserStoreWithOut()
|
||||
await userStore.setUser()
|
||||
app.mount(dom)
|
||||
|
||||
@ -95,6 +95,9 @@ export const pathValid = path => {
|
||||
* @returns
|
||||
*/
|
||||
const hasCurrentRouter = (locations, routers, index) => {
|
||||
if (!routers?.length) {
|
||||
return false
|
||||
}
|
||||
const location = locations[index]
|
||||
let kids = []
|
||||
const isvalid = routers.some(router => {
|
||||
|
||||
@ -150,7 +150,13 @@ const update = (licKey: string) => {
|
||||
<div class="item">
|
||||
<div class="label">{{ $t('about.version') }}</div>
|
||||
<div class="value">
|
||||
{{ license.edition === 'Standard' ? $t('about.standard') : $t('about.enterprise') }}
|
||||
{{
|
||||
!license?.edition
|
||||
? $t('about.standard')
|
||||
: license.edition === 'Embedded'
|
||||
? $t('about.Embedded')
|
||||
: $t('about.enterprise')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
|
||||
@ -173,33 +173,10 @@ const dsClick = (data: Tree) => {
|
||||
}
|
||||
//选中赋值
|
||||
_modelValue.value = data.id
|
||||
getFields(data.id, props.viewId)
|
||||
//关闭弹窗
|
||||
datasetSelectorPopover.value?.hide()
|
||||
}
|
||||
}
|
||||
const getFields = (id, chartId) => {
|
||||
if (id && chartId) {
|
||||
getFieldByDQ(id, chartId)
|
||||
.then(res => {
|
||||
state.value.dimension = (res.dimensionList as unknown as Field[]) || []
|
||||
state.value.quota = (res.quotaList as unknown as Field[]) || []
|
||||
state.value.dimensionData = JSON.parse(JSON.stringify(state.value.dimension))
|
||||
state.value.quotaData = JSON.parse(JSON.stringify(state.value.quota))
|
||||
})
|
||||
.catch(() => {
|
||||
state.value.dimension = []
|
||||
state.value.quota = []
|
||||
state.value.dimensionData = []
|
||||
state.value.quotaData = []
|
||||
})
|
||||
} else {
|
||||
state.value.dimension = []
|
||||
state.value.quota = []
|
||||
state.value.dimensionData = []
|
||||
state.value.quotaData = []
|
||||
}
|
||||
}
|
||||
const _popoverShow = ref(false)
|
||||
function onPopoverShow() {
|
||||
_popoverShow.value = true
|
||||
|
||||
@ -7,10 +7,11 @@ import cloneDeep from 'lodash-es/cloneDeep'
|
||||
import defaultsDeep from 'lodash-es/defaultsDeep'
|
||||
import { formatterType, unitType } from '../../../js/formatter'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import { differenceBy, partition } from 'lodash-es'
|
||||
import { partition } from 'lodash-es'
|
||||
import chartViewManager from '../../../js/panel'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -34,11 +35,10 @@ const toolTip = computed(() => {
|
||||
return props.themes === 'dark' ? 'ndark' : 'dark'
|
||||
})
|
||||
const emit = defineEmits(['onTooltipChange', 'onExtTooltipChange'])
|
||||
|
||||
const curSeriesFormatter = ref<DeepPartial<SeriesFormatter>>({})
|
||||
const quotaData = ref<Axis[]>(inject('quotaData'))
|
||||
const showSeriesTooltipFormatter = computed(() => {
|
||||
return showProperty('seriesTooltipFormatter') && !batchOptStatus.value
|
||||
return showProperty('seriesTooltipFormatter') && !batchOptStatus.value && props.chart.id
|
||||
})
|
||||
// 初始化系列提示
|
||||
const initSeriesTooltip = () => {
|
||||
@ -69,7 +69,7 @@ const initSeriesTooltip = () => {
|
||||
...next,
|
||||
seriesId: next.seriesId ?? next.id,
|
||||
show: index <= quotaAxis.value.length - 1,
|
||||
summary: 'sum'
|
||||
summary: COUNT_DE_TYPE.includes(next.deType) ? 'count' : 'sum'
|
||||
} as SeriesFormatter
|
||||
if (seriesAxisMap[tmp.seriesId]) {
|
||||
tmp = {
|
||||
@ -90,84 +90,15 @@ const initSeriesTooltip = () => {
|
||||
}
|
||||
curSeriesFormatter.value = axisMap[curSeriesFormatter.value.seriesId]
|
||||
}
|
||||
// 更新系列提示
|
||||
const updateSeriesTooltip = (newAxis?: SeriesFormatter[], oldAxis?: SeriesFormatter[]) => {
|
||||
if (
|
||||
!showSeriesTooltipFormatter.value ||
|
||||
!state.tooltipForm.seriesTooltipFormatter.length ||
|
||||
!quotaData.value?.length
|
||||
) {
|
||||
return
|
||||
}
|
||||
const axisMap: Record<string, Axis> = newAxis?.reduce((pre, next) => {
|
||||
pre[next.seriesId] = next
|
||||
return pre
|
||||
}, {})
|
||||
// 新增
|
||||
const addedAxisMap = differenceBy(newAxis, oldAxis, 'seriesId').reduce((pre, next) => {
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {}) as Record<string, SeriesFormatter>
|
||||
// 删除
|
||||
const removedAxisMap = differenceBy(oldAxis, newAxis, 'seriesId').reduce((pre, next) => {
|
||||
pre[next.seriesId] = next
|
||||
return pre
|
||||
}, {}) as Record<string, SeriesFormatter>
|
||||
const quotaIds = quotaData.value?.map(i => i.id)
|
||||
state.tooltipForm.seriesTooltipFormatter = state.tooltipForm.seriesTooltipFormatter?.filter(i =>
|
||||
quotaIds?.includes(i.id)
|
||||
)
|
||||
const dupAxis: SeriesFormatter[] = []
|
||||
state.tooltipForm.seriesTooltipFormatter?.forEach(ele => {
|
||||
if (addedAxisMap[ele.id]) {
|
||||
// 数据集中的字段
|
||||
ele.show = true
|
||||
if (ele.seriesId === ele.id) {
|
||||
ele.seriesId = addedAxisMap[ele.id].seriesId
|
||||
ele.axisType = addedAxisMap[ele.id].axisType
|
||||
} else {
|
||||
// 其他轴已有的字段
|
||||
const tmp = cloneDeep(addedAxisMap[ele.id])
|
||||
tmp.show = true
|
||||
dupAxis.push(tmp)
|
||||
}
|
||||
}
|
||||
if (removedAxisMap[ele.seriesId]) {
|
||||
ele.show = false
|
||||
ele.seriesId = ele.id
|
||||
}
|
||||
ele.chartShowName = axisMap[ele.seriesId]?.chartShowName
|
||||
ele.summary = axisMap[ele.seriesId]?.summary ?? ele.summary
|
||||
})
|
||||
// 重新排序
|
||||
state.tooltipForm.seriesTooltipFormatter =
|
||||
state.tooltipForm.seriesTooltipFormatter.concat(dupAxis)
|
||||
state.tooltipForm.seriesTooltipFormatter = partition(
|
||||
state.tooltipForm.seriesTooltipFormatter,
|
||||
ele => axisMap[ele.seriesId]
|
||||
).flat()
|
||||
if (removedAxisMap[curSeriesFormatter.value?.seriesId]) {
|
||||
curSeriesFormatter.value = state.tooltipForm.seriesTooltipFormatter?.[0]
|
||||
}
|
||||
if (!newAxis.length) {
|
||||
curSeriesFormatter.value = {}
|
||||
}
|
||||
emit('onTooltipChange', { data: state.tooltipForm, render: false })
|
||||
emit('onExtTooltipChange', extTooltip.value)
|
||||
}
|
||||
const AXIS_PROP: AxisType[] = ['yAxis', 'yAxisExt', 'extBubble']
|
||||
const quotaAxis = computed(() => {
|
||||
let result = []
|
||||
const axisProp: AxisType[] = ['yAxis', 'yAxisExt', 'extBubble']
|
||||
axisProp.forEach(prop => {
|
||||
AXIS_PROP.forEach(prop => {
|
||||
if (!chartViewInstance.value?.axis?.includes(prop)) {
|
||||
return
|
||||
}
|
||||
const axis = props.chart[prop]
|
||||
axis?.forEach(item => {
|
||||
item.axisType = prop
|
||||
item.seriesId = `${item.id}-${prop}`
|
||||
result.push(item)
|
||||
})
|
||||
axis?.forEach(item => result.push(item))
|
||||
})
|
||||
return result
|
||||
})
|
||||
@ -205,13 +136,18 @@ const AGGREGATION_TYPE = [
|
||||
{ name: t('chart.count'), value: 'count' },
|
||||
{ name: t('chart.count_distinct'), value: 'count_distinct' }
|
||||
]
|
||||
watch(
|
||||
() => cloneDeep(quotaAxis.value),
|
||||
(newVal, oldVal) => {
|
||||
updateSeriesTooltip(newVal, oldVal)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
const COUNT_AGGREGATION_TYPE = [
|
||||
{ name: t('chart.count'), value: 'count' },
|
||||
{ name: t('chart.count_distinct'), value: 'count_distinct' }
|
||||
]
|
||||
const COUNT_DE_TYPE = [0, 1, 5]
|
||||
|
||||
const aggregationList = computed(() => {
|
||||
if (COUNT_DE_TYPE.includes(curSeriesFormatter.value?.deType)) {
|
||||
return COUNT_AGGREGATION_TYPE
|
||||
}
|
||||
return AGGREGATION_TYPE
|
||||
})
|
||||
watch(
|
||||
[() => props.chart.customAttr.tooltip, () => props.chart.customAttr.tooltip.show],
|
||||
() => {
|
||||
@ -262,7 +198,13 @@ const init = () => {
|
||||
if (customAttr.tooltip) {
|
||||
state.tooltipForm = defaultsDeep(customAttr.tooltip, cloneDeep(DEFAULT_TOOLTIP))
|
||||
formatterSelector.value?.blur()
|
||||
// 新增视图
|
||||
const formatter = state.tooltipForm.seriesTooltipFormatter
|
||||
if (!formatter.length) {
|
||||
quotaData.value?.forEach(i => formatter.push({ ...i, seriesId: i.id, show: false }))
|
||||
curSeriesFormatter.value = {}
|
||||
return
|
||||
}
|
||||
const seriesAxisMap = formatter.reduce((pre, next) => {
|
||||
next.seriesId = next.seriesId ?? next.id
|
||||
pre[next.seriesId] = next
|
||||
@ -277,10 +219,138 @@ const init = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const showProperty = prop => props.propertyInner?.includes(prop)
|
||||
|
||||
const showProperty = prop => {
|
||||
const instance = chartViewManager.getChartView(props.chart.render, props.chart.type)
|
||||
if (instance) {
|
||||
return instance.propertyInner['tooltip-selector'].includes(prop)
|
||||
}
|
||||
return props.propertyInner?.includes(prop)
|
||||
}
|
||||
const updateSeriesTooltipFormatter = (form: AxisEditForm) => {
|
||||
const { axisType, editType } = form
|
||||
if (
|
||||
!showSeriesTooltipFormatter.value ||
|
||||
!state.tooltipForm.seriesTooltipFormatter.length ||
|
||||
!quotaData.value?.length ||
|
||||
!AXIS_PROP.includes(axisType)
|
||||
) {
|
||||
return
|
||||
}
|
||||
switch (editType) {
|
||||
case 'add':
|
||||
addAxis(form)
|
||||
break
|
||||
case 'remove':
|
||||
removeAxis(form)
|
||||
break
|
||||
case 'update':
|
||||
updateAxis(form)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
emit('onTooltipChange', { data: state.tooltipForm, render: false }, 'seriesTooltipFormatter')
|
||||
emit('onExtTooltipChange', extTooltip.value)
|
||||
}
|
||||
const addAxis = (form: AxisEditForm) => {
|
||||
const { axis, axisType } = form
|
||||
const axisMap = axis.reduce((pre, next) => {
|
||||
next.axisType = axisType
|
||||
next.seriesId = `${next.id}-${axisType}`
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {})
|
||||
const dupAxis = []
|
||||
state.tooltipForm.seriesTooltipFormatter.forEach(ele => {
|
||||
if (axisMap[ele.id]) {
|
||||
// 数据集中的字段
|
||||
ele.show = true
|
||||
if (ele.seriesId === ele.id) {
|
||||
ele.seriesId = axisMap[ele.id].seriesId
|
||||
ele.axisType = axisMap[ele.id].axisType
|
||||
ele.summary = axisMap[ele.id].summary
|
||||
ele.chartShowName = axisMap[ele.id].chartShowName
|
||||
} else {
|
||||
// 其他轴已有的字段
|
||||
const tmp = cloneDeep(axisMap[ele.id])
|
||||
tmp.show = true
|
||||
dupAxis.push(tmp)
|
||||
}
|
||||
}
|
||||
})
|
||||
state.tooltipForm.seriesTooltipFormatter =
|
||||
state.tooltipForm.seriesTooltipFormatter.concat(dupAxis)
|
||||
state.tooltipForm.seriesTooltipFormatter = partition(
|
||||
state.tooltipForm.seriesTooltipFormatter,
|
||||
ele => quotaAxis.value.findIndex(item => item.id === ele.id) !== -1
|
||||
).flat()
|
||||
}
|
||||
const removeAxis = (form: AxisEditForm) => {
|
||||
const { axis, axisType } = form
|
||||
const axisMap = axis.reduce((pre, next) => {
|
||||
if (!next) {
|
||||
return pre
|
||||
}
|
||||
next.axisType = axisType
|
||||
next.seriesId = `${next.id}-${axisType}`
|
||||
pre[next.seriesId] = next
|
||||
return pre
|
||||
}, {})
|
||||
const quotaIds = quotaData.value?.map(i => i.id)
|
||||
const formatterDupMap = state.tooltipForm.seriesTooltipFormatter.reduce((pre, next) => {
|
||||
if (pre[next.id] !== undefined) {
|
||||
pre[`${next.id}-${axisType}`] = true
|
||||
} else {
|
||||
pre[next.id] = false
|
||||
}
|
||||
return pre
|
||||
}, {})
|
||||
state.tooltipForm.seriesTooltipFormatter = state.tooltipForm.seriesTooltipFormatter?.filter(
|
||||
i => quotaIds?.includes(i.id) && !formatterDupMap[i.seriesId]
|
||||
)
|
||||
state.tooltipForm.seriesTooltipFormatter.forEach(ele => {
|
||||
if (axisMap[ele.seriesId]) {
|
||||
// 数据集中的字段
|
||||
ele.show = false
|
||||
ele.seriesId = ele.id
|
||||
ele.summary = 'sum'
|
||||
}
|
||||
})
|
||||
state.tooltipForm.seriesTooltipFormatter = partition(
|
||||
state.tooltipForm.seriesTooltipFormatter,
|
||||
ele => quotaAxis.value.findIndex(item => item.id === ele.id) !== -1
|
||||
).flat()
|
||||
if (!quotaAxis.value?.length) {
|
||||
curSeriesFormatter.value = {}
|
||||
return
|
||||
}
|
||||
if (axisMap[curSeriesFormatter.value?.seriesId]) {
|
||||
curSeriesFormatter.value = state.tooltipForm.seriesTooltipFormatter?.[0]
|
||||
}
|
||||
}
|
||||
const updateAxis = (form: AxisEditForm) => {
|
||||
const { axis, axisType } = form
|
||||
const axisMap = axis.reduce((pre, next) => {
|
||||
if (!next) {
|
||||
return pre
|
||||
}
|
||||
next.axisType = axisType
|
||||
next.seriesId = `${next.id}-${axisType}`
|
||||
pre[next.seriesId] = next
|
||||
return pre
|
||||
}, {})
|
||||
state.tooltipForm.seriesTooltipFormatter.forEach(ele => {
|
||||
if (axisMap[ele.seriesId]) {
|
||||
ele.chartShowName = axisMap[ele.seriesId]?.chartShowName
|
||||
ele.summary = axisMap[ele.seriesId]?.summary ?? ele.summary
|
||||
}
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
useEmitt({ name: 'addAxis', callback: updateSeriesTooltipFormatter })
|
||||
useEmitt({ name: 'removeAxis', callback: updateSeriesTooltipFormatter })
|
||||
useEmitt({ name: 'updateAxis', callback: updateSeriesTooltipFormatter })
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -482,10 +552,11 @@ onMounted(() => {
|
||||
<template v-if="curSeriesFormatter?.seriesId">
|
||||
<el-form-item class="form-item form-item-checkbox" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
@change="changeTooltipAttr('seriesTooltipFormatter', true)"
|
||||
:disabled="!formatterEditable"
|
||||
v-model="curSeriesFormatter.show"
|
||||
size="small"
|
||||
label="quota"
|
||||
@change="changeTooltipAttr('seriesTooltipFormatter', true)"
|
||||
>
|
||||
{{ t('chart.show') }}
|
||||
</el-checkbox>
|
||||
@ -520,7 +591,7 @@ onMounted(() => {
|
||||
@change="changeTooltipAttr('seriesTooltipFormatter', true)"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in AGGREGATION_TYPE"
|
||||
v-for="item in aggregationList"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
:key="item.value"
|
||||
|
||||
@ -15,7 +15,6 @@ import {
|
||||
import Icon from '@/components/icon-custom/src/Icon.vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus-secondary'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { Field, getFieldByDQ } from '@/api/chart'
|
||||
import { Tree } from '../../../visualized/data/dataset/form/CreatDsGroup.vue'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { ElMessage, ElTreeSelect } from 'element-plus-secondary'
|
||||
@ -43,13 +42,14 @@ import CustomSortEdit from '@/views/chart/components/editor/drag-item/components
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import CalcFieldEdit from '@/views/visualized/data/dataset/form/CalcFieldEdit.vue'
|
||||
import { getFieldName, guid } from '@/views/visualized/data/dataset/form/util'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { cloneDeep, get } from 'lodash-es'
|
||||
import { deleteField, saveField } from '@/api/dataset'
|
||||
import { getWorldTree } from '@/api/map'
|
||||
import chartViewManager from '@/views/chart/components/js/panel'
|
||||
import DatasetSelect from '@/views/chart/components/editor/dataset-select/DatasetSelect.vue'
|
||||
import { useDraggable } from '@vueuse/core'
|
||||
import _ from 'lodash'
|
||||
import { set, concat, keys } from 'lodash-es'
|
||||
import { Field, getFieldByDQ } from '@/api/chart'
|
||||
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
@ -63,7 +63,7 @@ const tabActiveVQuery = ref('style')
|
||||
const datasetSelector = ref(null)
|
||||
const curDatasetWeight = ref(0)
|
||||
const renameForm = ref<FormInstance>()
|
||||
|
||||
const { emitter } = useEmitt()
|
||||
const props = defineProps({
|
||||
view: {
|
||||
type: Object as PropType<ChartObj>,
|
||||
@ -144,17 +144,10 @@ const state = reactive({
|
||||
useless: null
|
||||
})
|
||||
|
||||
watch(
|
||||
[() => props.view.tableId],
|
||||
() => {
|
||||
getFields(props.view.tableId, props.view.id)
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
[() => view.value['tableId']],
|
||||
() => {
|
||||
getFields(props.view.tableId, props.view.id)
|
||||
const nodeId = view.value['tableId']
|
||||
if (!!nodeId) {
|
||||
cacheId = nodeId as unknown as string
|
||||
@ -166,7 +159,28 @@ watch(
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
const getFields = (id, chartId) => {
|
||||
if (id && chartId) {
|
||||
getFieldByDQ(id, chartId)
|
||||
.then(res => {
|
||||
state.dimension = (res.dimensionList as unknown as Field[]) || []
|
||||
state.quota = (res.quotaList as unknown as Field[]) || []
|
||||
state.dimensionData = JSON.parse(JSON.stringify(state.dimension))
|
||||
state.quotaData = JSON.parse(JSON.stringify(state.quota))
|
||||
})
|
||||
.catch(() => {
|
||||
state.dimension = []
|
||||
state.quota = []
|
||||
state.dimensionData = []
|
||||
state.quotaData = []
|
||||
})
|
||||
} else {
|
||||
state.dimension = []
|
||||
state.quota = []
|
||||
state.dimensionData = []
|
||||
state.quotaData = []
|
||||
}
|
||||
}
|
||||
watch(
|
||||
[() => state.searchField],
|
||||
newVal => {
|
||||
@ -222,31 +236,8 @@ const filterNode = (value, data) => {
|
||||
return data.name?.includes(value)
|
||||
}
|
||||
|
||||
const getFields = (id, chartId) => {
|
||||
if (id && chartId) {
|
||||
getFieldByDQ(id, chartId)
|
||||
.then(res => {
|
||||
state.dimension = (res.dimensionList as unknown as Field[]) || []
|
||||
state.quota = (res.quotaList as unknown as Field[]) || []
|
||||
state.dimensionData = JSON.parse(JSON.stringify(state.dimension))
|
||||
state.quotaData = JSON.parse(JSON.stringify(state.quota))
|
||||
})
|
||||
.catch(() => {
|
||||
state.dimension = []
|
||||
state.quota = []
|
||||
state.dimensionData = []
|
||||
state.quotaData = []
|
||||
})
|
||||
} else {
|
||||
state.dimension = []
|
||||
state.quota = []
|
||||
state.dimensionData = []
|
||||
state.quotaData = []
|
||||
}
|
||||
}
|
||||
|
||||
const allFields = computed(() => {
|
||||
return _.concat(state.quotaData, state.dimensionData)
|
||||
return concat(state.quotaData, state.dimensionData)
|
||||
})
|
||||
|
||||
const queryList = computed(() => {
|
||||
@ -266,9 +257,9 @@ const queryList = computed(() => {
|
||||
|
||||
const quotaData = computed(() => {
|
||||
if (view.value?.type === 'table-info') {
|
||||
return state.quotaData?.filter(item => item.id !== '-1')
|
||||
return state.quota?.filter(item => item.id !== '-1')
|
||||
}
|
||||
return state.quotaData
|
||||
return state.quota
|
||||
})
|
||||
provide('quotaData', quotaData)
|
||||
|
||||
@ -313,23 +304,29 @@ const dimensionItemRemove = item => {
|
||||
}
|
||||
}
|
||||
|
||||
const quotaItemChange = () => {
|
||||
const quotaItemChange = (axis: Axis, axisType: AxisType) => {
|
||||
recordSnapshotInfo('calcData')
|
||||
// do quotaItemChange
|
||||
emitter.emit('updateAxis', { axisType, axis: [axis], editType: 'update' })
|
||||
}
|
||||
const quotaItemRemove = item => {
|
||||
recordSnapshotInfo('calcData')
|
||||
let axisType: AxisType = item.removeType
|
||||
let axis
|
||||
if (item.removeType === 'quota') {
|
||||
view.value.yAxis.splice(item.index, 1)
|
||||
axisType = 'yAxis'
|
||||
axis = view.value.yAxis.splice(item.index, 1)
|
||||
} else if (item.removeType === 'quotaExt') {
|
||||
view.value.yAxisExt.splice(item.index, 1)
|
||||
axisType = 'yAxisExt'
|
||||
axis = view.value.yAxisExt.splice(item.index, 1)
|
||||
} else if (item.removeType === 'extLabel') {
|
||||
view.value.extLabel.splice(item.index, 1)
|
||||
axis = view.value.extLabel.splice(item.index, 1)
|
||||
} else if (item.removeType === 'extTooltip') {
|
||||
view.value.extTooltip.splice(item.index, 1)
|
||||
axis = view.value.extTooltip.splice(item.index, 1)
|
||||
} else if (item.removeType === 'extBubble') {
|
||||
view.value.extBubble.splice(item.index, 1)
|
||||
axis = view.value.extBubble.splice(item.index, 1)
|
||||
}
|
||||
useEmitt().emitter.emit('removeAxis', { axisType, axis, editType: 'remove' })
|
||||
}
|
||||
const arrowIcon = () => {
|
||||
return h(Icon, { name: 'icon_down_outlined-1' })
|
||||
@ -394,7 +391,7 @@ const onMove = e => {
|
||||
// drag
|
||||
const dragCheckType = (list, type) => {
|
||||
if (list && list.length > 0) {
|
||||
var valid = true
|
||||
let valid = true
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].groupType !== type) {
|
||||
list.splice(i, 1)
|
||||
@ -407,6 +404,7 @@ const dragCheckType = (list, type) => {
|
||||
type: 'warning'
|
||||
})
|
||||
}
|
||||
return valid
|
||||
}
|
||||
}
|
||||
const dragMoveDuplicate = (list, e, mode) => {
|
||||
@ -418,6 +416,7 @@ const dragMoveDuplicate = (list, e, mode) => {
|
||||
})
|
||||
if (dup && dup.length > 1) {
|
||||
list.splice(e.newDraggableIndex, 1)
|
||||
return dup
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -439,14 +438,37 @@ const addAxis = (e, axis: AxisType) => {
|
||||
return
|
||||
}
|
||||
const { type, limit, duplicate } = axisSpec
|
||||
let typeValid, dup
|
||||
if (type) {
|
||||
dragCheckType(view.value[axis], type)
|
||||
typeValid = dragCheckType(view.value[axis], type)
|
||||
}
|
||||
if (!duplicate) {
|
||||
dragMoveDuplicate(view.value[axis], e, 'chart')
|
||||
dup = dragMoveDuplicate(view.value[axis], e, 'chart')
|
||||
}
|
||||
if (limit) {
|
||||
view.value[axis] = view.value[axis].splice(0, limit)
|
||||
if (view.value[axis].length > limit) {
|
||||
const removedAxis = view.value[axis].splice(limit)
|
||||
if (e.newDraggableIndex + 1 <= limit) {
|
||||
emitter.emit('removeAxis', { axisType: axis, axis: removedAxis, editType: 'remove' })
|
||||
emitter.emit('addAxis', {
|
||||
axisType: axis,
|
||||
axis: [view.value[axis][e.newDraggableIndex]],
|
||||
editType: 'add'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
if (!dup && typeValid) {
|
||||
emitter.emit('addAxis', {
|
||||
axisType: axis,
|
||||
axis: [view.value[axis][e.newDraggableIndex]],
|
||||
editType: 'add'
|
||||
})
|
||||
}
|
||||
}
|
||||
if (view.value.type === 'line') {
|
||||
if (view.value?.xAxisExt?.length && view.value?.yAxis?.length > 1) {
|
||||
const axis = view.value.yAxis.splice(1)
|
||||
emitter.emit('removeAxis', { axisType: 'yAxis', axis, editType: 'remove' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,6 +527,13 @@ const moveToQuota = e => {
|
||||
dragMoveDuplicate(state.quotaData, e, 'ds')
|
||||
}
|
||||
|
||||
const onAxisChange = (e, axis: AxisType) => {
|
||||
if (e.removed) {
|
||||
const { element } = e.removed
|
||||
emitter.emit('removeAxis', { axisType: axis, axis: [element], editType: 'remove' })
|
||||
}
|
||||
}
|
||||
|
||||
const calcData = (view, resetDrill = false, updateQuery = '') => {
|
||||
if (
|
||||
view.refreshTime === '' ||
|
||||
@ -551,26 +580,36 @@ const onTypeChange = (render, type) => {
|
||||
view.value = chartViewInstance.setupDefaultOptions(view.value) as unknown as ChartObj
|
||||
// 处理轴
|
||||
const axisConfig = chartViewInstance.axisConfig
|
||||
_.keys(axisConfig).forEach((axis: AxisType) => {
|
||||
keys(axisConfig).forEach((axis: AxisType) => {
|
||||
const axisArr = view.value[axis] as Axis[]
|
||||
if (!axisArr?.length) {
|
||||
return
|
||||
}
|
||||
const axisSpec = axisConfig[axis]
|
||||
const { type, limit } = axisSpec
|
||||
const removedAxis = []
|
||||
// check type
|
||||
if (type) {
|
||||
for (let i = axisArr.length - 1; i >= 0; i--) {
|
||||
if (axisArr[i].groupType !== type) {
|
||||
axisArr.splice(i, 1)
|
||||
const [axis] = axisArr.splice(i, 1)
|
||||
removedAxis.push(axis)
|
||||
}
|
||||
}
|
||||
}
|
||||
// check limit
|
||||
if (limit && axisArr.length) {
|
||||
axisArr.splice(0, axisArr.length - limit)
|
||||
if (limit && limit < axisArr.length) {
|
||||
axisArr.splice(limit).forEach(i => removedAxis.push(i))
|
||||
}
|
||||
removedAxis.length &&
|
||||
emitter.emit('removeAxis', { axisType: axis, axis: removedAxis, editType: 'remove' })
|
||||
})
|
||||
if (view.value.type === 'line') {
|
||||
if (view.value?.xAxisExt?.length && view.value?.yAxis?.length > 1) {
|
||||
const axis = view.value.yAxis.splice(1)
|
||||
emitter.emit('removeAxis', { axisType: 'yAxis', axis, editType: 'remove' })
|
||||
}
|
||||
}
|
||||
}
|
||||
curComponent.value.innerType = type
|
||||
calcData(view.value, true)
|
||||
@ -617,23 +656,22 @@ const onLabelChange = val => {
|
||||
view.value.customAttr.label = val
|
||||
renderChart(view.value)
|
||||
}
|
||||
watch([() => view.value.xAxisExt?.length, () => view.value.yAxis?.length], () => {
|
||||
if (view.value.type === 'line') {
|
||||
if (view.value?.xAxisExt?.length && view.value?.yAxis?.length > 1) {
|
||||
view.value.yAxis.splice(1)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const onTooltipChange = (chartForm: ChartEditorForm<ChartTooltipAttr>) => {
|
||||
const onTooltipChange = (chartForm: ChartEditorForm<ChartTooltipAttr>, prop: string) => {
|
||||
const { data, requestData, render } = chartForm
|
||||
let tooltipObj = data
|
||||
if (!data) {
|
||||
view.value.customAttr.tooltip = chartForm as unknown as ChartTooltipAttr
|
||||
tooltipObj = chartForm as unknown as ChartTooltipAttr
|
||||
}
|
||||
if (prop) {
|
||||
const val = get(tooltipObj, prop)
|
||||
set(view.value.customAttr.tooltip, prop, val)
|
||||
} else {
|
||||
view.value.customAttr.tooltip = data
|
||||
view.value.customAttr.tooltip = tooltipObj
|
||||
}
|
||||
if (requestData) {
|
||||
calcData(view.value)
|
||||
return
|
||||
}
|
||||
// for compatibility
|
||||
if (render !== false) {
|
||||
@ -716,29 +754,31 @@ const removeItems = (
|
||||
_type: 'xAxis' | 'xAxisExt' | 'extStack' | 'yAxis' | 'extBubble' | 'customFilter' | 'drillFields'
|
||||
) => {
|
||||
recordSnapshotInfo('calcData')
|
||||
let axis = []
|
||||
switch (_type) {
|
||||
case 'xAxis':
|
||||
view.value.xAxis = []
|
||||
axis = view.value.xAxis?.splice(0)
|
||||
break
|
||||
case 'xAxisExt':
|
||||
view.value.xAxisExt = []
|
||||
axis = view.value.xAxisExt?.splice(0)
|
||||
break
|
||||
case 'extStack':
|
||||
view.value.extStack = []
|
||||
axis = view.value.extStack?.splice(0)
|
||||
break
|
||||
case 'yAxis':
|
||||
view.value.yAxis = []
|
||||
axis = view.value.yAxis?.splice(0)
|
||||
break
|
||||
case 'extBubble':
|
||||
view.value.extBubble = []
|
||||
axis = view.value.extBubble?.splice(0)
|
||||
break
|
||||
case 'customFilter':
|
||||
view.value.customFilter = []
|
||||
axis = view.value.customFilter?.splice(0)
|
||||
break
|
||||
case 'drillFields':
|
||||
view.value.drillFields = []
|
||||
axis = view.value.drillFields?.splice(0)
|
||||
break
|
||||
}
|
||||
axis?.length && emitter.emit('removeAxis', { axisType: _type, axis, editType: 'remove' })
|
||||
}
|
||||
|
||||
const saveRename = ref => {
|
||||
@ -746,14 +786,19 @@ const saveRename = ref => {
|
||||
ref.validate(valid => {
|
||||
if (valid) {
|
||||
const { renameType, index, chartShowName } = state.itemForm
|
||||
let axisType, axis
|
||||
switch (renameType) {
|
||||
case 'quota':
|
||||
axisType = 'yAxis'
|
||||
axis = view.value.yAxis[index]
|
||||
view.value.yAxis[index].chartShowName = chartShowName
|
||||
break
|
||||
case 'dimension':
|
||||
view.value.xAxis[index].chartShowName = chartShowName
|
||||
break
|
||||
case 'quotaExt':
|
||||
axisType = 'yAxisExt'
|
||||
axis = view.value.yAxisExt[index]
|
||||
view.value.yAxisExt[index].chartShowName = chartShowName
|
||||
break
|
||||
case 'dimensionExt':
|
||||
@ -763,6 +808,8 @@ const saveRename = ref => {
|
||||
view.value.extStack[index].chartShowName = chartShowName
|
||||
break
|
||||
case 'extBubble':
|
||||
axisType = 'extBubble'
|
||||
axis = view.value.extBubble[index]
|
||||
view.value.extBubble[index].chartShowName = chartShowName
|
||||
break
|
||||
case 'extLabel':
|
||||
@ -774,6 +821,7 @@ const saveRename = ref => {
|
||||
default:
|
||||
break
|
||||
}
|
||||
axisType && emitter.emit('updateAxis', { axisType, axis: [axis], editType: 'update' })
|
||||
closeRename()
|
||||
} else {
|
||||
return false
|
||||
@ -1356,6 +1404,7 @@ const onRefreshChange = val => {
|
||||
class="drag-block-style"
|
||||
:class="{ dark: themes === 'dark' }"
|
||||
@add="addYaxis"
|
||||
@change="e => onAxisChange(e, 'yAxis')"
|
||||
>
|
||||
<template #item="{ element, index }">
|
||||
<quota-item
|
||||
@ -1366,7 +1415,7 @@ const onRefreshChange = val => {
|
||||
:index="index"
|
||||
type="quota"
|
||||
:themes="props.themes"
|
||||
@onQuotaItemChange="quotaItemChange"
|
||||
@onQuotaItemChange="item => quotaItemChange(item, 'yAxis')"
|
||||
@onQuotaItemRemove="quotaItemRemove"
|
||||
@onNameEdit="showRename"
|
||||
@editItemFilter="showQuotaEditFilter"
|
||||
@ -1403,6 +1452,7 @@ const onRefreshChange = val => {
|
||||
class="drag-block-style"
|
||||
:class="{ dark: themes === 'dark' }"
|
||||
@add="addExtBubble"
|
||||
@change="e => onAxisChange(e, 'extBubble')"
|
||||
>
|
||||
<template #item="{ element, index }">
|
||||
<quota-item
|
||||
@ -1413,7 +1463,7 @@ const onRefreshChange = val => {
|
||||
:index="index"
|
||||
type="extBubble"
|
||||
:themes="props.themes"
|
||||
@onQuotaItemChange="quotaItemChange"
|
||||
@onQuotaItemChange="item => quotaItemChange(item, 'extBubble')"
|
||||
@onQuotaItemRemove="quotaItemRemove"
|
||||
@onNameEdit="showRename"
|
||||
@editItemFilter="showQuotaEditFilter"
|
||||
|
||||
@ -116,6 +116,7 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {})
|
||||
// 默认是灰色
|
||||
tmpOptions.label.style.fill = DEFAULT_LABEL.color
|
||||
const label = {
|
||||
fields: [],
|
||||
@ -242,6 +243,7 @@ export class StackBar extends Bar {
|
||||
return baseOptions
|
||||
}
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum) {
|
||||
|
||||
@ -164,11 +164,12 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
}
|
||||
|
||||
setupDefaultOptions(chart: ChartObj): ChartObj {
|
||||
const { customAttr } = chart
|
||||
const { customAttr, senior } = chart
|
||||
const { label } = customAttr
|
||||
if (!['left', 'middle', 'right'].includes(label.position)) {
|
||||
label.position = 'middle'
|
||||
}
|
||||
senior.functionCfg.emptyDataStrategy = 'ignoreData'
|
||||
return chart
|
||||
}
|
||||
|
||||
@ -185,6 +186,7 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
pre[next.id] = next
|
||||
return pre
|
||||
}, {})
|
||||
// 默认灰色
|
||||
tmpOptions.label.style.fill = DEFAULT_LABEL.color
|
||||
const label = {
|
||||
fields: [],
|
||||
@ -272,6 +274,7 @@ export class HorizontalStackBar extends HorizontalBar {
|
||||
return baseOptions
|
||||
}
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum) {
|
||||
|
||||
@ -78,7 +78,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
const options = this.setupOptions(chart, initOptions)
|
||||
const newChart = new G2WordCloud(container, options)
|
||||
newChart.on('point:click', param => {
|
||||
action({ data: { data: param.data.data.datum } })
|
||||
action({ x: param.x, y: param.y, data: { data: param.data.data.datum } })
|
||||
})
|
||||
return newChart
|
||||
}
|
||||
|
||||
@ -253,9 +253,8 @@ export function handleEmptyDataStrategy<O extends PickOptions>(chart: Chart, opt
|
||||
handleIgnoreData(data)
|
||||
return options
|
||||
}
|
||||
const yAxis = JSON.parse(JSON.stringify(chart.yAxis))
|
||||
const extAxis = JSON.parse(JSON.stringify(chart.xAxisExt))
|
||||
const multiDimension = yAxis?.length >= 2 || extAxis?.length > 0
|
||||
const { yAxis, xAxisExt, extStack } = chart
|
||||
const multiDimension = yAxis?.length >= 2 || xAxisExt?.length > 0 || extStack?.length > 0
|
||||
switch (strategy) {
|
||||
case 'breakLine': {
|
||||
if (multiDimension) {
|
||||
|
||||
@ -434,7 +434,7 @@ onMounted(() => {
|
||||
}
|
||||
})
|
||||
useEmitt({
|
||||
name: 'calc-data-' + view.value.id,
|
||||
name: 'calcData-' + view.value.id,
|
||||
callback: function (val) {
|
||||
if (!state.initReady) {
|
||||
return
|
||||
|
||||
@ -311,8 +311,7 @@ defineExpose({
|
||||
</el-tooltip>
|
||||
<el-tooltip :content="newResourceLabel" placement="top" effect="dark">
|
||||
<el-icon class="custom-icon btn" @click="addOperation('newLeaf', null, 'leaf', true)">
|
||||
<Icon v-if="curCanvasType === 'dashboard'" name="dv-new"></Icon>
|
||||
<Icon v-else name="dv-screen-new" />
|
||||
<Icon name="icon_file-add_outlined" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
@ -40,7 +40,7 @@ const handleClick = (tab, event: Event) => {
|
||||
.sys-setting-p {
|
||||
width: 100%;
|
||||
background: var(--ContentBG, #ffffff);
|
||||
height: calc(100% - 95px);
|
||||
height: calc(100vh - 176px);
|
||||
box-sizing: border-box;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-container class="geometry-container">
|
||||
<el-aside width="200px" class="geonetry-aside">
|
||||
<el-aside class="geonetry-aside">
|
||||
<div class="geo-title">
|
||||
<span>{{ t('online_map.geometry') }}</span>
|
||||
<span class="add-icon-span">
|
||||
@ -10,7 +10,13 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="geo-search">
|
||||
<el-input class="m16 w100" v-model="keyword" clearable :placeholder="t('commons.search')">
|
||||
<el-input
|
||||
class="m16 w100"
|
||||
v-model="keyword"
|
||||
clearable
|
||||
:placeholder="t('commons.search')"
|
||||
@change="filterResource"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon>
|
||||
<Icon name="icon_search-outline_outlined"></Icon>
|
||||
@ -19,90 +25,118 @@
|
||||
</el-input>
|
||||
</div>
|
||||
<div class="map-tree-container">
|
||||
<el-tree :data="data" :props="defaultProps" @node-click="handleNodeClick" />
|
||||
<el-scrollbar class="menu-tree">
|
||||
<el-tree
|
||||
menu
|
||||
ref="areaTreeRef"
|
||||
node-key="id"
|
||||
:data="treeData"
|
||||
@node-click="handleNodeClick"
|
||||
:highlight-current="true"
|
||||
:expand-on-click-node="false"
|
||||
:default-expand-all="false"
|
||||
:filter-node-method="filterResourceNode"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span class="custom-tree-node" :class="{ 'is-disabled': node.disabled || data.root }">
|
||||
<span
|
||||
:title="data.name"
|
||||
v-html="data.colorName && keyword ? data.colorName : data.name"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-main>地理信息内容区域</el-main>
|
||||
<el-main class="geometry-main">
|
||||
<div class="geo-content-container" v-if="!selectedData">
|
||||
<EmptyBackground img-type="noneWhite" description="请在左侧选择区域" />
|
||||
</div>
|
||||
<div v-else class="geo-content-container">
|
||||
<div class="geo-content-top">
|
||||
<span>{{ selectedData.name }}</span>
|
||||
</div>
|
||||
<div class="geo-content-middle">
|
||||
<div class="geo-area">
|
||||
<div class="area-label"><span>区域代码</span></div>
|
||||
<div class="area-content">
|
||||
<span>{{ selectedData.id }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="geo-area">
|
||||
<div class="area-label"><span>上级区域</span></div>
|
||||
<div class="area-content">
|
||||
<span>{{ selectedData.parentName }}</span>
|
||||
<span v-if="selectedData.pid" class="area-secondary">{{
|
||||
'(' + selectedData.pid + ')'
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="geo-content-bottom">
|
||||
<div class="area-label"><span>坐标文件</span></div>
|
||||
<el-scrollbar class="area-content-geo">
|
||||
<span>{{ selectedData.geoJson }}</span>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { getWorldTree } from '@/api/map'
|
||||
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
|
||||
import { getGeoJsonFile } from '@/views/chart/components/js/util'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { setColorName } from '@/utils/utils'
|
||||
const { t } = useI18n()
|
||||
const keyword = ref('')
|
||||
|
||||
const treeData = ref([])
|
||||
interface Tree {
|
||||
label: string
|
||||
children?: Tree[]
|
||||
}
|
||||
const areaTreeRef = ref(null)
|
||||
|
||||
const handleNodeClick = (data: Tree) => {
|
||||
console.log(data)
|
||||
}
|
||||
const selectedData = ref(null)
|
||||
|
||||
const data: Tree[] = [
|
||||
{
|
||||
label: 'Level one 1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 1-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 1-1-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Level one 2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 2-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 2-1-1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Level two 2-2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 2-2-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Level one 3',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 3-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 3-1-1'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Level two 3-2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 3-2-1'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
const handleNodeClick = async (data: Tree) => {
|
||||
selectedData.value = data
|
||||
const geoJson = cloneDeep(await getGeoJsonFile(data['id']))
|
||||
selectedData.value['geoJson'] = geoJson
|
||||
const pid = data['pid']
|
||||
if (pid) {
|
||||
const parent = areaTreeRef.value.getNode(pid)
|
||||
if (parent) {
|
||||
selectedData.value.parentName = parent.data.name
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label'
|
||||
}
|
||||
const filterResource = val => {
|
||||
areaTreeRef.value?.filter(val)
|
||||
}
|
||||
const filterResourceNode = (value: string, data) => {
|
||||
setColorName(data, value)
|
||||
if (!value) return true
|
||||
return data.name.toLocaleLowerCase().includes(value.toLocaleLowerCase())
|
||||
}
|
||||
|
||||
const loadTreeData = () => {
|
||||
getWorldTree()
|
||||
.then(res => {
|
||||
const root = res.data
|
||||
treeData.value = [root]
|
||||
})
|
||||
.catch(e => {
|
||||
console.error(e)
|
||||
})
|
||||
}
|
||||
|
||||
loadTreeData()
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@ -112,6 +146,7 @@ const defaultProps = {
|
||||
width: 280px !important;
|
||||
border-right: 1px solid #1f232926;
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
.geo-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@ -123,6 +158,7 @@ const defaultProps = {
|
||||
line-height: 24px;
|
||||
}
|
||||
.add-icon-span {
|
||||
display: none;
|
||||
color: #3370ff;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
@ -140,6 +176,79 @@ const defaultProps = {
|
||||
.geo-search {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.map-tree-container {
|
||||
height: calc(100% - 96px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
.geometry-main {
|
||||
padding: 16px !important;
|
||||
}
|
||||
}
|
||||
.geo-content-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.geo-content-top {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
margin-bottom: 16px;
|
||||
span {
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
color: #1f2329;
|
||||
}
|
||||
}
|
||||
.geo-content-middle {
|
||||
display: flex;
|
||||
.geo-area {
|
||||
height: 48px;
|
||||
width: 50%;
|
||||
}
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
:deep(.area-label) {
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: #646a73;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
:deep(.area-content) {
|
||||
line-height: 22px;
|
||||
height: 22px;
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: #1f2329;
|
||||
font-weight: 400;
|
||||
}
|
||||
.area-secondary {
|
||||
color: #646a73;
|
||||
}
|
||||
}
|
||||
.geo-content-bottom {
|
||||
width: 100%;
|
||||
height: calc(100% - 110px);
|
||||
.area-content-geo {
|
||||
line-height: 22px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
height: calc(100% - 30px);
|
||||
span {
|
||||
font-size: 14px;
|
||||
color: #1f2329;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.custom-tree-node {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-sizing: content-box;
|
||||
padding-right: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -443,7 +443,7 @@ const filterNode = (value: string, data: BusiTreeNode) => {
|
||||
</el-tooltip>
|
||||
<el-tooltip class="box-item" effect="dark" content="新建数据集" placement="top">
|
||||
<el-icon class="custom-icon btn" @click="createDataset">
|
||||
<Icon name="icon_dataset_outlined" />
|
||||
<Icon name="icon_file-add_outlined" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
@ -614,6 +614,18 @@ defineExpose({
|
||||
autocomplete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('datasource.port')" prop="configuration.port">
|
||||
<el-input-number
|
||||
v-model="form.configuration.port"
|
||||
autocomplete="off"
|
||||
step-strictly
|
||||
class="text-left"
|
||||
:min="0"
|
||||
:placeholder="t('common.inputText') + t('datasource.port')"
|
||||
controls-position="right"
|
||||
type="number"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('datasource.data_base')" prop="configuration.dataBase">
|
||||
<el-input
|
||||
v-model="form.configuration.dataBase"
|
||||
@ -687,18 +699,6 @@ defineExpose({
|
||||
autocomplete="off"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="t('datasource.port')" prop="configuration.port">
|
||||
<el-input-number
|
||||
v-model="form.configuration.port"
|
||||
autocomplete="off"
|
||||
step-strictly
|
||||
class="text-left"
|
||||
:min="0"
|
||||
:placeholder="t('common.inputText') + t('datasource.port')"
|
||||
controls-position="right"
|
||||
type="number"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.type == 'oracle'"
|
||||
:label="t('datasource.connection_mode')"
|
||||
|
||||
@ -654,7 +654,7 @@ onMounted(() => {
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" :content="t('datasource.create')" placement="top">
|
||||
<el-icon class="custom-icon btn" @click="createDatasource">
|
||||
<Icon name="icon_dataset_outlined" />
|
||||
<Icon name="icon_file-add_outlined" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
@ -336,8 +336,9 @@ const getEmptyDesc = (): string => {
|
||||
padding: 8px 24px 0 24px;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
height: calc(100% - 280px);
|
||||
margin-top: 16px;
|
||||
// height: calc(100% - 280px);
|
||||
// margin-top: 16px;
|
||||
height: 100%;
|
||||
|
||||
.select-type-list {
|
||||
width: 104px;
|
||||
|
||||
@ -17,6 +17,8 @@ const { t } = useI18n()
|
||||
const busiDataMap = computed(() => interactiveStore.getData)
|
||||
const busiCountCardList = ref([])
|
||||
|
||||
const showTemplate = ref(false)
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const quickCreationList = shallowRef([
|
||||
@ -159,7 +161,7 @@ fillCardInfo()
|
||||
</div>
|
||||
</div>
|
||||
<div class="template-market-dashboard">
|
||||
<div class="template-market">
|
||||
<div v-if="showTemplate" class="template-market">
|
||||
<div class="label">
|
||||
模版市场
|
||||
<div class="expand-all">
|
||||
|
||||
2
de-xpack
2
de-xpack
@ -1 +1 @@
|
||||
Subproject commit 1ca8187376d058b65d163dbad52ff6159ca024f3
|
||||
Subproject commit 912a648808e87bdf1e5a11f7cdc6467b89fd9347
|
||||
@ -1,4 +1,4 @@
|
||||
pisix:
|
||||
apisix:
|
||||
node_listen: 9080 # APISIX listening port
|
||||
enable_ipv6: false
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ version: "3"
|
||||
|
||||
services:
|
||||
apisix-dashboard:
|
||||
image: apache/apisix-dashboard:3.0.1-alpine
|
||||
image: registry.cn-qingdao.aliyuncs.com/dataease/apisix-dashboard:3.0.1-alpine
|
||||
container_name: apisix-dashboard
|
||||
restart: always
|
||||
volumes:
|
||||
@ -13,7 +13,7 @@ services:
|
||||
dataease-network:
|
||||
|
||||
apisix:
|
||||
image: apache/apisix:3.4.1-debian
|
||||
image: registry.cn-qingdao.aliyuncs.com/dataease/apisix:3.6.0-debian
|
||||
container_name: apisix
|
||||
environment:
|
||||
- TZ=Asia/Shanghai
|
||||
@ -33,7 +33,7 @@ services:
|
||||
dataease-network:
|
||||
|
||||
etcd:
|
||||
image: bitnami/etcd:3.4.15
|
||||
image: registry.cn-qingdao.aliyuncs.com/dataease/etcd:3.5.10
|
||||
container_name: apisix-etcd
|
||||
restart: always
|
||||
volumes:
|
||||
|
||||
@ -2,7 +2,7 @@ version: '2.1'
|
||||
services:
|
||||
|
||||
DE_MYSQL_HOST:
|
||||
image: mysql:8.1.0
|
||||
image: registry.cn-qingdao.aliyuncs.com/dataease/mysql:8.1.0
|
||||
container_name: ${DE_MYSQL_HOST}
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-u${DE_MYSQL_USER}", "-p${DE_MYSQL_PASSWORD}", "--protocol","tcp"]
|
||||
|
||||
@ -2,7 +2,7 @@ version: '2.1'
|
||||
services:
|
||||
|
||||
dataease:
|
||||
image: registry.cn-qingdao.aliyuncs.com/dataease/dataease2.0:DE_TAG
|
||||
image: registry.cn-qingdao.aliyuncs.com/dataease/dataease:DE_TAG
|
||||
container_name: dataease
|
||||
ports:
|
||||
- ${DE_PORT}:8100
|
||||
|
||||
@ -14,4 +14,4 @@ dataease:
|
||||
origin-list: localhost:8080,localhost:8100,localhost:9080
|
||||
apisix-api:
|
||||
domain: http://apisix:9180
|
||||
key: edd1c9f034335f136f87ad84b625c8f1
|
||||
key: DE_APISIX_KEY
|
||||
@ -44,7 +44,7 @@ function usage() {
|
||||
echo " version 查看 DATAEASE 版本"
|
||||
}
|
||||
function _check_apisix_init() {
|
||||
if [[ $DE_INSTALL_MODE = "enterprise" ]];then
|
||||
if [[ $DE_INSTALL_MODE != "community" ]];then
|
||||
_prepare_apisix
|
||||
fi
|
||||
}
|
||||
@ -56,7 +56,7 @@ function _prepare_apisix() {
|
||||
cd $DE_RUNNING_BASE
|
||||
env | grep DE_ >.env
|
||||
sed -i -e "s/DE_APISIX_KEY/${DE_APISIX_KEY}/g" $DE_RUNNING_BASE/apisix/apisix_conf/config.yaml
|
||||
sed -i -e "s/key:.*/key: ${DE_APISIX_KEY}/g" $DE_RUNNING_BASE/conf/application.yml
|
||||
sed -i -e "s/DE_APISIX_KEY/${DE_APISIX_KEY}/g" $DE_RUNNING_BASE/conf/application.yml
|
||||
fi
|
||||
compose_files="${compose_files} -f docker-compose-apisix.yml"
|
||||
}
|
||||
@ -83,7 +83,7 @@ function _healthcheck() {
|
||||
echo
|
||||
}
|
||||
function _get_current_version() {
|
||||
de_current_version=$(grep "^ image:.*dataease2.0:" ${DE_RUNNING_BASE}/docker-compose.yml | awk -F'dataease2.0:' '{print $2}')
|
||||
de_current_version=$(grep "^ image:.*dataease:" ${DE_RUNNING_BASE}/docker-compose.yml | awk -F'dataease:' '{print $2}')
|
||||
echo $de_current_version
|
||||
}
|
||||
function status() {
|
||||
@ -143,7 +143,7 @@ function version() {
|
||||
}
|
||||
function upgrade() {
|
||||
echo
|
||||
git_urls=('gitee.com' 'github.com')
|
||||
git_urls=('github.com')
|
||||
if [[ -x "$(command -v python)" ]]; then
|
||||
py_cmd='python'
|
||||
elif [[ -x "$(command -v python3)" ]]; then
|
||||
@ -170,7 +170,7 @@ function upgrade() {
|
||||
done
|
||||
|
||||
if [[ "x${server_url}" == "x" ]]; then
|
||||
echo "没有找到稳定的下载服务器,请稍候重试"
|
||||
echo "没有找到稳定的下载服务器,请访问 https://community.fit2cloud.com/#/products/dataease/downloads 下载离线安装包"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ DE_PORT=8100
|
||||
## 登录超时时间,单位min。如果不设置则默认8小时,也就是480
|
||||
DE_LOGIN_TIMEOUT=480
|
||||
## 安装模式
|
||||
DE_INSTALL_MODE=enterprise
|
||||
DE_INSTALL_MODE=community
|
||||
|
||||
# 数据库配置
|
||||
## 是否使用外部数据库
|
||||
|
||||
@ -183,7 +183,7 @@ else
|
||||
cd ${DE_RUN_BASE} && docker-compose $compose_files pull 2>&1
|
||||
|
||||
DEVERSION=$(cat ${CURRENT_DIR}/dataease/templates/version)
|
||||
#curl -sfL https://resource.fit2cloud.com/installation-log.sh | sh -s de ${INSTALL_TYPE} ${DEVERSION}
|
||||
curl -sfL https://resource.fit2cloud.com/installation-log.sh | sh -s de ${INSTALL_TYPE} ${DEVERSION}
|
||||
cd -
|
||||
fi
|
||||
|
||||
@ -258,5 +258,4 @@ if [[ $http_code != 200 ]];then
|
||||
fi
|
||||
|
||||
echo -e "======================= 安装完成 =======================\n" 2>&1 | tee -a ${CURRENT_DIR}/install.log
|
||||
echo -e "请通过以下方式访问:\n URL: http://\$LOCAL_IP:$DE_PORT\n 用户名: admin\n 初始密码: dataease" 2>&1 | tee -a ${CURRENT_DIR}/install.log
|
||||
|
||||
|
||||
@ -78,13 +78,14 @@ public class HttpClientUtil {
|
||||
* @return 响应结果字符串
|
||||
*/
|
||||
public static String get(String url, HttpClientConfig config) {
|
||||
CloseableHttpClient httpClient = buildHttpClient(url);
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
CloseableHttpClient httpClient = null;
|
||||
try {
|
||||
httpClient = buildHttpClient(url);
|
||||
HttpGet httpGet = new HttpGet(url);
|
||||
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
httpGet.setConfig(config.buildRequestConfig());
|
||||
|
||||
Map<String, String> header = config.getHeader();
|
||||
@ -98,7 +99,9 @@ public class HttpClientUtil {
|
||||
throw new DEException(SYSTEM_INNER_ERROR.code(), "HttpClient查询失败: " + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
httpClient.close();
|
||||
if(httpClient != null){
|
||||
httpClient.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClient关闭连接失败", e);
|
||||
}
|
||||
@ -143,14 +146,14 @@ public class HttpClientUtil {
|
||||
* @return 响应结果字符串
|
||||
*/
|
||||
public static String post(String url, String json, HttpClientConfig config) {
|
||||
CloseableHttpClient httpClient = buildHttpClient(url);
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
CloseableHttpClient httpClient = null;
|
||||
try {
|
||||
buildHttpClient(url);
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
httpPost.setConfig(config.buildRequestConfig());
|
||||
|
||||
Map<String, String> header = config.getHeader();
|
||||
for (String key : header.keySet()) {
|
||||
httpPost.addHeader(key, header.get(key));
|
||||
@ -168,7 +171,9 @@ public class HttpClientUtil {
|
||||
throw new DEException(SYSTEM_INNER_ERROR.code(), "HttpClient查询失败: " + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
httpClient.close();
|
||||
if(httpClient != null){
|
||||
httpClient.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClient关闭连接失败", e);
|
||||
}
|
||||
@ -195,14 +200,15 @@ public class HttpClientUtil {
|
||||
* @return 响应结果字符串
|
||||
*/
|
||||
public static String post(String url, Map<String, String> body, HttpClientConfig config) {
|
||||
CloseableHttpClient httpClient = buildHttpClient(url);
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
try {
|
||||
httpPost.setConfig(config.buildRequestConfig());
|
||||
CloseableHttpClient httpClient = null;
|
||||
|
||||
try {
|
||||
buildHttpClient(url);
|
||||
HttpPost httpPost = new HttpPost(url);
|
||||
if (config == null) {
|
||||
config = new HttpClientConfig();
|
||||
}
|
||||
httpPost.setConfig(config.buildRequestConfig());
|
||||
Map<String, String> header = config.getHeader();
|
||||
for (String key : header.keySet()) {
|
||||
httpPost.addHeader(key, header.get(key));
|
||||
@ -227,7 +233,9 @@ public class HttpClientUtil {
|
||||
throw new DEException(SYSTEM_INNER_ERROR.code(), "HttpClient查询失败: " + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
httpClient.close();
|
||||
if(httpClient != null){
|
||||
httpClient.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClient关闭连接失败", e);
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package io.dataease.utils;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
public class VersionUtil {
|
||||
|
||||
private static final String randomId = IDUtils.randomID(16);
|
||||
|
||||
public static String getRandomVersion() {
|
||||
return randomId;
|
||||
Environment environment = CommonBeanFactory.getBean(Environment.class);
|
||||
assert environment != null;
|
||||
return environment.getProperty("dataease.version", "2.0.0");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user