Merge branch 'dev-v2' into pr@dev-v2_dzz_mobile

This commit is contained in:
dataeaseShu 2024-02-19 16:17:11 +08:00
commit 0daa83865f
245 changed files with 8704 additions and 1134 deletions

View File

@ -7,4 +7,7 @@ assignees: xuwei-fit2cloud, yayanpei-fit2cloud
---
DataEase 版本:
**请描述您的需求或者改进建议.**

View File

@ -3,7 +3,7 @@ name: Bug 提交
about: 提交产品缺陷帮助我们更好的改进
title: "[Bug]"
labels: 状态:待处理
assignees: BBchicken-9527, Shenguobin0102, zrfit
assignees: BBchicken-9527, Shenguobin0102
---

View File

@ -13,10 +13,11 @@ WORKDIR /opt/apps
ADD core/core-backend/target/CoreApplication.jar /opt/apps/app.jar
ADD de-xpack/xpack-permissions/target/xpack-permissions-$IMAGE_TAG.jar /opt/apps/xpack-permission.jar
ADD de-xpack/xpack-base/target/xpack-base-$IMAGE_TAG.jar /opt/apps/xpack-base.jar
ADD de-xpack/xpack-sync/target/xpack-sync-$IMAGE_TAG.jar /opt/apps/xpack-sync.jar
ENV JAVA_APP_JAR=/opt/apps/app.jar
HEALTHCHECK --interval=15s --timeout=5s --retries=20 --start-period=30s CMD curl -f 127.0.0.1:8100
CMD java -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dataease2.0/logs/dump.hprof -Dloader.path=/opt/apps/xpack-permission.jar,/opt/apps/xpack-base.jar -jar /opt/apps/app.jar
CMD java -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/dataease2.0/logs/dump.hprof -Dloader.path=/opt/apps/xpack-permission.jar,/opt/apps/xpack-base.jar,/opt/apps/xpack-sync.jar -jar /opt/apps/app.jar

View File

@ -23,6 +23,11 @@
<artifactId>api-permissions</artifactId>
<version>${dataease.version}</version>
</dependency>
<dependency>
<groupId>io.dataease</groupId>
<artifactId>api-sync</artifactId>
<version>${dataease.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
@ -54,7 +59,7 @@
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
<version>[2.9.0, )</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>

View File

@ -21,11 +21,11 @@ public class MybatisPlusGenerator {
/**
* 业务模块例如datasource,dataset,panel等
*/
private static final String busi = "visualization";
private static final String busi = "template";
/**
* 这是要生成代码的表名称
*/
private static final String TABLE_NAME = "visualization_watermark";
private static final String TABLE_NAME = "visualization_template";
/**
* 下面两个配置基本上不用动

View File

@ -174,7 +174,7 @@ public class ChartDataManage {
Map<String, Object> mapAttr = view.getCustomAttr();
Map<String, Object> mapSize = (Map<String, Object>) mapAttr.get("basicStyle");
if (StringUtils.equalsIgnoreCase(view.getType(), "table-info") && table.getMode() == 0) {
if (StringUtils.equalsIgnoreCase((String) mapSize.get("tablePageMode"), "page") && !chartExtRequest.getExcelExportFlag()) {
if (StringUtils.equalsIgnoreCase((String) mapSize.get("tablePageMode"), "page") && !view.getIsExcelExport()) {
if (chartExtRequest.getGoPage() == null) {
chartExtRequest.setGoPage(1L);
}
@ -190,7 +190,7 @@ public class ChartDataManage {
if (StringUtils.equalsIgnoreCase(view.getResultMode(), "custom")) {
chartExtRequest.setGoPage(1L);
chartExtRequest.setPageSize(view.getResultCount().longValue());
} else if (!chartExtRequest.getExcelExportFlag()) {
} else if (!view.getIsExcelExport()) {
chartExtRequest.setGoPage(null);
chartExtRequest.setPageSize(null);
}
@ -203,12 +203,13 @@ public class ChartDataManage {
switch (view.getType()) {
case "label":
xAxis = xAxis.stream().filter(item -> !desensitizationList.keySet().contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
xAxisBase = xAxisBase.stream().filter(item -> !desensitizationList.keySet().contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
yAxis = new ArrayList<>();
if (ObjectUtils.isEmpty(xAxis)) {
return emptyChartViewDTO(view);
}
break;
case "text":
case "indicator":
case "gauge":
case "liquid":
xAxis = new ArrayList<>();
@ -220,16 +221,19 @@ public class ChartDataManage {
case "table-info":
yAxis = new ArrayList<>();
xAxis = xAxis.stream().filter(item -> dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
xAxisBase = xAxisBase.stream().filter(item -> dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
if (ObjectUtils.isEmpty(xAxis)) {
return emptyChartViewDTO(view);
}
break;
case "table-normal":
xAxis = xAxis.stream().filter(item -> dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
xAxisBase = xAxisBase.stream().filter(item -> dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
yAxis = yAxis.stream().filter(item -> dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
break;
default:
xAxis = xAxis.stream().filter(item -> !desensitizationList.keySet().contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
xAxisBase = xAxisBase.stream().filter(item -> !desensitizationList.keySet().contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
yAxis = yAxis.stream().filter(item -> !desensitizationList.keySet().contains(item.getDataeaseName()) && dataeaseNames.contains(item.getDataeaseName())).collect(Collectors.toList());
}
@ -496,7 +500,7 @@ public class ChartDataManage {
ExtWhere2Str.extWhere2sqlOjb(sqlMeta, extFilterList, transFields(allFields));
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, transFields(allFields));
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "indicator", "gauge", "liquid")) {
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, transFields(allFields));
querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {
@ -684,7 +688,7 @@ public class ChartDataManage {
mapChart = ChartDataBuild.transScatterData(xAxis, yAxis, view, data, extBubble, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "radar")) {
mapChart = ChartDataBuild.transRadarChartData(xAxis, yAxis, view, data, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "text")
} else if (StringUtils.containsIgnoreCase(view.getType(), "indicator")
|| StringUtils.containsIgnoreCase(view.getType(), "gauge")
|| StringUtils.equalsIgnoreCase("liquid", view.getType())) {
mapChart = ChartDataBuild.transNormalChartData(xAxis, yAxis, view, data, isDrill);
@ -708,7 +712,7 @@ public class ChartDataManage {
mapChart = ChartDataBuild.transScatterDataAntV(xAxis, yAxis, view, data, extBubble, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "radar")) {
mapChart = ChartDataBuild.transRadarChartDataAntV(xAxis, yAxis, view, data, isDrill);
} else if (StringUtils.containsIgnoreCase(view.getType(), "text")
} else if (StringUtils.containsIgnoreCase(view.getType(), "indicator")
|| StringUtils.containsIgnoreCase(view.getType(), "gauge")
|| StringUtils.equalsIgnoreCase("liquid", view.getType())) {
mapChart = ChartDataBuild.transNormalChartData(xAxis, yAxis, view, data, isDrill);
@ -719,6 +723,10 @@ public class ChartDataManage {
} else {
mapChart = ChartDataBuild.transChartDataAntV(xAxis, yAxis, view, data, isDrill);
}
} else if (StringUtils.equalsIgnoreCase(view.getRender(), "custom")) {
if (StringUtils.containsIgnoreCase(view.getType(), "indicator")) {
mapChart = ChartDataBuild.transNormalChartData(xAxis, yAxis, view, data, isDrill);
}
}
// table组件明细表也用于导出数据
Map<String, Object> mapTableNormal = null;
@ -1220,7 +1228,7 @@ public class ChartDataManage {
return new ArrayList<String[]>();
}
break;
case "text":
case "indicator":
case "gauge":
case "liquid":
xAxis = new ArrayList<>();
@ -1276,7 +1284,7 @@ public class ChartDataManage {
Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")");
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, transFields(allFields));
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "text", "gauge", "liquid")) {
if (StringUtils.equalsAnyIgnoreCase(view.getType(), "indicator", "gauge", "liquid")) {
Quota2SQLObj.quota2sqlObj(sqlMeta, yAxis, transFields(allFields));
querySql = SQLProvider.createQuerySQL(sqlMeta, true, needOrder, view);
} else if (StringUtils.containsIgnoreCase(view.getType(), "stack")) {

View File

@ -43,10 +43,9 @@ public class SqlparserUtils {
}
SqlParser.Config config =
SqlParser.configBuilder()
.setLex(Lex.JAVA)
.setIdentifierMaxLength(256)
.build();
SqlParser.config()
.withLex(Lex.JAVA)
.withIdentifierMaxLength(256);
SqlParser sqlParser = SqlParser.create(tmpSql, config);
SqlNode sqlNode;
try {
@ -60,12 +59,13 @@ public class SqlparserUtils {
}
private static void getDependencies(SqlNode sqlNode, Boolean fromOrJoin) {
if (sqlNode == null) {
return;
}
if (sqlNode.getKind() == JOIN) {
SqlJoin sqlKind = (SqlJoin) sqlNode;
} else if (sqlNode.getKind() == IDENTIFIER) {
} else if (sqlNode.getKind() == AS) {
SqlBasicCall sqlKind = (SqlBasicCall) sqlNode;
} else if (sqlNode.getKind() == SELECT) {
@ -80,9 +80,19 @@ public class SqlparserUtils {
SqlNode newWhere = sqlKind.getWhere().accept(getSqlShuttle());
sqlKind.setWhere(newWhere);
}
} else {
// TODO 这里可根据需求拓展处理其他类型的 sqlNode
} else if (sqlNode.getKind() == ORDER_BY) {
SqlOrderBy sqlKind = (SqlOrderBy) sqlNode;
List<SqlNode> operandList = sqlKind.getOperandList();
for (int i = 0; i < operandList.size(); i++) {
getDependencies(operandList.get(i), false);
}
} else if (sqlNode.getKind() == UNION) {
SqlBasicCall sqlKind = (SqlBasicCall) sqlNode;
if (sqlKind.getOperandList().size() >= 2) {
for (int i = 0; i < sqlKind.getOperandList().size(); i++) {
getDependencies(sqlKind.getOperandList().get(i), false);
}
}
}
}

View File

@ -311,6 +311,7 @@ public class DatasetDataManage {
Map<String, Object> previewData = buildPreviewData(data, fields, new HashMap<>());
Map<String, Object> map = new LinkedHashMap<>();
map.put("data", previewData);
map.put("sql", Base64.getEncoder().encodeToString(sql.getBytes()));
return map;
}

View File

@ -6,7 +6,6 @@ import io.dataease.api.dataset.dto.DatasetTableDTO;
import io.dataease.api.dataset.dto.SqlVariableDetails;
import io.dataease.api.dataset.union.DatasetGroupInfoDTO;
import io.dataease.api.dataset.vo.DataSetBarVO;
import io.dataease.commons.constants.OptConstants;
import io.dataease.constant.LogOT;
import io.dataease.constant.LogST;
import io.dataease.dataset.manage.DatasetGroupManage;
@ -44,11 +43,13 @@ public class DatasetTreeServer implements DatasetTreeApi {
return datasetGroupManage.save(dto, false);
}
@DeLog(id = "#p0.id", ot = LogOT.MODIFY, st = LogST.DATASET)
@Override
public DatasetNodeDTO move(DatasetGroupInfoDTO dto) throws Exception {
return datasetGroupManage.move(dto);
}
@DeLog(id = "#p0", ot = LogOT.DELETE, st = LogST.DATASET)
@Override
public void delete(Long id) {
datasetGroupManage.delete(id);

View File

@ -21,10 +21,9 @@ public class SqlUtils {
}
SqlParser.Config config =
SqlParser.configBuilder()
.setLex(Lex.JAVA)
.setIdentifierMaxLength(256)
.build();
SqlParser.config()
.withLex(Lex.JAVA)
.withIdentifierMaxLength(256);
// 创建解析器
SqlParser sqlParser = SqlParser
.create(sql, config);

View File

@ -25,7 +25,6 @@ import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Component
public class DataSourceManage {
@ -71,12 +70,14 @@ public class DataSourceManage {
return TreeUtils.mergeTree(nodes, BusiNodeVO.class, false);
}
@XpackInteract(value = "datasourceResourceTree", before = false)
public void innerSave(CoreDatasource coreDatasource) {
coreDatasourceMapper.insert(coreDatasource);
coreOptRecentManage.saveOpt(coreDatasource.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASOURCE,OptConstants.OPT_TYPE.NEW);
coreOptRecentManage.saveOpt(coreDatasource.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASOURCE, OptConstants.OPT_TYPE.NEW);
}
@XpackInteract(value = "datasourceResourceTree", before = false)
public void innerEdit(CoreDatasource coreDatasource) {
UpdateWrapper<CoreDatasource> updateWrapper = new UpdateWrapper<>();
@ -84,9 +85,10 @@ public class DataSourceManage {
coreDatasource.setUpdateTime(System.currentTimeMillis());
coreDatasource.setUpdateBy(AuthUtils.getUser().getUserId());
coreDatasourceMapper.update(coreDatasource, updateWrapper);
coreOptRecentManage.saveOpt(coreDatasource.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASOURCE,OptConstants.OPT_TYPE.UPDATE);
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<>();
@ -94,6 +96,7 @@ public class DataSourceManage {
coreDatasourceMapper.update(coreDatasource, updateWrapper);
}
@XpackInteract(value = "datasourceResourceTree", before = false)
public void move(DatasourceDTO dataSourceDTO) {
Long id = dataSourceDTO.getId();
@ -106,6 +109,6 @@ public class DataSourceManage {
sourceData.setPid(dataSourceDTO.getPid());
sourceData.setName(dataSourceDTO.getName());
coreDatasourceMapper.updateById(sourceData);
coreOptRecentManage.saveOpt(sourceData.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASOURCE,OptConstants.OPT_TYPE.UPDATE);
coreOptRecentManage.saveOpt(sourceData.getId(), OptConstants.OPT_RESOURCE_TYPE.DATASOURCE, OptConstants.OPT_TYPE.UPDATE);
}
}

View File

@ -16,8 +16,8 @@ import io.dataease.utils.CommonBeanFactory;
import io.dataease.utils.HttpClientConfig;
import io.dataease.utils.HttpClientUtil;
import io.dataease.utils.JsonUtil;
import net.minidev.json.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

View File

@ -144,7 +144,7 @@ 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.getMessage());
throw e;
}
return "Success";
}
@ -173,8 +173,14 @@ public class CalciteProvider {
datasetTableFields.add(tableField);
}
list = getDataResult(resultSet);
} catch (Exception e) {
DEException.throwException(Translator.get("i18n_fetch_error") + e.getMessage());
} catch (Exception | AssertionError e) {
String msg;
if (e.getCause() != null && e.getCause().getCause() != null) {
msg = e.getMessage() + " [" + e.getCause().getCause().getMessage() + "]";
} else {
msg = e.getMessage();
}
DEException.throwException(Translator.get("i18n_fetch_error") + msg);
} finally {
try {
if (resultSet != null) resultSet.close();
@ -255,7 +261,7 @@ public class CalciteProvider {
DatasourceConfiguration configuration = null;
DatasourceType datasourceType = DatasourceType.valueOf(ds.getType());
try {
if(rootSchema.getSubSchema(ds.getSchemaAlias()) != null){
if (rootSchema.getSubSchema(ds.getSchemaAlias()) != null) {
JdbcSchema jdbcSchema = rootSchema.getSubSchema(ds.getSchemaAlias()).unwrap(JdbcSchema.class);
BasicDataSource basicDataSource = (BasicDataSource) jdbcSchema.getDataSource();
basicDataSource.close();
@ -453,6 +459,7 @@ public class CalciteProvider {
DEException.throwException(Translator.get("i18n_schema_is_empty"));
}
tableSqls.add("select table_name, owner, comments from all_tab_comments where owner='" + configuration.getSchema() + "' AND table_type = 'TABLE'");
tableSqls.add("select table_name, owner, comments from all_tab_comments where owner='" + configuration.getSchema() + "' AND table_type = 'VIEW'");
break;
case db2:
configuration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), Db2.class);

View File

@ -60,7 +60,7 @@ public class MysqlEngineProvider extends EngineProvider {
if (StringUtils.isEmpty(strings[i])) {
strings1[i] = null;
} else {
strings1[i] = strings[i].replace("'", "\\'");
strings1[i] = strings[i].replace("\\", "\\\\").replace("'", "\\'");
}
}
values.append("('").append(String.join("','", Arrays.asList(strings1)))

View File

@ -14,6 +14,8 @@ import io.dataease.api.ds.vo.*;
import io.dataease.commons.constants.TaskStatus;
import io.dataease.commons.utils.CommonThreadPool;
import io.dataease.constant.DataSourceType;
import io.dataease.constant.LogOT;
import io.dataease.constant.LogST;
import io.dataease.dataset.dto.DatasourceSchemaDTO;
import io.dataease.dataset.manage.DatasetDataManage;
import io.dataease.dataset.utils.TableUtils;
@ -35,6 +37,7 @@ import io.dataease.i18n.Translator;
import io.dataease.job.sechedule.CheckDsStatusJob;
import io.dataease.job.sechedule.ScheduleManager;
import io.dataease.license.config.XpackInteract;
import io.dataease.log.DeLog;
import io.dataease.model.BusiNodeRequest;
import io.dataease.model.BusiNodeVO;
import io.dataease.system.dao.auto.entity.CoreSysSetting;
@ -63,7 +66,6 @@ import static io.dataease.datasource.server.DatasourceTaskServer.ScheduleType.RI
@RestController
@RequestMapping("/datasource")
@Transactional
public class DatasourceServer implements DatasourceApi {
@Resource
private CoreDatasourceMapper datasourceMapper;
@ -117,45 +119,6 @@ public class DatasourceServer implements DatasourceApi {
}
}
public void move(DatasourceDTO dataSourceDTO) throws DEException {
switch (dataSourceDTO.getAction()) {
case "move" -> {
if (dataSourceDTO.getPid() == null) {
DEException.throwException("目录必选!");
}
if (Objects.equals(dataSourceDTO.getId(), dataSourceDTO.getPid())) {
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);
}
case "rename" -> {
CoreDatasource datasource = datasourceMapper.selectById(dataSourceDTO.getId());
datasource.setName(dataSourceDTO.getName());
dataSourceManage.innerEdit(datasource);
}
case "create" -> {
CoreDatasource coreDatasource = new CoreDatasource();
BeanUtils.copyBean(coreDatasource, dataSourceDTO);
coreDatasource.setCreateTime(System.currentTimeMillis());
coreDatasource.setUpdateTime(System.currentTimeMillis());
coreDatasource.setTaskStatus(TaskStatus.WaitingForExecution.name());
coreDatasource.setType(dataSourceDTO.getNodeType());
coreDatasource.setId(IDUtils.snowID());
coreDatasource.setConfiguration("");
dataSourceManage.innerSave(coreDatasource);
}
default -> {
}
}
}
private void filterDs(List<BusiNodeVO> busiNodeVOS, List<Long> ids, String type, Long id) {
for (BusiNodeVO busiNodeVO : busiNodeVOS) {
if (busiNodeVO.getType() != null && busiNodeVO.getType().equalsIgnoreCase(type)) {
@ -225,16 +188,56 @@ public class DatasourceServer implements DatasourceApi {
return hasRepeat;
}
@DeLog(id = "#p0.id", ot = LogOT.MODIFY, st = LogST.DATASOURCE)
@Transactional
public DatasourceDTO move(DatasourceDTO dataSourceDTO) {
if (dataSourceDTO.getPid() == null) {
DEException.throwException("目录必选!");
}
if (Objects.equals(dataSourceDTO.getId(), dataSourceDTO.getPid())) {
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);
return dataSourceDTO;
}
@Transactional
public DatasourceDTO reName(DatasourceDTO dataSourceDTO) {
if (StringUtils.isEmpty(dataSourceDTO.getName())) {
DEException.throwException("名称不能为空!");
}
CoreDatasource datasource = datasourceMapper.selectById(dataSourceDTO.getId());
datasource.setName(dataSourceDTO.getName());
dataSourceManage.innerEdit(datasource);
return dataSourceDTO;
}
@DeLog(id = "#p0.id", pid = "#p0.pid", ot = LogOT.CREATE, st = LogST.DATASOURCE)
@Transactional
public DatasourceDTO createFolder(DatasourceDTO dataSourceDTO) {
dataSourceDTO.setCreateTime(System.currentTimeMillis());
dataSourceDTO.setUpdateTime(System.currentTimeMillis());
dataSourceDTO.setType(dataSourceDTO.getNodeType());
dataSourceDTO.setId(IDUtils.snowID());
dataSourceDTO.setConfiguration("");
CoreDatasource coreDatasource = new CoreDatasource();
coreDatasource.setTaskStatus(TaskStatus.WaitingForExecution.name());
BeanUtils.copyBean(coreDatasource, dataSourceDTO);
dataSourceManage.innerSave(coreDatasource);
return dataSourceDTO;
}
@DeLog(id = "#p0.id", pid = "#p0.pid", ot = LogOT.CREATE, st = LogST.DATASOURCE)
@Transactional
@Override
public DatasourceDTO save(DatasourceDTO dataSourceDTO) throws DEException {
if (StringUtils.isNotEmpty(dataSourceDTO.getAction())) {
move(dataSourceDTO);
return dataSourceDTO;
}
if (StringUtils.isNotEmpty(dataSourceDTO.getNodeType()) && dataSourceDTO.getNodeType().equalsIgnoreCase("folder")) {
dataSourceDTO.setType("folder");
dataSourceDTO.setConfiguration("");
}
if (dataSourceDTO.getId() != null && dataSourceDTO.getId() > 0) {
return update(dataSourceDTO);
}
@ -250,6 +253,7 @@ public class DatasourceServer implements DatasourceApi {
try {
checkDatasourceStatus(coreDatasource);
} catch (Exception ignore) {
coreDatasource.setStatus("Error");
}
coreDatasource.setTaskStatus(TaskStatus.WaitingForExecution.name());
coreDatasource.setCreateBy(AuthUtils.getUser().getUserId().toString());
@ -310,32 +314,9 @@ public class DatasourceServer implements DatasourceApi {
return dataSourceDTO;
}
private static void checkParams(String configurationStr) {
DatasourceConfiguration configuration = JsonUtil.parseObject(configurationStr, DatasourceConfiguration.class);
if (configuration.getInitialPoolSize() < configuration.getMinPoolSize()) {
DEException.throwException("初始连接数不能小于最小连接数!");
}
if (configuration.getInitialPoolSize() > configuration.getMaxPoolSize()) {
DEException.throwException("初始连接数不能大于最大连接数!");
}
if (configuration.getMaxPoolSize() < configuration.getMinPoolSize()) {
DEException.throwException("最大连接数不能小于最小连接数!");
}
if (configuration.getQueryTimeout() < 0) {
DEException.throwException("查询超时不能小于0");
}
}
private static void checkName(List<String> tables) {
for (int i = 0; i < tables.size() - 1; i++) {
for (int j = i + 1; j < tables.size(); j++) {
if (tables.get(i).equalsIgnoreCase(tables.get(j))) {
DEException.throwException(Translator.get("i18n_table_name_repeat") + tables.get(i));
}
}
}
}
@DeLog(id = "#p0.id", ot = LogOT.MODIFY, st = LogST.DATASOURCE)
@Transactional
@Override
public DatasourceDTO update(DatasourceDTO dataSourceDTO) throws DEException {
Long pk = null;
if (ObjectUtils.isEmpty(pk = dataSourceDTO.getId())) {
@ -352,7 +333,8 @@ public class DatasourceServer implements DatasourceApi {
requestDatasource.setUpdateBy(AuthUtils.getUser().getUserId());
try {
checkDatasourceStatus(requestDatasource);
} catch (Exception ignore) {
} catch (Exception e) {
requestDatasource.setStatus("Error");
}
DatasourceRequest sourceTableRequest = new DatasourceRequest();
@ -449,6 +431,32 @@ public class DatasourceServer implements DatasourceApi {
return dataSourceDTO;
}
private static void checkParams(String configurationStr) {
DatasourceConfiguration configuration = JsonUtil.parseObject(configurationStr, DatasourceConfiguration.class);
if (configuration.getInitialPoolSize() < configuration.getMinPoolSize()) {
DEException.throwException("初始连接数不能小于最小连接数!");
}
if (configuration.getInitialPoolSize() > configuration.getMaxPoolSize()) {
DEException.throwException("初始连接数不能大于最大连接数!");
}
if (configuration.getMaxPoolSize() < configuration.getMinPoolSize()) {
DEException.throwException("最大连接数不能小于最小连接数!");
}
if (configuration.getQueryTimeout() < 0) {
DEException.throwException("查询超时不能小于0");
}
}
private static void checkName(List<String> tables) {
for (int i = 0; i < tables.size() - 1; i++) {
for (int j = i + 1; j < tables.size(); j++) {
if (tables.get(i).equalsIgnoreCase(tables.get(j))) {
DEException.throwException(Translator.get("i18n_table_name_repeat") + tables.get(i));
}
}
}
}
private String excelDataTableName(String name) {
return StringUtils.substring(name, 6, name.length() - 11);
}
@ -464,8 +472,9 @@ public class DatasourceServer implements DatasourceApi {
CoreDatasource coreDatasource = new CoreDatasource();
BeanUtils.copyBean(coreDatasource, dataSourceDTO);
checkDatasourceStatus(coreDatasource);
dataSourceDTO.setStatus(coreDatasource.getStatus());
return dataSourceDTO;
DatasourceDTO result = new DatasourceDTO();
result.setStatus(coreDatasource.getStatus());
return result;
}
@Override
@ -546,6 +555,8 @@ public class DatasourceServer implements DatasourceApi {
return datasourceDTO;
}
@Transactional
@DeLog(id = "#p0", ot = LogOT.DELETE, st = LogST.DATASOURCE)
@Override
@XpackInteract(value = "datasourceResourceTree", before = false)
public void delete(Long datasourceId) throws DEException {
@ -607,7 +618,8 @@ public class DatasourceServer implements DatasourceApi {
@Override
public DatasourceDTO validate(Long datasourceId) throws DEException {
CoreDatasource coreDatasource = datasourceMapper.selectById(datasourceId);
CoreDatasource coreDatasource = new CoreDatasource();
BeanUtils.copyBean(coreDatasource, datasourceMapper.selectById(datasourceId));
return validate(coreDatasource);
}
@ -637,19 +649,24 @@ public class DatasourceServer implements DatasourceApi {
}
private DatasourceDTO validate(CoreDatasource coreDatasource) {
checkDatasourceStatus(coreDatasource);
DatasourceDTO datasourceDTO = new DatasourceDTO();
BeanUtils.copyBean(datasourceDTO, coreDatasource);
CoreDatasource record = new CoreDatasource();
record.setStatus(coreDatasource.getStatus());
QueryWrapper<CoreDatasource> wrapper = new QueryWrapper<>();
wrapper.eq("id", coreDatasource.getId());
CoreDatasource originData = datasourceMapper.selectById(coreDatasource.getId());
String originStatus = originData.getStatus();
if (StringUtils.equals(coreDatasource.getStatus(), originStatus)) {
return datasourceDTO;
try {
checkDatasourceStatus(coreDatasource);
} catch (Exception e) {
coreDatasource.setStatus("Error");
DEException.throwException(e.getMessage());
} finally {
datasourceDTO.setStatus(coreDatasource.getStatus());
QueryWrapper<CoreDatasource> wrapper = new QueryWrapper<>();
wrapper.eq("id", coreDatasource.getId());
CoreDatasource originData = datasourceMapper.selectById(coreDatasource.getId());
String originStatus = originData.getStatus();
if (!StringUtils.equals(coreDatasource.getStatus(), originStatus)) {
dataSourceManage.innerEditStatus(coreDatasource);
}
}
dataSourceManage.innerEditStatus(coreDatasource);
datasourceDTO.setConfiguration("");
return datasourceDTO;
}
@ -830,7 +847,7 @@ public class DatasourceServer implements DatasourceApi {
}
}
public void checkDatasourceStatus(CoreDatasource coreDatasource) throws DEException {
public void checkDatasourceStatus(CoreDatasource coreDatasource) {
if (coreDatasource.getType().equals(DatasourceConfiguration.DatasourceType.Excel.name()) || coreDatasource.getType().equals(DatasourceConfiguration.DatasourceType.folder.name())) {
return;
}
@ -845,8 +862,7 @@ public class DatasourceServer implements DatasourceApi {
}
coreDatasource.setStatus(status);
} catch (Exception e) {
coreDatasource.setStatus("Error");
DEException.throwException("校验失败: " + e.getMessage());
DEException.throwException(e.getMessage());
}
}

View File

@ -6,6 +6,7 @@ import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
@ -25,7 +26,7 @@ public class Mysql extends DatasourceConfiguration {
.replace("DATABASE", getDataBase().trim());
} else {
for (String illegalParameter : illegalParameters) {
if (getExtraParams().toLowerCase().contains(illegalParameter.toLowerCase())) {
if (getExtraParams().toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(getExtraParams()).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}

View File

@ -71,9 +71,9 @@ public class SQLConstants {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_INT_FORMAT = "DECIMAL(20,0)";
public static final String DEFAULT_INT_FORMAT = "DECIMAL(18,0)";
public static final String DEFAULT_FLOAT_FORMAT = "DECIMAL(27,8)";
public static final String DEFAULT_FLOAT_FORMAT = "DECIMAL(26,8)";
public static final String WHERE_VALUE_NULL = "(NULL,'')";

View File

@ -0,0 +1,12 @@
package io.dataease.rmonitor.bo;
import lombok.Data;
import java.io.Serializable;
@Data
public class PerMonitorCheckBO implements Serializable {
private boolean valid;
private boolean emptyPermission;
}

View File

@ -0,0 +1,24 @@
package io.dataease.rmonitor.bo;
import io.dataease.model.TreeBaseModel;
import io.dataease.model.TreeResultModel;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class PerMonitorNodeBO implements TreeBaseModel<PerMonitorNodeBO>, TreeResultModel<PerMonitorNodeBO>, Serializable {
private Long id;
private String name;
private Long pid;
private boolean leaf;
private int extraFlag;
private List<PerMonitorNodeBO> children;
}

View File

@ -0,0 +1,118 @@
package io.dataease.rmonitor.manage;
import io.dataease.exception.DEException;
import io.dataease.rmonitor.bo.PerMonitorCheckBO;
import io.dataease.rmonitor.bo.PerMonitorNodeBO;
import io.dataease.rmonitor.mapper.ResourceMonitorMapper;
import io.dataease.rmonitor.mapper.entity.DatasetFreeResource;
import io.dataease.rmonitor.mapper.entity.DsFreeResource;
import io.dataease.rmonitor.mapper.entity.VisualFreeResource;
import io.dataease.utils.BeanUtils;
import io.dataease.utils.TreeUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component("resourceMonitorManage")
public class ResourceMonitorManage {
@Resource(name = "resourceMonitorSyncManage")
private ResourceMonitorSyncManage resourceMonitorSyncManage;
@Resource
private ResourceMonitorMapper resourceMonitorMapper;
private boolean existFreeResource() {
int rCount = resourceMonitorMapper.dsCount() + resourceMonitorMapper.datasetCount() + resourceMonitorMapper.vCount();
return rCount > 0;
}
private Map<String, List<PerMonitorNodeBO>> freeResource() {
Map<String, List<PerMonitorNodeBO>> result = new HashMap<>();
List<DsFreeResource> dsFreeResources = resourceMonitorMapper.queryFreeDs();
if (CollectionUtils.isNotEmpty(dsFreeResources)) {
List<PerMonitorNodeBO> dsBos = dsFreeResources.stream().map(node -> {
PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
bo.setLeaf(!StringUtils.equals("folder", node.getType()));
return bo;
}).collect(Collectors.toList());
List<PerMonitorNodeBO> dsTree = TreeUtils.mergeTree(dsBos, PerMonitorNodeBO.class, false);
result.put("datasource", dsTree);
}
List<DatasetFreeResource> datasetFreeResources = resourceMonitorMapper.queryFreeDataset();
if (CollectionUtils.isNotEmpty(datasetFreeResources)) {
List<PerMonitorNodeBO> datasetBos = datasetFreeResources.stream().map(node -> {
PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
bo.setLeaf(!StringUtils.equals("folder", node.getNodeType()));
return bo;
}).collect(Collectors.toList());
List<PerMonitorNodeBO> datasetTree = TreeUtils.mergeTree(datasetBos, PerMonitorNodeBO.class, false);
result.put("dataset", datasetTree);
}
List<VisualFreeResource> visualFreeResources = resourceMonitorMapper.queryFreeVusial();
if (CollectionUtils.isNotEmpty(visualFreeResources)) {
Map<String, List<VisualFreeResource>> baseMap = visualFreeResources.stream().collect(Collectors.groupingBy(VisualFreeResource::getType));
for (Map.Entry<String, List<VisualFreeResource>> entry : baseMap.entrySet()) {
List<VisualFreeResource> freeResource = entry.getValue();
List<PerMonitorNodeBO> visualBos = freeResource.stream().map(node -> {
PerMonitorNodeBO bo = BeanUtils.copyBean(new PerMonitorNodeBO(), node);
bo.setLeaf(!StringUtils.equals("folder", node.getNodeType()));
return bo;
}).collect(Collectors.toList());
result.put(convertBusiFlag(entry.getKey()), TreeUtils.mergeTree(visualBos, PerMonitorNodeBO.class, false));
}
}
return result;
}
private String convertBusiFlag(String key) {
if (StringUtils.equals("dashboard", key)){
return "panel";
} else if (StringUtils.equals("dataV", key)) {
return "screen";
} else return key;
}
public boolean check() {
PerMonitorCheckBO checkBO = resourceMonitorSyncManage.checkXpackResource();
return checkBO.isValid() && checkBO.isEmptyPermission() && existFreeResource();
}
@Transactional
public void delete() {
boolean existFree = existFreeResource();
if (!existFree) DEException.throwException("无未同步资源!");
resourceMonitorMapper.delFreeDs();
resourceMonitorMapper.delFreeDataset();
resourceMonitorMapper.delFreeVisual();
}
public void sync() {
//1从xpack获取资源 如果xpack不存在 或者资源不为空 则直接返回 并且抛出异常仅支持首次导入lic同步
//2从core获取资源
//3根据类型分组 并组织成树形结构
//4分别遍历每一棵树 从上到下 同步到权限体系 给默认组织
PerMonitorCheckBO checkBO = resourceMonitorSyncManage.checkXpackResource();
if (!checkBO.isValid()) DEException.throwException("缺少许可证");
if (!checkBO.isEmptyPermission()) DEException.throwException("仅支持license首次导入同步");
Map<String, List<PerMonitorNodeBO>> freeResourceMap = freeResource();
if (MapUtils.isEmpty(freeResourceMap)) DEException.throwException("无未同步资源!");
for (Map.Entry<String, List<PerMonitorNodeBO>> entry : freeResourceMap.entrySet()) {
resourceMonitorSyncManage.sync(entry.getKey(), entry.getValue());
}
}
}

View File

@ -0,0 +1,28 @@
package io.dataease.rmonitor.manage;
import io.dataease.exception.DEException;
import io.dataease.license.config.XpackInteract;
import io.dataease.rmonitor.bo.PerMonitorCheckBO;
import io.dataease.rmonitor.bo.PerMonitorNodeBO;
import io.dataease.rmonitor.mapper.ResourceMonitorMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("resourceMonitorSyncManage")
public class ResourceMonitorSyncManage {
@Resource(name = "resourceMonitorMapper")
private ResourceMonitorMapper resourceMonitorMapper;
@XpackInteract(value = "resourceMonitorSyncManage", replace = true)
public void sync(String flag, List<PerMonitorNodeBO> treeNodes) {
DEException.throwException("缺失许可证");
}
@XpackInteract(value = "resourceMonitorSyncManage", replace = true)
public PerMonitorCheckBO checkXpackResource() {
return new PerMonitorCheckBO();
}
}

View File

@ -0,0 +1,41 @@
package io.dataease.rmonitor.mapper;
import io.dataease.rmonitor.mapper.entity.DatasetFreeResource;
import io.dataease.rmonitor.mapper.entity.DsFreeResource;
import io.dataease.rmonitor.mapper.entity.VisualFreeResource;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface ResourceMonitorMapper {
@Select("select count(id) from core_datasource")
int dsCount();
@Select("select count(id) from core_dataset_group")
int datasetCount();
@Select("select count(id) from data_visualization_info")
int vCount();
@Select("select id, name, pid, type, status from core_datasource")
List<DsFreeResource> queryFreeDs();
@Select("select id, name, pid, node_type from core_dataset_group")
List<DatasetFreeResource> queryFreeDataset();
@Select("select id, name, pid, node_type, type from data_visualization_info")
List<VisualFreeResource> queryFreeVusial();
@Delete("delete from core_datasource")
void delFreeDs();
@Delete("delete from core_dataset_group")
void delFreeDataset();
@Delete("delete from data_visualization_info")
void delFreeVisual();
}

View File

@ -0,0 +1,15 @@
package io.dataease.rmonitor.mapper.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class BaseFreeResource implements Serializable {
private Long id;
private String name;
private Long pid;
}

View File

@ -0,0 +1,13 @@
package io.dataease.rmonitor.mapper.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@EqualsAndHashCode(callSuper = true)
@Data
public class DatasetFreeResource extends BaseFreeResource implements Serializable {
private String nodeType;
}

View File

@ -0,0 +1,16 @@
package io.dataease.rmonitor.mapper.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@EqualsAndHashCode(callSuper = true)
@Data
public class DsFreeResource extends BaseFreeResource implements Serializable {
private String type;
private String status;
}

View File

@ -0,0 +1,15 @@
package io.dataease.rmonitor.mapper.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@EqualsAndHashCode(callSuper = true)
@Data
public class VisualFreeResource extends BaseFreeResource implements Serializable {
private String nodeType;
private String type;
}

View File

@ -0,0 +1,30 @@
package io.dataease.rmonitor.server;
import io.dataease.api.rmonitor.ResourceMonitorApi;
import io.dataease.rmonitor.manage.ResourceMonitorManage;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/rmonitor")
public class ResourceMonitorServer implements ResourceMonitorApi {
@Resource(name = "resourceMonitorManage")
private ResourceMonitorManage resourceMonitorManage;
@Override
public boolean existFree() {
return resourceMonitorManage.check();
}
@Override
public void delete() {
resourceMonitorManage.delete();
}
@Override
public void sync() {
resourceMonitorManage.sync();
}
}

View File

@ -0,0 +1,150 @@
package io.dataease.share.dao.auto.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author fit2cloud
* @since 2023-09-22
*/
@TableName("xpack_share")
public class XpackShare implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 创建人
*/
private Long creator;
/**
* 创建时间
*/
private Long time;
/**
* 过期时间
*/
private Long exp;
/**
* uuid
*/
private String uuid;
/**
* 密码
*/
private String pwd;
/**
* 资源ID
*/
private Long resourceId;
/**
* 组织ID
*/
private Long oid;
/**
* 业务类型
*/
private Integer type;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getCreator() {
return creator;
}
public void setCreator(Long creator) {
this.creator = creator;
}
public Long getTime() {
return time;
}
public void setTime(Long time) {
this.time = time;
}
public Long getExp() {
return exp;
}
public void setExp(Long exp) {
this.exp = exp;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Long getResourceId() {
return resourceId;
}
public void setResourceId(Long resourceId) {
this.resourceId = resourceId;
}
public Long getOid() {
return oid;
}
public void setOid(Long oid) {
this.oid = oid;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
@Override
public String toString() {
return "XpackShare{" +
"id = " + id +
", creator = " + creator +
", time = " + time +
", exp = " + exp +
", uuid = " + uuid +
", pwd = " + pwd +
", resourceId = " + resourceId +
", oid = " + oid +
", type = " + type +
"}";
}
}

View File

@ -0,0 +1,18 @@
package io.dataease.share.dao.auto.mapper;
import io.dataease.share.dao.auto.entity.XpackShare;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author fit2cloud
* @since 2023-09-22
*/
@Mapper
public interface XpackShareMapper extends BaseMapper<XpackShare> {
}

View File

@ -0,0 +1,30 @@
package io.dataease.share.dao.ext.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.dataease.share.dao.ext.po.XpackSharePO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
@Mapper
public interface XpackShareExtMapper {
@Select("""
select
s.id as share_id,
v.id as resource_id,
v.type,
s.creator,
s.time,
s.exp,
v.name
from xpack_share s
left join data_visualization_info v on s.resource_id = v.id
${ew.customSqlSegment}
""")
IPage<XpackSharePO> query(IPage<XpackSharePO> page, @Param("ew") QueryWrapper<Object> ew);
@Select("select type from data_visualization_info where id = #{id}")
String visualizationType(@Param("id") Long id);
}

View File

@ -0,0 +1,31 @@
package io.dataease.share.dao.ext.po;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class XpackSharePO implements Serializable {
@Serial
private static final long serialVersionUID = 7929343371768885789L;
private Long shareId;
private Long resourceId;
private String name;
private String type;
private Long creator;
private Long time;
private Long exp;
}

View File

@ -0,0 +1,201 @@
package io.dataease.share.manage;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.dataease.api.visualization.request.VisualizationWorkbranchQueryRequest;
import io.dataease.api.xpack.share.request.XpackShareProxyRequest;
import io.dataease.api.xpack.share.request.XpackSharePwdValidator;
import io.dataease.api.xpack.share.vo.XpackShareGridVO;
import io.dataease.api.xpack.share.vo.XpackShareProxyVO;
import io.dataease.auth.bo.TokenUserBO;
import io.dataease.constant.AuthConstant;
import io.dataease.constant.BusiResourceEnum;
import io.dataease.exception.DEException;
import io.dataease.license.config.XpackInteract;
import io.dataease.share.dao.auto.mapper.XpackShareMapper;
import io.dataease.utils.*;
import io.dataease.share.dao.auto.entity.XpackShare;
import io.dataease.share.dao.ext.mapper.XpackShareExtMapper;
import io.dataease.share.dao.ext.po.XpackSharePO;
import io.dataease.share.util.LinkTokenUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component("xpackShareManage")
public class XpackShareManage {
@Resource(name = "xpackShareMapper")
private XpackShareMapper xpackShareMapper;
@Resource(name = "xpackShareExtMapper")
private XpackShareExtMapper xpackShareExtMapper;
public XpackShare queryByResource(Long resourceId) {
Long userId = AuthUtils.getUser().getUserId();
QueryWrapper<XpackShare> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("creator", userId);
queryWrapper.eq("resource_id", resourceId);
return xpackShareMapper.selectOne(queryWrapper);
}
public void switcher(Long resourceId) {
XpackShare originData = queryByResource(resourceId);
if (ObjectUtils.isNotEmpty(originData)) {
xpackShareMapper.deleteById(originData.getId());
return;
}
TokenUserBO user = AuthUtils.getUser();
Long userId = user.getUserId();
XpackShare xpackShare = new XpackShare();
xpackShare.setId(IDUtils.snowID());
xpackShare.setCreator(userId);
xpackShare.setTime(System.currentTimeMillis());
xpackShare.setResourceId(resourceId);
xpackShare.setUuid(RandomStringUtils.randomAlphanumeric(8));
xpackShare.setOid(user.getDefaultOid());
String dType = xpackShareExtMapper.visualizationType(resourceId);
xpackShare.setType(StringUtils.equalsIgnoreCase("dataV", dType) ? 2 : 1);
xpackShareMapper.insert(xpackShare);
}
public void editExp(Long resourceId, Long exp) {
XpackShare originData = queryByResource(resourceId);
if (ObjectUtils.isEmpty(originData)) {
DEException.throwException("share instance not exist");
}
originData.setExp(exp);
if (ObjectUtils.isEmpty(exp)) {
originData.setExp(0L);
}
xpackShareMapper.updateById(originData);
}
public void editPwd(Long resourceId, String pwd) {
XpackShare originData = queryByResource(resourceId);
if (ObjectUtils.isEmpty(originData)) {
DEException.throwException("share instance not exist");
}
originData.setPwd(pwd);
xpackShareMapper.updateById(originData);
}
public IPage<XpackSharePO> querySharePage(int goPage, int pageSize, VisualizationWorkbranchQueryRequest request) {
Long uid = AuthUtils.getUser().getUserId();
QueryWrapper<Object> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("s.creator", uid);
if (StringUtils.isNotBlank(request.getType())) {
BusiResourceEnum busiResourceEnum = BusiResourceEnum.valueOf(request.getType().toUpperCase());
if (ObjectUtils.isEmpty(busiResourceEnum)) {
DEException.throwException("type is invalid");
}
String resourceType = convertResourceType(request.getType());
if (StringUtils.isNotBlank(resourceType)) {
queryWrapper.eq("v.type", resourceType);
}
}
if (StringUtils.isNotBlank(request.getKeyword())) {
queryWrapper.like("v.name", request.getKeyword());
}
queryWrapper.orderBy(true, request.isAsc(), "s.time");
Page<XpackSharePO> page = new Page<>(goPage, pageSize);
return xpackShareExtMapper.query(page, queryWrapper);
}
private String convertResourceType(String busiFlag) {
return switch (busiFlag) {
case "panel" -> "dashboard";
case "screen" -> "dataV";
default -> null;
};
}
@XpackInteract(value = "perFilterShareManage", recursion = true)
public IPage<XpackShareGridVO> query(int pageNum, int pageSize, VisualizationWorkbranchQueryRequest request) {
IPage<XpackSharePO> poiPage = proxy().querySharePage(pageNum, pageSize, request);
List<XpackShareGridVO> vos = proxy().formatResult(poiPage.getRecords());
IPage<XpackShareGridVO> ipage = new Page<>();
ipage.setSize(poiPage.getSize());
ipage.setCurrent(poiPage.getCurrent());
ipage.setPages(poiPage.getPages());
ipage.setTotal(poiPage.getTotal());
ipage.setRecords(vos);
return ipage;
}
public List<XpackShareGridVO> formatResult(List<XpackSharePO> pos) {
if (CollectionUtils.isEmpty(pos)) return new ArrayList<>();
return pos.stream().map(po ->
new XpackShareGridVO(
po.getShareId(), po.getResourceId(), po.getName(), po.getCreator().toString(),
po.getTime(), po.getExp(), 9)).toList();
}
private XpackShareManage proxy() {
return CommonBeanFactory.getBean(this.getClass());
}
public XpackShareProxyVO proxyInfo(XpackShareProxyRequest request) {
QueryWrapper<XpackShare> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("uuid", request.getUuid());
XpackShare xpackShare = xpackShareMapper.selectOne(queryWrapper);
if (ObjectUtils.isEmpty(xpackShare))
return null;
String linkToken = LinkTokenUtil.generate(xpackShare.getCreator(), xpackShare.getResourceId(), xpackShare.getExp(), xpackShare.getPwd(), xpackShare.getOid());
HttpServletResponse response = ServletUtils.response();
response.addHeader(AuthConstant.LINK_TOKEN_KEY, linkToken);
Integer type = xpackShare.getType();
String typeText = (ObjectUtils.isNotEmpty(type) && type == 1) ? "dashboard" : "dataV";
return new XpackShareProxyVO(xpackShare.getResourceId(), xpackShare.getCreator(), linkExp(xpackShare), pwdValid(xpackShare, request.getCiphertext()), typeText);
}
private boolean linkExp(XpackShare xpackShare) {
if (ObjectUtils.isEmpty(xpackShare.getExp()) || xpackShare.getExp().equals(0L)) return false;
return System.currentTimeMillis() > xpackShare.getExp();
}
private boolean pwdValid(XpackShare xpackShare, String ciphertext) {
if (StringUtils.isBlank(xpackShare.getPwd())) return true;
if (StringUtils.isBlank(ciphertext)) return false;
String text = RsaUtils.decryptStr(ciphertext);
int len = text.length();
int splitIndex = len - 4;
String pwd = text.substring(splitIndex);
String uuid = text.substring(0, splitIndex);
return StringUtils.equals(xpackShare.getUuid(), uuid) && StringUtils.equals(xpackShare.getPwd(), pwd);
}
public boolean validatePwd(XpackSharePwdValidator validator) {
String ciphertext = RsaUtils.decryptStr(validator.getCiphertext());
int len = ciphertext.length();
int splitIndex = len - 4;
String pwd = ciphertext.substring(splitIndex);
String uuid = ciphertext.substring(0, splitIndex);
QueryWrapper<XpackShare> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("uuid", uuid);
XpackShare xpackShare = xpackShareMapper.selectOne(queryWrapper);
return StringUtils.equals(xpackShare.getUuid(), uuid) && StringUtils.equals(xpackShare.getPwd(), pwd);
}
public Map<String, String> queryRelationByUserId(Long uid) {
QueryWrapper<XpackShare> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("creator", uid);
List<XpackShare> result = xpackShareMapper.selectList(queryWrapper);
if (CollectionUtils.isNotEmpty(result)) {
return result.stream()
.collect(Collectors.toMap(xpackShare -> String.valueOf(xpackShare.getResourceId()), XpackShare::getUuid));
}
return new HashMap<>();
}
}

View File

@ -0,0 +1,76 @@
package io.dataease.share.server;
import io.dataease.api.visualization.request.VisualizationWorkbranchQueryRequest;
import io.dataease.api.xpack.share.XpackShareApi;
import io.dataease.api.xpack.share.request.XpackShareExpRequest;
import io.dataease.api.xpack.share.request.XpackShareProxyRequest;
import io.dataease.api.xpack.share.request.XpackSharePwdRequest;
import io.dataease.api.xpack.share.request.XpackSharePwdValidator;
import io.dataease.api.xpack.share.vo.XpackShareGridVO;
import io.dataease.api.xpack.share.vo.XpackShareProxyVO;
import io.dataease.api.xpack.share.vo.XpackShareVO;
import io.dataease.utils.BeanUtils;
import io.dataease.share.dao.auto.entity.XpackShare;
import io.dataease.share.manage.XpackShareManage;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
@RequestMapping("/share")
@RestController
public class XpackShareServer implements XpackShareApi {
@Resource(name = "xpackShareManage")
private XpackShareManage xpackShareManage;
@Override
public boolean status(Long resourceId) {
return ObjectUtils.isNotEmpty(xpackShareManage.queryByResource(resourceId));
}
@Override
public void switcher(Long resourceId) {
xpackShareManage.switcher(resourceId);
}
@Override
public void editExp(XpackShareExpRequest request) {
xpackShareManage.editExp(request.getResourceId(), request.getExp());
}
@Override
public void editPwd(XpackSharePwdRequest request) {
xpackShareManage.editPwd(request.getResourceId(), request.getPwd());
}
@Override
public XpackShareVO detail(Long resourceId) {
XpackShare xpackShare = xpackShareManage.queryByResource(resourceId);
if (ObjectUtils.isEmpty(xpackShare)) return null;
return BeanUtils.copyBean(new XpackShareVO(), xpackShare);
}
@Override
public List<XpackShareGridVO> query(VisualizationWorkbranchQueryRequest request) {
return xpackShareManage.query(1, 20, request).getRecords();
}
@Override
public XpackShareProxyVO proxyInfo(XpackShareProxyRequest request) {
return xpackShareManage.proxyInfo(request);
}
@Override
public boolean validatePwd(XpackSharePwdValidator validator) {
return xpackShareManage.validatePwd(validator);
}
@Override
public Map<String, String> queryRelationByUserId(@PathVariable("uid") Long uid) {
return xpackShareManage.queryRelationByUserId(uid);
}
}

View File

@ -0,0 +1,23 @@
package io.dataease.share.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
public class LinkTokenUtil {
private static final String defaultPwd = "link-pwd-fit2cloud";
public static String generate(Long uid, Long resourceId, Long exp, String pwd, Long oid) {
pwd = StringUtils.isBlank(pwd) ? defaultPwd : pwd;
Algorithm algorithm = Algorithm.HMAC256(pwd);
JWTCreator.Builder builder = JWT.create();
builder.withClaim("uid", uid).withClaim("resourceId", resourceId).withClaim("oid", oid);
if (ObjectUtils.isNotEmpty(exp) && !exp.equals(0L)) {
builder = builder.withExpiresAt(new Date(exp));
}
return builder.sign(algorithm);
}
}

View File

@ -5,11 +5,11 @@ import java.io.Serializable;
/**
* <p>
* 仪表板模板表
*
* </p>
*
* @author fit2cloud
* @since 2023-11-06
* @since 2024-01-16
*/
@TableName("visualization_template")
public class VisualizationTemplate implements Serializable {
@ -37,7 +37,7 @@ public class VisualizationTemplate implements Serializable {
private Integer level;
/**
* 种类 dataV or dashboard 目录或者文件夹
* 种类 dataV or dashboard 目录或者文件夹
*/
private String dvType;
@ -62,7 +62,7 @@ public class VisualizationTemplate implements Serializable {
private String snapshot;
/**
* 类型 system 系统内置 self 用户自建
* 类型 system 系统内置 self 用户自建
*/
private String templateType;
@ -81,6 +81,11 @@ public class VisualizationTemplate implements Serializable {
*/
private String dynamicData;
/**
* 使用次数
*/
private Integer useCount;
public String getId() {
return id;
}
@ -185,6 +190,14 @@ public class VisualizationTemplate implements Serializable {
this.dynamicData = dynamicData;
}
public Integer getUseCount() {
return useCount;
}
public void setUseCount(Integer useCount) {
this.useCount = useCount;
}
@Override
public String toString() {
return "VisualizationTemplate{" +
@ -201,6 +214,7 @@ public class VisualizationTemplate implements Serializable {
", templateStyle = " + templateStyle +
", templateData = " + templateData +
", dynamicData = " + dynamicData +
", useCount = " + useCount +
"}";
}
}

View File

@ -6,11 +6,11 @@ import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 仪表板模板表 Mapper 接口
* Mapper 接口
* </p>
*
* @author fit2cloud
* @since 2023-11-06
* @since 2024-01-16
*/
@Mapper
public interface VisualizationTemplateMapper extends BaseMapper<VisualizationTemplate> {

View File

@ -121,13 +121,17 @@ public class TemplateCenterManage {
public MarketBaseResponse searchTemplateRecommend() {
MarketTemplateV2BaseResponse v2BaseResponse = null;
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
// 模版市场推荐
try {
Map<String, String> templateParams = sysParameterManage.groupVal("template.");
return baseResponseV2TransRecommend(templateQuery(templateParams), templateParams.get("template.url"));
v2BaseResponse = templateQuery(templateParams);
} catch (Exception e) {
DEException.throwException(e);
}
return null;
// 模版管理使用次数推荐
List<TemplateMarketDTO> manage = searchTemplateFromManage();
return baseResponseV2TransRecommend(v2BaseResponse, manage, templateParams.get("template.url"));
}
public MarketPreviewBaseResponse searchTemplatePreview() {
@ -161,7 +165,7 @@ public class TemplateCenterManage {
}
}
private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse, String url) {
private MarketBaseResponse baseResponseV2TransRecommend(MarketTemplateV2BaseResponse v2BaseResponse,List<TemplateMarketDTO> templateManages, String url) {
Map<String, Long> useTime = coreOptRecentManage.findTemplateRecentUseTime();
List<MarketMetaDataVO> categoryVO = getCategoriesV2().stream().filter(node -> !"全部".equalsIgnoreCase(node.getLabel())).collect(Collectors.toList());
Map<String, String> categoriesMap = categoryVO.stream()
@ -177,6 +181,22 @@ public class TemplateCenterManage {
}
// 最近使用排序
Collections.sort(contents);
Long countDataV = contents.stream().filter(item -> "PANEL".equals(item.getTemplateType())).count();
Long countDashboard = contents.stream().filter(item -> "SCREEN".equals(item.getTemplateType())).count();
List<TemplateMarketDTO> templateDataV = templateManages.stream().filter(item -> "PANEL".equals(item.getTemplateType())).collect(Collectors.toList());
List<TemplateMarketDTO> templateDashboard = templateManages.stream().filter(item -> "SCREEN".equals(item.getTemplateType())).collect(Collectors.toList());
if(countDataV<10){
Long addItemCount = 10 -countDataV;
Long addIndex = templateDataV.size()<addItemCount? templateDataV.size() :addItemCount;
contents.addAll(templateDataV.subList(0,addIndex.intValue()));
}
if(countDashboard<10){
Long addItemCount = 10 -countDashboard;
Long addIndex = templateDashboard.size()<addItemCount? templateDashboard.size() :addItemCount;
contents.addAll(templateDashboard.subList(0,addIndex.intValue()));
}
return new MarketBaseResponse(url, categoryVO, contents);
}

View File

@ -88,7 +88,7 @@ public class VisualizationStoreManage {
return pos.stream().map(po ->
new VisualizationStoreVO(
po.getStoreId(), po.getResourceId(), po.getName(),
po.getType(), po.getCreator().toString(), ObjectUtils.isEmpty(po.getEditor()) ? null : po.getEditor().toString(),
po.getType(), String.valueOf(po.getCreator()), ObjectUtils.isEmpty(po.getEditor()) ? null : String.valueOf(po.getEditor()),
po.getEditTime(), 9)).toList();
}

View File

@ -17,8 +17,10 @@ import io.dataease.chart.manage.ChartViewManege;
import io.dataease.commons.constants.DataVisualizationConstants;
import io.dataease.commons.constants.OptConstants;
import io.dataease.constant.CommonConstants;
import io.dataease.constant.LogOT;
import io.dataease.exception.DEException;
import io.dataease.license.config.XpackInteract;
import io.dataease.log.DeLog;
import io.dataease.model.BusiNodeRequest;
import io.dataease.model.BusiNodeVO;
import io.dataease.operation.manage.CoreOptRecentManage;
@ -89,6 +91,17 @@ public class DataVisualizationServer implements DataVisualizationApi {
@Resource
private VisualizationWatermarkMapper watermarkMapper;
@Override
public DataVisualizationVO findCopyResource(Long dvId, String busiFlag) {
DataVisualizationVO result = findById(dvId, busiFlag);
if (result != null && result.getPid() == -1) {
return result;
} else {
return null;
}
}
@DeLog(id = "#p0", ot = LogOT.READ, stExp = "#p1")
@Override
@XpackInteract(value = "dataVisualizationServer", original = true)
public DataVisualizationVO findById(Long dvId, String busiFlag) {
@ -102,7 +115,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
}
VisualizationWatermark watermark = watermarkMapper.selectById("system_default");
VisualizationWatermarkVO watermarkVO = new VisualizationWatermarkVO();
BeanUtils.copyBean(watermarkVO,watermark);
BeanUtils.copyBean(watermarkVO, watermark);
result.setWatermarkInfo(watermarkVO);
return result;
} else {
@ -111,23 +124,31 @@ public class DataVisualizationServer implements DataVisualizationApi {
return null;
}
@DeLog(id = "#p0.id", pid = "#p0.pid", ot = LogOT.CREATE, stExp = "#p0.type")
@Override
@Transactional
public String saveCanvas(DataVisualizationBaseRequest request) {
DataVisualizationInfo visualizationInfo = new DataVisualizationInfo();
BeanUtils.copyBean(visualizationInfo, request);
visualizationInfo.setNodeType(request.getNodeType() == null ? DataVisualizationConstants.NODE_TYPE.LEAF : request.getNodeType());
if(request.getSelfWatermarkStatus() != null && request.getSelfWatermarkStatus()){
if (request.getSelfWatermarkStatus() != null && request.getSelfWatermarkStatus()) {
visualizationInfo.setSelfWatermarkStatus(1);
}else{
} else {
visualizationInfo.setSelfWatermarkStatus(0);
}
if (DataVisualizationConstants.RESOURCE_OPT_TYPE.COPY.equals(request.getOptType())) {
// 复制更新 新建权限插入
visualizationInfoMapper.deleteById(request.getId());
visualizationInfo.setNodeType(DataVisualizationConstants.NODE_TYPE.LEAF);
}
Long newDvId = coreVisualizationManage.innerSave(visualizationInfo);
request.setId(newDvId);
//保存视图信
chartDataManage.saveChartViewFromVisualization(request.getComponentData(), newDvId, request.getCanvasViewInfo());
return newDvId.toString();
}
@DeLog(id = "#p0.id", ot = LogOT.MODIFY, stExp = "#p0.type")
@Override
@Transactional
public void updateCanvas(DataVisualizationBaseRequest request) {
@ -137,29 +158,24 @@ public class DataVisualizationServer implements DataVisualizationApi {
}
DataVisualizationInfo visualizationInfo = new DataVisualizationInfo();
BeanUtils.copyBean(visualizationInfo, request);
if(request.getSelfWatermarkStatus() != null && request.getSelfWatermarkStatus()){
if (request.getSelfWatermarkStatus() != null && request.getSelfWatermarkStatus()) {
visualizationInfo.setSelfWatermarkStatus(1);
}else{
} else {
visualizationInfo.setSelfWatermarkStatus(0);
}
if(DataVisualizationConstants.RESOURCE_OPT_TYPE.COPY.equals(request.getOptType())){
// 复制更新 新建权限插入
visualizationInfoMapper.deleteById(dvId);
visualizationInfo.setNodeType(DataVisualizationConstants.NODE_TYPE.LEAF);
coreVisualizationManage.innerSave(visualizationInfo);
}else{
// 检查当前节点的pid是否一致如果不一致 需要调用move 接口(预存 可能会出现pid =-1的情况)
if (request.getPid() != -1) {
QueryWrapper<DataVisualizationInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("pid", request.getPid());
queryWrapper.eq("id", dvId);
if (!visualizationInfoMapper.exists(queryWrapper)) {
request.setMoveFromUpdate(true);
coreVisualizationManage.move(request);
}
// 检查当前节点的pid是否一致如果不一致 需要调用move 接口(预存 可能会出现pid =-1的情况)
if (request.getPid() != -1) {
QueryWrapper<DataVisualizationInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("pid", request.getPid());
queryWrapper.eq("id", dvId);
if (!visualizationInfoMapper.exists(queryWrapper)) {
request.setMoveFromUpdate(true);
coreVisualizationManage.move(request);
}
coreVisualizationManage.innerEdit(visualizationInfo);
}
coreVisualizationManage.innerEdit(visualizationInfo);
//保存视图信
chartDataManage.saveChartViewFromVisualization(request.getComponentData(), dvId, request.getCanvasViewInfo());
}
@ -168,6 +184,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
* @Description: 更新基础信息
* 为什么单独接口1.基础信息更新频繁数据且数据载量较小2.防止出现更新过多信息的情况造成视图的误删等操作
*/
@DeLog(id = "#p0.id", ot = LogOT.MODIFY, stExp = "#p0.type")
@Override
@Transactional
public void updateBase(DataVisualizationBaseRequest request) {
@ -181,6 +198,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
/**
* @Description: 逻辑删除可视化信息将delete_flag 置为0
*/
@DeLog(id = "#p0", ot = LogOT.DELETE, stExp = "#p1")
@Transactional
@Override
public void deleteLogic(Long dvId, String busiFlag) {
@ -193,6 +211,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
return coreVisualizationManage.tree(request);
}
@DeLog(id = "#p0.id", pid = "#p0.pid", ot = LogOT.MODIFY, stExp = "#p0.type")
@Transactional
@Override
public void move(DataVisualizationBaseRequest request) {
@ -241,7 +260,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
extDataVisualizationMapper.copyLinkJumpInfo(copyId);
extDataVisualizationMapper.copyLinkJumpTargetInfo(copyId);
DataVisualizationInfo visualizationInfoTarget = new DataVisualizationInfo();
BeanUtils.copyBean(visualizationInfoTarget,newDv);
BeanUtils.copyBean(visualizationInfoTarget, newDv);
visualizationInfoTarget.setPid(-1L);
coreVisualizationManage.preInnerSave(visualizationInfoTarget);
return String.valueOf(newDvId);
@ -271,7 +290,11 @@ public class DataVisualizationServer implements DataVisualizationApi {
name = visualizationTemplate.getName();
dvType = visualizationTemplate.getDvType();
// 模板市场记录
coreOptRecentManage.saveOpt(request.getTemplateId(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE,OptConstants.OPT_TYPE.NEW);
coreOptRecentManage.saveOpt(request.getTemplateId(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE, OptConstants.OPT_TYPE.NEW);
VisualizationTemplate visualizationTemplateUpdate = new VisualizationTemplate();
visualizationTemplateUpdate.setId(visualizationTemplate.getId());
visualizationTemplateUpdate.setUseCount(visualizationTemplate.getUseCount() == null ? 0 : visualizationTemplate.getUseCount() + 1);
templateMapper.updateById(visualizationTemplateUpdate);
} else if (DataVisualizationConstants.NEW_PANEL_FROM.NEW_OUTER_TEMPLATE.equals(newFrom)) {
templateStyle = request.getCanvasStyleData();
templateData = request.getComponentData();
@ -291,7 +314,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
name = templateFileInfo.getName();
dvType = templateFileInfo.getDvType();
// 模板市场记录
coreOptRecentManage.saveOpt(request.getResourceName(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE,OptConstants.OPT_TYPE.NEW);
coreOptRecentManage.saveOpt(request.getResourceName(), OptConstants.OPT_RESOURCE_TYPE.TEMPLATE, OptConstants.OPT_TYPE.NEW);
}
// 解析动态数据
Map<String, String> dynamicDataMap = JsonUtil.parseObject(dynamicData, Map.class);
@ -302,7 +325,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
String originViewId = entry.getKey();
String originViewData = JsonUtil.toJSONString(entry.getValue()).toString();
ChartViewDTO chartView = JsonUtil.parseObject(originViewData, ChartViewDTO.class);
if(chartView == null){
if (chartView == null) {
continue;
}
Long newViewId = IDUtils.snowID();

View File

@ -46,6 +46,7 @@ quartz:
dataease:
version: '@project.version@'
origin-list: http://192.168.2.70:9080
apisix-api:
domain: http://192.168.0.121:9180
key: edd1c9f034335f136f87ad84b625c8f1

View File

@ -1,19 +1,4 @@
DROP TABLE IF EXISTS `visualization_template`;
CREATE TABLE `visualization_template` (
`id` varchar(50) NOT NULL COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '名称',
`pid` varchar(255) DEFAULT NULL COMMENT '父级id',
`level` int DEFAULT NULL COMMENT '层级',
`dv_type` varchar(255) DEFAULT NULL COMMENT '模板种类 dataV or dashboard 目录或者文件夹',
`node_type` varchar(255) DEFAULT NULL COMMENT '节点类型 folder or panel 目录或者文件夹',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint DEFAULT NULL COMMENT '创建时间',
`snapshot` longtext COMMENT '缩略图',
`template_type` varchar(255) DEFAULT NULL COMMENT '模板类型 system 系统内置 self 用户自建 ',
`template_style` longtext COMMENT 'template 样式',
`template_data` longtext COMMENT 'template 数据',
`dynamic_data` longtext COMMENT '预存数据',
PRIMARY KEY (`id`)
CREATE TABLE `visualization_template`
(
`id` varchar(50) NOT NULL COMMENT '主键',
@ -85,7 +70,8 @@ VALUES (30, 0, 1, 'toolbox', null, 7, 'icon_template', '/toolbox', 1, 1, 0);
INSERT INTO `core_menu`
VALUES (31, 30, 2, 'template-setting', 'toolbox/template-setting', 1, 'icon_template', '/template-setting', 0, 1, 1);
ALTER TABLE core_opt_recent ADD `resource_name` varchar(255) NULL COMMENT '资源名称';
ALTER TABLE core_opt_recent
ADD `resource_name` varchar(255) NULL COMMENT '资源名称';
DROP TABLE IF EXISTS `core_area_custom`;
CREATE TABLE `core_area_custom`

View File

@ -1,177 +1,211 @@
ALTER TABLE `QRTZ_BLOB_TRIGGERS` COMMENT = '自定义触发器存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_CALENDARS` COMMENT = 'Quartz日历开源作业调度框架Quartz';
ALTER TABLE `QRTZ_CRON_TRIGGERS` COMMENT = 'CronTrigger存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_FIRED_TRIGGERS` COMMENT = '存储已经触发的trigger相关信息开源作业调度框架Quartz';
ALTER TABLE `QRTZ_JOB_DETAILS` COMMENT = '存储jobDetails信息开源作业调度框架Quartz';
ALTER TABLE `QRTZ_LOCKS` COMMENT = 'Quartz锁表为多个节点调度提供分布式锁开源作业调度框架Quartz';
ALTER TABLE `QRTZ_PAUSED_TRIGGER_GRPS` COMMENT = '存放暂停掉的触发器开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SCHEDULER_STATE` COMMENT = '存储所有节点的scheduler开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SIMPLE_TRIGGERS` COMMENT = 'SimpleTrigger存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SIMPROP_TRIGGERS` COMMENT = '存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器开源作业调度框架Quartz';
ALTER TABLE `QRTZ_TRIGGERS` COMMENT = '存储定义的trigger开源作业调度框架Quartz';
ALTER TABLE `area` COMMENT = '地图区域表';
ALTER TABLE `core_area_custom` COMMENT = '自定义地图区域信息表';
ALTER TABLE `core_chart_view` COMMENT = '组件视图表';
ALTER TABLE `core_dataset_group` COMMENT = '数据集分组表';
ALTER TABLE `core_dataset_table` COMMENT = 'table数据集';
ALTER TABLE `core_dataset_table_field` COMMENT = 'table数据集表字段';
ALTER TABLE `core_dataset_table_sql_log` COMMENT = 'table数据集查询sql日志';
ALTER TABLE `core_datasource` COMMENT = '数据源表';
ALTER TABLE `core_datasource_task` COMMENT = '数据源定时同步任务';
ALTER TABLE `core_datasource_task_log` COMMENT = '数据源定时同步任务执行日志';
ALTER TABLE `core_de_engine` COMMENT = '数据引擎';
ALTER TABLE `core_driver` COMMENT = '驱动';
ALTER TABLE `core_driver_jar` COMMENT = '驱动详情';
ALTER TABLE `core_menu` COMMENT = '路由菜单';
ALTER TABLE `core_opt_recent` COMMENT = '可视化资源表';
ALTER TABLE `core_rsa` COMMENT = 'rsa 密钥表';
ALTER TABLE `core_store` COMMENT = '用户收藏表';
ALTER TABLE `core_sys_setting` COMMENT = '系统设置表';
ALTER TABLE `data_visualization_info` COMMENT = '可视化大屏信息表';
ALTER TABLE `de_standalone_version` COMMENT = '数据库版本变更记录表';
ALTER TABLE `license` COMMENT = '企业版许可证信息表';
ALTER TABLE `per_api_key` COMMENT = 'API Key 密钥表';
ALTER TABLE `per_auth_busi_role` COMMENT = '角色资源权限配置';
ALTER TABLE `per_auth_busi_user` COMMENT = '用户资源权限配置';
ALTER TABLE `per_auth_menu` COMMENT = '菜单资源权限配置';
ALTER TABLE `per_busi_resource` COMMENT = '企业资源';
ALTER TABLE `per_dataset_column_permissions` COMMENT = '数据集列权限';
ALTER TABLE `per_dataset_row_permissions_tree` COMMENT = '数据集行权限';
ALTER TABLE `per_embedded_instance` COMMENT = '嵌入式应用';
ALTER TABLE `per_menu_resource` COMMENT = '菜单资源';
ALTER TABLE `per_org` COMMENT = '组织机构';
ALTER TABLE `per_role` COMMENT = '角色';
ALTER TABLE `per_sys_setting` COMMENT = '系统设置表';
ALTER TABLE `per_user` COMMENT = '用户表';
ALTER TABLE `per_user_role` COMMENT = '用户角色表';
ALTER TABLE `visualization_background` COMMENT = '边框背景表';
ALTER TABLE `visualization_background_image` COMMENT = '背景图';
ALTER TABLE `visualization_link_jump` COMMENT = '跳转记录表';
ALTER TABLE `visualization_link_jump_info` COMMENT = '跳转配置表';
ALTER TABLE `visualization_link_jump_target_view_info` COMMENT = '跳转目标仪表板视图字段配置表';
ALTER TABLE `visualization_linkage` COMMENT = '联动记录表';
ALTER TABLE `visualization_linkage_field` COMMENT = '联动字段';
ALTER TABLE `visualization_subject` COMMENT = '主题表';
ALTER TABLE `visualization_template_extend_data` COMMENT = '模板视图明细信息表';
ALTER TABLE `xpack_setting_authentication` COMMENT = '认证设置';
ALTER TABLE `xpack_share` COMMENT = '公共链接';
COMMENT ON TABLE `QRTZ_BLOB_TRIGGERS`
IS '自定义触发器存储开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_CALENDARS`
IS 'Quartz日历开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_CRON_TRIGGERS`
IS 'CronTrigger存储开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_FIRED_TRIGGERS`
IS '存储已经触发的trigger相关信息开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_JOB_DETAILS`
IS '存储jobDetails信息开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_LOCKS`
IS 'Quartz锁表为多个节点调度提供分布式锁开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_PAUSED_TRIGGER_GRPS`
IS '存放暂停掉的触发器开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_SCHEDULER_STATE`
IS '存储所有节点的scheduler开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_SIMPLE_TRIGGERS`
IS 'SimpleTrigger存储开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_SIMPROP_TRIGGERS`
IS '存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器开源作业调度框架Quartz';
COMMENT ON TABLE `QRTZ_TRIGGERS`
IS '存储定义的trigger开源作业调度框架Quartz';
COMMENT ON TABLE `area`
IS '地图区域表';
COMMENT ON TABLE `core_area_custom`
IS '自定义地图区域信息表';
COMMENT ON TABLE `core_chart_view`
IS '组件视图表';
COMMENT ON TABLE `core_dataset_group`
IS '数据集分组表';
COMMENT ON TABLE `core_dataset_table`
IS 'table数据集';
COMMENT ON TABLE `core_dataset_table_field`
IS 'table数据集表字段';
COMMENT ON TABLE `core_dataset_table_sql_log`
IS 'table数据集查询sql日志';
COMMENT ON TABLE `core_datasource`
IS '数据源表';
COMMENT ON TABLE `core_datasource_task`
IS '数据源定时同步任务';
COMMENT ON TABLE `core_datasource_task_log`
IS '数据源定时同步任务执行日志';
COMMENT ON TABLE `core_de_engine`
IS '数据引擎';
COMMENT ON TABLE `core_driver`
IS '驱动';
COMMENT ON TABLE `core_driver_jar`
IS '驱动详情';
COMMENT ON TABLE `core_menu`
IS '路由菜单';
COMMENT ON TABLE `core_opt_recent`
IS '可视化资源表';
COMMENT ON TABLE `core_rsa`
IS 'rsa 密钥表';
COMMENT ON TABLE `core_store`
IS '用户收藏表';
COMMENT ON TABLE `core_sys_setting`
IS '系统设置表';
COMMENT ON TABLE `data_visualization_info`
IS '可视化大屏信息表';
COMMENT ON TABLE `visualization_background`
IS '边框背景表';
COMMENT ON TABLE `visualization_background_image`
IS '背景图';
COMMENT ON TABLE `visualization_link_jump`
IS '跳转记录表';
COMMENT ON TABLE `visualization_link_jump_info`
IS '跳转配置表';
COMMENT ON TABLE `visualization_link_jump_target_view_info`
IS '跳转目标仪表板视图字段配置表';
COMMENT ON TABLE `visualization_linkage`
IS '联动记录表';
COMMENT ON TABLE `visualization_linkage_field`
IS '联动字段';
COMMENT ON TABLE `visualization_subject`
IS '主题表';
COMMENT ON TABLE `visualization_template_extend_data`
IS '模板视图明细信息表';
ALTER TABLE `core_dataset_group`
MODIFY COLUMN `qrtz_instance` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'Quartz 实例 ID' AFTER `create_time`;
MODIFY COLUMN `qrtz_instance` varchar(1024) NULL DEFAULT NULL COMMENT 'Quartz 实例 ID';
ALTER TABLE `core_dataset_table_field`
MODIFY COLUMN `size` int(0) NULL DEFAULT NULL COMMENT '字段长度允许为空默认0' AFTER `type`,
MODIFY COLUMN `date_format` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '时间字段类型' AFTER `accuracy`;
MODIFY COLUMN `size` int(0) NULL DEFAULT NULL COMMENT '字段长度允许为空默认0';
ALTER TABLE `core_dataset_table_field`
MODIFY COLUMN `date_format` varchar(255) NULL DEFAULT NULL COMMENT '时间字段类型';
ALTER TABLE `core_datasource_task`
MODIFY COLUMN `extra_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '额外数据' AFTER `last_exec_status`;
MODIFY COLUMN `extra_data` longtext NULL COMMENT '额外数据';
ALTER TABLE `core_datasource_task_log`
MODIFY COLUMN `trigger_type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新频率类型' AFTER `create_time`;
MODIFY COLUMN `trigger_type` varchar(45) NULL DEFAULT NULL COMMENT '更新频率类型';
ALTER TABLE `core_driver_jar`
MODIFY COLUMN `trans_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '替换后的 jar 包名称' AFTER `driver_class`,
MODIFY COLUMN `is_trans_name` tinyint(1) NULL DEFAULT NULL COMMENT '是否将上传 jar 包替换了名称1-0-' AFTER `trans_name`;
MODIFY COLUMN `trans_name` varchar(255) NULL DEFAULT NULL COMMENT '替换后的 jar 包名称';
ALTER TABLE `core_driver_jar`
MODIFY COLUMN `is_trans_name` tinyint(1) NULL DEFAULT NULL COMMENT '是否将上传 jar 包替换了名称1-0-';
ALTER TABLE `core_rsa`
MODIFY COLUMN `aes_key` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AES 加密算法的 key' AFTER `create_time`;
MODIFY COLUMN `aes_key` text NOT NULL COMMENT 'AES 加密算法的 key';
ALTER TABLE `data_visualization_info`
MODIFY COLUMN `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键' FIRST;
ALTER TABLE `de_standalone_version`
MODIFY COLUMN `installed_rank` int(0) NOT NULL COMMENT '执行顺序主键' FIRST,
MODIFY COLUMN `version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '版本' AFTER `installed_rank`,
MODIFY COLUMN `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '描述' AFTER `version`,
MODIFY COLUMN `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '类型' AFTER `description`,
MODIFY COLUMN `script` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '脚本名称' AFTER `type`,
MODIFY COLUMN `checksum` int(0) NULL DEFAULT NULL COMMENT '脚本内容一致性校验码' AFTER `script`,
MODIFY COLUMN `installed_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '执行用户' AFTER `checksum`,
MODIFY COLUMN `installed_on` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '执行时间' AFTER `installed_by`,
MODIFY COLUMN `execution_time` int(0) NOT NULL COMMENT '执行时长' AFTER `installed_on`,
MODIFY COLUMN `success` tinyint(1) NOT NULL COMMENT '状态1-成功0-失败' AFTER `execution_time`;
ALTER TABLE `license`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `update_time` bigint(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `id`,
MODIFY COLUMN `license` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT 'license' AFTER `update_time`,
MODIFY COLUMN `f2c_license` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT 'F2C License' AFTER `license`;
ALTER TABLE `per_dataset_column_permissions`
MODIFY COLUMN `update_time` bigint(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `white_list_user`;
ALTER TABLE `per_dataset_row_permissions_tree`
MODIFY COLUMN `update_time` bigint(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `white_list_dept`;
ALTER TABLE `per_user`
MODIFY COLUMN `pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码' AFTER `account`;
MODIFY COLUMN `id` varchar(50) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_background`
MODIFY COLUMN `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称' AFTER `id`,
MODIFY COLUMN `classification` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分类名' AFTER `name`,
MODIFY COLUMN `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '内容' AFTER `classification`,
MODIFY COLUMN `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注' AFTER `content`,
MODIFY COLUMN `sort` int(0) NULL DEFAULT NULL COMMENT '排序' AFTER `remark`,
MODIFY COLUMN `upload_time` bigint(0) NULL DEFAULT NULL COMMENT '上传时间' AFTER `sort`,
MODIFY COLUMN `base_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所在目录地址' AFTER `upload_time`,
MODIFY COLUMN `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图片url' AFTER `base_url`;
MODIFY COLUMN `id` varchar(64) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_background`
MODIFY COLUMN `name` varchar(255) NULL DEFAULT NULL COMMENT '名称';
ALTER TABLE `visualization_background`
MODIFY COLUMN `classification` varchar(255) NOT NULL COMMENT '分类名';
ALTER TABLE `visualization_background`
MODIFY COLUMN `content` longtext NULL COMMENT '内容';
ALTER TABLE `visualization_background`
MODIFY COLUMN `remark` varchar(255) NULL DEFAULT NULL COMMENT '备注';
ALTER TABLE `visualization_background`
MODIFY COLUMN `sort` int(0) NULL DEFAULT NULL COMMENT '排序';
ALTER TABLE `visualization_background`
MODIFY COLUMN `upload_time` bigint(0) NULL DEFAULT NULL COMMENT '上传时间';
ALTER TABLE `visualization_background`
MODIFY COLUMN `base_url` varchar(255) NULL DEFAULT NULL COMMENT '所在目录地址';
ALTER TABLE `visualization_background`
MODIFY COLUMN `url` varchar(255) NULL DEFAULT NULL COMMENT '图片url';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称' AFTER `id`,
MODIFY COLUMN `classification` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分类名' AFTER `name`,
MODIFY COLUMN `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '内容' AFTER `classification`,
MODIFY COLUMN `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注' AFTER `content`,
MODIFY COLUMN `sort` int(0) NULL DEFAULT NULL COMMENT '排序' AFTER `remark`,
MODIFY COLUMN `upload_time` bigint(0) NULL DEFAULT NULL COMMENT '上传时间' AFTER `sort`,
MODIFY COLUMN `base_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所在目录地址' AFTER `upload_time`,
MODIFY COLUMN `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图片url' AFTER `base_url`;
MODIFY COLUMN `id` varchar(64) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `name` varchar(255) NULL DEFAULT NULL COMMENT '名称';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `classification` varchar(255) NOT NULL COMMENT '分类名';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `content` longtext NULL COMMENT '内容';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `remark` varchar(255) NULL DEFAULT NULL COMMENT '备注';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `sort` int(0) NULL DEFAULT NULL COMMENT '排序';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `upload_time` bigint(0) NULL DEFAULT NULL COMMENT '上传时间';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `base_url` varchar(255) NULL DEFAULT NULL COMMENT '所在目录地址';
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `url` varchar(255) NULL DEFAULT NULL COMMENT '图片url';
ALTER TABLE `visualization_link_jump`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源' AFTER `checked`,
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_link_jump`
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源';
ALTER TABLE `visualization_link_jump`
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID';
ALTER TABLE `visualization_link_jump_info`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源' AFTER `attach_params`,
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_link_jump_info`
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源';
ALTER TABLE `visualization_link_jump_info`
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID';
ALTER TABLE `visualization_link_jump_target_view_info`
MODIFY COLUMN `target_id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `link_jump_info_id` bigint(0) NULL DEFAULT NULL COMMENT 'visualization_link_jump_info 表的 ID' AFTER `target_id`,
MODIFY COLUMN `target_view_id` bigint(0) NULL DEFAULT NULL COMMENT '目标视图ID' AFTER `source_field_active_id`,
MODIFY COLUMN `target_field_id` bigint(0) NULL DEFAULT NULL COMMENT '目标字段ID' AFTER `target_view_id`,
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源' AFTER `target_field_id`,
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `target_id` bigint(0) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_link_jump_target_view_info`
MODIFY COLUMN `link_jump_info_id` bigint(0) NULL DEFAULT NULL COMMENT 'visualization_link_jump_info 表的 ID';
ALTER TABLE `visualization_link_jump_target_view_info`
MODIFY COLUMN `target_view_id` bigint(0) NULL DEFAULT NULL COMMENT '目标视图ID';
ALTER TABLE `visualization_link_jump_target_view_info`
MODIFY COLUMN `target_field_id` bigint(0) NULL DEFAULT NULL COMMENT '目标字段ID';
ALTER TABLE `visualization_link_jump_target_view_info`
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源';
ALTER TABLE `visualization_link_jump_target_view_info`
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID';
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `dv_id` bigint(0) NULL DEFAULT NULL COMMENT '联动大屏/仪表板ID' AFTER `id`,
MODIFY COLUMN `ext1` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '扩展字段1' AFTER `linkage_active`,
MODIFY COLUMN `ext2` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '扩展字段2' AFTER `ext1`,
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源' AFTER `ext2`,
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `dv_id` bigint(0) NULL DEFAULT NULL COMMENT '联动大屏/仪表板ID';
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `ext1` varchar(2000) NULL DEFAULT NULL COMMENT '扩展字段1';
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `ext2` varchar(2000) NULL DEFAULT NULL COMMENT '扩展字段2';
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源';
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID';
ALTER TABLE `visualization_linkage_field`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源' AFTER `update_time`,
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_linkage_field`
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源';
ALTER TABLE `visualization_linkage_field`
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID';
ALTER TABLE `visualization_subject`
MODIFY COLUMN `create_num` int(0) NOT NULL DEFAULT 0 COMMENT '创建序号' AFTER `cover_url`;
MODIFY COLUMN `create_num` int(0) NOT NULL DEFAULT 0 COMMENT '创建序号';
ALTER TABLE `visualization_template_category`
MODIFY COLUMN `template_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模版类型 system 系统内置 self 用户自建' AFTER `snapshot`;
MODIFY COLUMN `template_type` varchar(255) NULL DEFAULT NULL COMMENT '模版类型 system 系统内置 self 用户自建';
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `dv_id` bigint(0) NULL DEFAULT NULL COMMENT '模板ID' AFTER `id`,
MODIFY COLUMN `view_id` bigint(0) NULL DEFAULT NULL COMMENT '视图ID' AFTER `dv_id`,
MODIFY COLUMN `view_details` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '视图详情' AFTER `view_id`,
MODIFY COLUMN `copy_from` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '复制来源' AFTER `view_details`,
MODIFY COLUMN `copy_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键';
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `dv_id` bigint(0) NULL DEFAULT NULL COMMENT '模板ID';
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `view_id` bigint(0) NULL DEFAULT NULL COMMENT '视图ID';
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `view_details` longtext NULL COMMENT '视图详情';
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `copy_from` varchar(255) NULL DEFAULT NULL COMMENT '复制来源';
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `copy_id` varchar(255) NULL DEFAULT NULL COMMENT '复制来源ID';
ALTER TABLE `core_opt_recent`
MODIFY COLUMN `resource_type` int(0) NOT NULL COMMENT '资源类型 1-可视化资源 2-仪表板 3-数据大屏 4-数据集 5-数据源 6-模板' AFTER `uid`;
MODIFY COLUMN `resource_type` int(0) NOT NULL COMMENT '资源类型 1-可视化资源 2-仪表板 3-数据大屏 4-数据集 5-数据源 6-模板';

View File

@ -1,14 +1,25 @@
DROP TABLE IF EXISTS `visualization_watermark`;
CREATE TABLE `visualization_watermark` (
`id` varchar(50) NOT NULL COMMENT '主键',
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
`setting_content` longtext COMMENT '设置内容',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint(13) DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) COMMENT='仪表板水印设置表';
CREATE TABLE `visualization_watermark`
(
`id` varchar(50) NOT NULL COMMENT '主键',
`version` varchar(255) DEFAULT NULL COMMENT '版本号',
`setting_content` longtext COMMENT '设置内容',
`create_by` varchar(255) DEFAULT NULL COMMENT '创建人',
`create_time` bigint(13) DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) COMMENT ='仪表板水印设置表';
INSERT INTO `visualization_watermark` (`id`, `version`, `setting_content`, `create_by`, `create_time`) VALUES ('system_default', '1.0', '{\"enable\":false,\"enablePanelCustom\":true,\"type\":\"custom\",\"content\":\"水印\",\"watermark_color\":\"#DD1010\",\"watermark_x_space\":12,\"watermark_y_space\":36,\"watermark_fontsize\":15}', 'admin', NULL);
INSERT INTO `visualization_watermark` (`id`, `version`, `setting_content`, `create_by`, `create_time`)
VALUES ('system_default', '1.0',
'{\"enable\":false,\"enablePanelCustom\":true,\"type\":\"custom\",\"content\":\"水印\",\"watermark_color\":\"#DD1010\",\"watermark_x_space\":12,\"watermark_y_space\":36,\"watermark_fontsize\":15}',
'admin', NULL);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`)
VALUES (9, 'basic.frontTimeOut', '60', 'text', 1);
ALTER TABLE `visualization_template`
ADD COLUMN `use_count` int NULL DEFAULT 0 COMMENT '使用次数';
update visualization_template set use_count = 0;
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (9, 'basic.frontTimeOut', '60', 'text', 1);

View File

@ -1,132 +1,142 @@
ALTER TABLE `QRTZ_BLOB_TRIGGERS` COMMENT = '自定义触发器存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_CALENDARS` COMMENT = 'Quartz日历开源作业调度框架Quartz';
ALTER TABLE `QRTZ_CRON_TRIGGERS` COMMENT = 'CronTrigger存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_FIRED_TRIGGERS` COMMENT = '存储已经触发的trigger相关信息开源作业调度框架Quartz';
ALTER TABLE `QRTZ_JOB_DETAILS` COMMENT = '存储jobDetails信息开源作业调度框架Quartz';
ALTER TABLE `QRTZ_LOCKS` COMMENT = 'Quartz锁表为多个节点调度提供分布式锁开源作业调度框架Quartz';
ALTER TABLE `QRTZ_PAUSED_TRIGGER_GRPS` COMMENT = '存放暂停掉的触发器开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SCHEDULER_STATE` COMMENT = '存储所有节点的scheduler开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SIMPLE_TRIGGERS` COMMENT = 'SimpleTrigger存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SIMPROP_TRIGGERS` COMMENT = '存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器开源作业调度框架Quartz';
ALTER TABLE `QRTZ_TRIGGERS` COMMENT = '存储定义的trigger开源作业调度框架Quartz';
ALTER TABLE `area` COMMENT = '地图区域表';
ALTER TABLE `core_area_custom` COMMENT = '自定义地图区域信息表';
ALTER TABLE `core_chart_view` COMMENT = '组件视图表';
ALTER TABLE `core_dataset_group` COMMENT = '数据集分组表';
ALTER TABLE `core_dataset_table` COMMENT = 'table数据集';
ALTER TABLE `core_dataset_table_field` COMMENT = 'table数据集表字段';
ALTER TABLE `core_dataset_table_sql_log` COMMENT = 'table数据集查询sql日志';
ALTER TABLE `core_datasource` COMMENT = '数据源表';
ALTER TABLE `core_datasource_task` COMMENT = '数据源定时同步任务';
ALTER TABLE `core_datasource_task_log` COMMENT = '数据源定时同步任务执行日志';
ALTER TABLE `core_de_engine` COMMENT = '数据引擎';
ALTER TABLE `core_driver` COMMENT = '驱动';
ALTER TABLE `core_driver_jar` COMMENT = '驱动详情';
ALTER TABLE `core_menu` COMMENT = '路由菜单';
ALTER TABLE `core_opt_recent` COMMENT = '可视化资源表';
ALTER TABLE `core_rsa` COMMENT = 'rsa 密钥表';
ALTER TABLE `core_store` COMMENT = '用户收藏表';
ALTER TABLE `core_sys_setting` COMMENT = '系统设置表';
ALTER TABLE `data_visualization_info` COMMENT = '可视化大屏信息表';
ALTER TABLE `de_standalone_version` COMMENT = '数据库版本变更记录表';
ALTER TABLE `license` COMMENT = '企业版许可证信息表';
ALTER TABLE `per_api_key` COMMENT = 'API Key 密钥表';
ALTER TABLE `per_auth_busi_role` COMMENT = '角色资源权限配置';
ALTER TABLE `per_auth_busi_user` COMMENT = '用户资源权限配置';
ALTER TABLE `per_auth_menu` COMMENT = '菜单资源权限配置';
ALTER TABLE `per_busi_resource` COMMENT = '企业资源';
ALTER TABLE `per_dataset_column_permissions` COMMENT = '数据集列权限';
ALTER TABLE `per_dataset_row_permissions_tree` COMMENT = '数据集行权限';
ALTER TABLE `per_embedded_instance` COMMENT = '嵌入式应用';
ALTER TABLE `per_menu_resource` COMMENT = '菜单资源';
ALTER TABLE `per_org` COMMENT = '组织机构';
ALTER TABLE `per_role` COMMENT = '角色';
ALTER TABLE `per_sys_setting` COMMENT = '系统设置表';
ALTER TABLE `per_user` COMMENT = '用户表';
ALTER TABLE `per_user_role` COMMENT = '用户角色表';
ALTER TABLE `visualization_background` COMMENT = '边框背景表';
ALTER TABLE `visualization_background_image` COMMENT = '背景图';
ALTER TABLE `visualization_link_jump` COMMENT = '跳转记录表';
ALTER TABLE `visualization_link_jump_info` COMMENT = '跳转配置表';
ALTER TABLE `visualization_link_jump_target_view_info` COMMENT = '跳转目标仪表板视图字段配置表';
ALTER TABLE `visualization_linkage` COMMENT = '联动记录表';
ALTER TABLE `visualization_linkage_field` COMMENT = '联动字段';
ALTER TABLE `visualization_subject` COMMENT = '主题表';
ALTER TABLE `visualization_template_extend_data` COMMENT = '模板视图明细信息表';
ALTER TABLE `xpack_setting_authentication` COMMENT = '认证设置';
ALTER TABLE `xpack_share` COMMENT = '公共链接';
ALTER TABLE `QRTZ_BLOB_TRIGGERS`
COMMENT = '自定义触发器存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_CALENDARS`
COMMENT = 'Quartz日历开源作业调度框架Quartz';
ALTER TABLE `QRTZ_CRON_TRIGGERS`
COMMENT = 'CronTrigger存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_FIRED_TRIGGERS`
COMMENT = '存储已经触发的trigger相关信息开源作业调度框架Quartz';
ALTER TABLE `QRTZ_JOB_DETAILS`
COMMENT = '存储jobDetails信息开源作业调度框架Quartz';
ALTER TABLE `QRTZ_LOCKS`
COMMENT = 'Quartz锁表为多个节点调度提供分布式锁开源作业调度框架Quartz';
ALTER TABLE `QRTZ_PAUSED_TRIGGER_GRPS`
COMMENT = '存放暂停掉的触发器开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SCHEDULER_STATE`
COMMENT = '存储所有节点的scheduler开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SIMPLE_TRIGGERS`
COMMENT = 'SimpleTrigger存储开源作业调度框架Quartz';
ALTER TABLE `QRTZ_SIMPROP_TRIGGERS`
COMMENT = '存储CalendarIntervalTrigger和DailyTimeIntervalTrigger两种类型的触发器开源作业调度框架Quartz';
ALTER TABLE `QRTZ_TRIGGERS`
COMMENT = '存储定义的trigger开源作业调度框架Quartz';
ALTER TABLE `area`
COMMENT = '地图区域表';
ALTER TABLE `core_area_custom`
COMMENT = '自定义地图区域信息表';
ALTER TABLE `core_chart_view`
COMMENT = '组件视图表';
ALTER TABLE `core_dataset_group`
COMMENT = '数据集分组表';
ALTER TABLE `core_dataset_table`
COMMENT = 'table数据集';
ALTER TABLE `core_dataset_table_field`
COMMENT = 'table数据集表字段';
ALTER TABLE `core_dataset_table_sql_log`
COMMENT = 'table数据集查询sql日志';
ALTER TABLE `core_datasource`
COMMENT = '数据源表';
ALTER TABLE `core_datasource_task`
COMMENT = '数据源定时同步任务';
ALTER TABLE `core_datasource_task_log`
COMMENT = '数据源定时同步任务执行日志';
ALTER TABLE `core_de_engine`
COMMENT = '数据引擎';
ALTER TABLE `core_driver`
COMMENT = '驱动';
ALTER TABLE `core_driver_jar`
COMMENT = '驱动详情';
ALTER TABLE `core_menu`
COMMENT = '路由菜单';
ALTER TABLE `core_opt_recent`
COMMENT = '可视化资源表';
ALTER TABLE `core_rsa`
COMMENT = 'rsa 密钥表';
ALTER TABLE `core_store`
COMMENT = '用户收藏表';
ALTER TABLE `core_sys_setting`
COMMENT = '系统设置表';
ALTER TABLE `data_visualization_info`
COMMENT = '可视化大屏信息表';
ALTER TABLE `de_standalone_version`
COMMENT = '数据库版本变更记录表';
ALTER TABLE `visualization_background`
COMMENT = '边框背景表';
ALTER TABLE `visualization_background_image`
COMMENT = '背景图';
ALTER TABLE `visualization_link_jump`
COMMENT = '跳转记录表';
ALTER TABLE `visualization_link_jump_info`
COMMENT = '跳转配置表';
ALTER TABLE `visualization_link_jump_target_view_info`
COMMENT = '跳转目标仪表板视图字段配置表';
ALTER TABLE `visualization_linkage`
COMMENT = '联动记录表';
ALTER TABLE `visualization_linkage_field`
COMMENT = '联动字段';
ALTER TABLE `visualization_subject`
COMMENT = '主题表';
ALTER TABLE `visualization_template_extend_data`
COMMENT = '模板视图明细信息表';
ALTER TABLE `core_dataset_group`
MODIFY COLUMN `qrtz_instance` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'Quartz 实例 ID' AFTER `create_time`;
MODIFY COLUMN `qrtz_instance` varchar(1024) NULL DEFAULT NULL COMMENT 'Quartz 实例 ID' AFTER `create_time`;
ALTER TABLE `core_dataset_table_field`
MODIFY COLUMN `size` int(0) NULL DEFAULT NULL COMMENT '字段长度允许为空默认0' AFTER `type`,
MODIFY COLUMN `date_format` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '时间字段类型' AFTER `accuracy`;
MODIFY COLUMN `date_format` varchar(255) NULL DEFAULT NULL COMMENT '时间字段类型' AFTER `accuracy`;
ALTER TABLE `core_datasource_task`
MODIFY COLUMN `extra_data` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '额外数据' AFTER `last_exec_status`;
MODIFY COLUMN `extra_data` longtext NULL COMMENT '额外数据' AFTER `last_exec_status`;
ALTER TABLE `core_datasource_task_log`
MODIFY COLUMN `trigger_type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新频率类型' AFTER `create_time`;
MODIFY COLUMN `trigger_type` varchar(45) NULL DEFAULT NULL COMMENT '更新频率类型' AFTER `create_time`;
ALTER TABLE `core_driver_jar`
MODIFY COLUMN `trans_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '替换后的 jar 包名称' AFTER `driver_class`,
MODIFY COLUMN `trans_name` varchar(255) NULL DEFAULT NULL COMMENT '替换后的 jar 包名称' AFTER `driver_class`,
MODIFY COLUMN `is_trans_name` tinyint(1) NULL DEFAULT NULL COMMENT '是否将上传 jar 包替换了名称1-0-' AFTER `trans_name`;
ALTER TABLE `core_rsa`
MODIFY COLUMN `aes_key` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AES 加密算法的 key' AFTER `create_time`;
MODIFY COLUMN `aes_key` text NOT NULL COMMENT 'AES 加密算法的 key' AFTER `create_time`;
ALTER TABLE `data_visualization_info`
MODIFY COLUMN `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键' FIRST;
MODIFY COLUMN `id` varchar(50) NOT NULL COMMENT '主键' FIRST;
ALTER TABLE `de_standalone_version`
MODIFY COLUMN `installed_rank` int(0) NOT NULL COMMENT '执行顺序主键' FIRST,
MODIFY COLUMN `version` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '版本' AFTER `installed_rank`,
MODIFY COLUMN `description` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '描述' AFTER `version`,
MODIFY COLUMN `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '类型' AFTER `description`,
MODIFY COLUMN `script` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '脚本名称' AFTER `type`,
MODIFY COLUMN `version` varchar(50) NULL DEFAULT NULL COMMENT '版本' AFTER `installed_rank`,
MODIFY COLUMN `description` varchar(200) NOT NULL COMMENT '描述' AFTER `version`,
MODIFY COLUMN `type` varchar(20) NOT NULL COMMENT '类型' AFTER `description`,
MODIFY COLUMN `script` varchar(1000) NOT NULL COMMENT '脚本名称' AFTER `type`,
MODIFY COLUMN `checksum` int(0) NULL DEFAULT NULL COMMENT '脚本内容一致性校验码' AFTER `script`,
MODIFY COLUMN `installed_by` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '执行用户' AFTER `checksum`,
MODIFY COLUMN `installed_by` varchar(100) NOT NULL COMMENT '执行用户' AFTER `checksum`,
MODIFY COLUMN `installed_on` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '执行时间' AFTER `installed_by`,
MODIFY COLUMN `execution_time` int(0) NOT NULL COMMENT '执行时长' AFTER `installed_on`,
MODIFY COLUMN `success` tinyint(1) NOT NULL COMMENT '状态1-成功0-失败' AFTER `execution_time`;
ALTER TABLE `license`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `update_time` bigint(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `id`,
MODIFY COLUMN `license` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT 'license' AFTER `update_time`,
MODIFY COLUMN `f2c_license` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT 'F2C License' AFTER `license`;
ALTER TABLE `per_dataset_column_permissions`
MODIFY COLUMN `update_time` bigint(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `white_list_user`;
ALTER TABLE `per_dataset_row_permissions_tree`
MODIFY COLUMN `update_time` bigint(0) NULL DEFAULT NULL COMMENT '更新时间' AFTER `white_list_dept`;
ALTER TABLE `per_user`
MODIFY COLUMN `pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码' AFTER `account`;
ALTER TABLE `visualization_background`
MODIFY COLUMN `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称' AFTER `id`,
MODIFY COLUMN `classification` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分类名' AFTER `name`,
MODIFY COLUMN `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '内容' AFTER `classification`,
MODIFY COLUMN `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注' AFTER `content`,
MODIFY COLUMN `id` varchar(64) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `name` varchar(255) NULL DEFAULT NULL COMMENT '名称' AFTER `id`,
MODIFY COLUMN `classification` varchar(255) NOT NULL COMMENT '分类名' AFTER `name`,
MODIFY COLUMN `content` longtext NULL COMMENT '内容' AFTER `classification`,
MODIFY COLUMN `remark` varchar(255) NULL DEFAULT NULL COMMENT '备注' AFTER `content`,
MODIFY COLUMN `sort` int(0) NULL DEFAULT NULL COMMENT '排序' AFTER `remark`,
MODIFY COLUMN `upload_time` bigint(0) NULL DEFAULT NULL COMMENT '上传时间' AFTER `sort`,
MODIFY COLUMN `base_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所在目录地址' AFTER `upload_time`,
MODIFY COLUMN `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图片url' AFTER `base_url`;
MODIFY COLUMN `base_url` varchar(255) NULL DEFAULT NULL COMMENT '所在目录地址' AFTER `upload_time`,
MODIFY COLUMN `url` varchar(255) NULL DEFAULT NULL COMMENT '图片url' AFTER `base_url`;
ALTER TABLE `visualization_background_image`
MODIFY COLUMN `id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称' AFTER `id`,
MODIFY COLUMN `classification` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '分类名' AFTER `name`,
MODIFY COLUMN `content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '内容' AFTER `classification`,
MODIFY COLUMN `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '备注' AFTER `content`,
MODIFY COLUMN `id` varchar(64) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `name` varchar(255) NULL DEFAULT NULL COMMENT '名称' AFTER `id`,
MODIFY COLUMN `classification` varchar(255) NOT NULL COMMENT '分类名' AFTER `name`,
MODIFY COLUMN `content` longtext NULL COMMENT '内容' AFTER `classification`,
MODIFY COLUMN `remark` varchar(255) NULL DEFAULT NULL COMMENT '备注' AFTER `content`,
MODIFY COLUMN `sort` int(0) NULL DEFAULT NULL COMMENT '排序' AFTER `remark`,
MODIFY COLUMN `upload_time` bigint(0) NULL DEFAULT NULL COMMENT '上传时间' AFTER `sort`,
MODIFY COLUMN `base_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '所在目录地址' AFTER `upload_time`,
MODIFY COLUMN `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '图片url' AFTER `base_url`;
MODIFY COLUMN `base_url` varchar(255) NULL DEFAULT NULL COMMENT '所在目录地址' AFTER `upload_time`,
MODIFY COLUMN `url` varchar(255) NULL DEFAULT NULL COMMENT '图片url' AFTER `base_url`;
ALTER TABLE `visualization_link_jump`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
@ -149,8 +159,8 @@ ALTER TABLE `visualization_link_jump_target_view_info`
ALTER TABLE `visualization_linkage`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `dv_id` bigint(0) NULL DEFAULT NULL COMMENT '联动大屏/仪表板ID' AFTER `id`,
MODIFY COLUMN `ext1` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '扩展字段1' AFTER `linkage_active`,
MODIFY COLUMN `ext2` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '扩展字段2' AFTER `ext1`,
MODIFY COLUMN `ext1` varchar(2000) NULL DEFAULT NULL COMMENT '扩展字段1' AFTER `linkage_active`,
MODIFY COLUMN `ext2` varchar(2000) NULL DEFAULT NULL COMMENT '扩展字段2' AFTER `ext1`,
MODIFY COLUMN `copy_from` bigint(0) NULL DEFAULT NULL COMMENT '复制来源' AFTER `ext2`,
MODIFY COLUMN `copy_id` bigint(0) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
@ -163,15 +173,15 @@ ALTER TABLE `visualization_subject`
MODIFY COLUMN `create_num` int(0) NOT NULL DEFAULT 0 COMMENT '创建序号' AFTER `cover_url`;
ALTER TABLE `visualization_template_category`
MODIFY COLUMN `template_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '模版类型 system 系统内置 self 用户自建' AFTER `snapshot`;
MODIFY COLUMN `template_type` varchar(255) NULL DEFAULT NULL COMMENT '模版类型 system 系统内置 self 用户自建' AFTER `snapshot`;
ALTER TABLE `visualization_template_extend_data`
MODIFY COLUMN `id` bigint(0) NOT NULL COMMENT '主键' FIRST,
MODIFY COLUMN `dv_id` bigint(0) NULL DEFAULT NULL COMMENT '模板ID' AFTER `id`,
MODIFY COLUMN `view_id` bigint(0) NULL DEFAULT NULL COMMENT '视图ID' AFTER `dv_id`,
MODIFY COLUMN `view_details` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '视图详情' AFTER `view_id`,
MODIFY COLUMN `copy_from` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '复制来源' AFTER `view_details`,
MODIFY COLUMN `copy_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
MODIFY COLUMN `view_details` longtext NULL COMMENT '视图详情' AFTER `view_id`,
MODIFY COLUMN `copy_from` varchar(255) NULL DEFAULT NULL COMMENT '复制来源' AFTER `view_details`,
MODIFY COLUMN `copy_id` varchar(255) NULL DEFAULT NULL COMMENT '复制来源ID' AFTER `copy_from`;
ALTER TABLE `core_opt_recent`
MODIFY COLUMN `resource_type` int(0) NOT NULL COMMENT '资源类型 1-可视化资源 2-仪表板 3-数据大屏 4-数据集 5-数据源 6-模板' AFTER `uid`;

View File

@ -11,4 +11,8 @@ CREATE TABLE `visualization_watermark` (
INSERT INTO `visualization_watermark` (`id`, `version`, `setting_content`, `create_by`, `create_time`) VALUES ('system_default', '1.0', '{\"enable\":false,\"enablePanelCustom\":true,\"type\":\"custom\",\"content\":\"水印\",\"watermark_color\":\"#DD1010\",\"watermark_x_space\":12,\"watermark_y_space\":36,\"watermark_fontsize\":15}', 'admin', NULL);
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (9, 'basic.frontTimeOut', '60', 'text', 1);
ALTER TABLE `visualization_template`
ADD COLUMN `use_count` int NULL DEFAULT 0 COMMENT '使用次数' AFTER `dynamic_data`;
update visualization_template set use_count = 0;
INSERT INTO `core_sys_setting` (`id`, `pkey`, `pval`, `type`, `sort`) VALUES (9, 'basic.frontTimeOut', '60', 'text', 1);

View File

@ -53,12 +53,13 @@
vt.create_time,
vt.template_type,
vt.SNAPSHOT,
vt.use_count,
vtcm.category_id,
cor.time as 'recent_use_time'
FROM visualization_template vt
LEFT JOIN visualization_template_category_map vtcm ON vt.id = vtcm.template_id
left JOIN core_opt_recent cor on cor.resource_type = 6 and vt.id = cor.resource_name
ORDER BY vt.create_time DESC
ORDER BY vt.use_count ,vt.create_time DESC
</select>
<select id="findCategories" resultMap="BaseResultMapDTO">

View File

@ -1,3 +1,3 @@
# 接口前缀
VITE_API_BASEPATH="/de2api"
VITE_API_BASEPATH="./de2api"
VITE_VERSION="0.0.0"

View File

@ -45,7 +45,8 @@ export default {
}),
createSvgIconsPlugin({
iconDirs: [pathResolve('src/assets/svg')],
symbolId: 'icon-[dir]-[name]'
symbolId: 'icon-[dir]-[name]',
customDomId: '__svg__icons__dom__de'
}),
VueI18nPlugin({
runtimeOnly: false,

View File

@ -24,7 +24,7 @@
"axios": "^1.3.3",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.9",
"element-plus-secondary": "^0.4.15",
"element-plus-secondary": "^0.5.1",
"element-resize-detector": "^1.2.4",
"file-saver": "^2.0.5",
"html-to-image": "^1.11.11",

View File

@ -3,3 +3,7 @@ import request from '@/config/axios'
export const validateApi = data => request.post({ url: '/license/validate', data })
export const buildVersionApi = () => request.get({ url: '/license/version' })
export const updateInfoApi = data => request.post({ url: '/license/update', data })
export const checkFreeApi = () => request.get({ url: '/rmonitor/existFree' })
export const syncFreeApi = () => request.post({ url: '/rmonitor/sync' })
export const delFreeApi = () => request.post({ url: '/rmonitor/delete' })

View File

@ -91,6 +91,30 @@ export const save = async (data = {}): Promise<Dataset> => {
})
}
export const update = async (data = {}): Promise<Dataset> => {
return request.post({ url: '/datasource/update', data }).then(res => {
return res?.data
})
}
export const move = async (data = {}): Promise<Dataset> => {
return request.post({ url: '/datasource/move', data }).then(res => {
return res?.data
})
}
export const reName = async (data = {}): Promise<Dataset> => {
return request.post({ url: '/datasource/reName', data }).then(res => {
return res?.data
})
}
export const createFolder = async (data = {}): Promise<Dataset> => {
return request.post({ url: '/datasource/createFolder', data }).then(res => {
return res?.data
})
}
export const checkRepeat = async (data = {}): Promise<Dataset> => {
return request.post({ url: '/datasource/checkRepeat', data }).then(res => {
return res?.data
@ -111,6 +135,14 @@ export const getDatasetTree = async (data = {}): Promise<IResponse> => {
})
}
export const getDsTree = async (data = {}): Promise<IResponse> => {
return request
.post({ url: '/datasource/tree', data: { ...data, ...{ busiFlag: 'datasource' } } })
.then(res => {
return res?.data
})
}
export const deleteById = (id: number) => request.get({ url: '/datasource/delete/' + id })
export const getById = (id: number) => request.get({ url: '/datasource/get/' + id })

View File

@ -7,8 +7,8 @@ export const sourceDsPageApi = (page: number, limit: number, data) => {
export const targetDsPageApi = (page: number, limit: number, data) => {
return request.post({ url: `/sync/datasource/target/pager/${page}/${limit}`, data })
}
export const latestUseApi = () => {
return request.post({ url: '/sync/datasource/latestUse', data: {} })
export const latestUseApi = (sourceType: string) => {
return request.post({ url: `/sync/datasource/latestUse/${sourceType}`, data: {} })
}
export const validateApi = data => {

View File

@ -35,6 +35,7 @@ export interface ITableField {
fieldType: string
remarks: string
fieldSize: number
fieldPrecision: number
fieldPk: boolean
fieldIndex: boolean
}

View File

@ -16,6 +16,10 @@ export interface Panel {
updateBy: string
}
export const findCopyResource = async (dvId, busiFlag): Promise<IResponse> => {
return request.get({ url: '/dataVisualization/findCopyResource/' + dvId + '/' + busiFlag })
}
export const findById = async (dvId, busiFlag): Promise<IResponse> => {
let busiFlagResult = busiFlag
if (!busiFlagResult) {

View File

@ -2,4 +2,4 @@ import request from '@/config/axios'
export const watermarkSave = params => request.post({ url: '/watermark/save', data: params })
export const watermarkFind = () => request.get({ url: 'watermark/find' })
export const watermarkFind = async () => request.get({ url: 'watermark/find' })

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708249747987" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8596" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 64c60.5 0 119.2 11.8 174.4 35.2 53.3 22.6 101.3 54.9 142.4 96 41.2 41.2 73.5 89.1 96 142.4C948.2 392.8 960 451.5 960 512s-11.8 119.2-35.2 174.4c-22.6 53.3-54.9 101.3-96 142.4-41.2 41.2-89.1 73.5-142.4 96C631.2 948.2 572.5 960 512 960s-119.2-11.8-174.4-35.2c-53.3-22.6-101.3-54.9-142.4-96-41.2-41.2-73.5-89.1-96-142.4C75.8 631.2 64 572.5 64 512s11.8-119.2 35.2-174.4c22.6-53.3 54.9-101.3 96-142.4s89.1-73.5 142.4-96C392.8 75.8 451.5 64 512 64m0-64C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z" p-id="8597"></path></svg>

After

Width:  |  Height:  |  Size: 884 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708249700626" class="icon" viewBox="0 0 1316 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6641" xmlns:xlink="http://www.w3.org/1999/xlink" width="257.03125" height="200"><path d="M0 0h1316.571429v1024H0V0z m73.142857 73.142857v877.714286h1170.285714V73.142857H73.142857z" p-id="6642" data-spm-anchor-id="a313x.search_index.0.i9.58073a81RUBy7T" class="selected"></path></svg>

After

Width:  |  Height:  |  Size: 535 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708249769352" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9558" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M928.64 896a2.144 2.144 0 0 1-0.64 0H96a32.032 32.032 0 0 1-27.552-48.288l416-704c11.488-19.456 43.552-19.456 55.104 0l413.152 699.2A31.936 31.936 0 0 1 928.64 896z m-776.576-64h719.84L512 222.912 152.064 832z" p-id="9559"></path></svg>

After

Width:  |  Height:  |  Size: 569 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708236511731" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4218" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M414.252575 821.425145c3.034288-2.311839 6.357556-4.045718 9.969804-5.201637l1.444899-0.86694 0.14449 0.28898c3.034288-0.866939 6.068576-1.300409 9.247354-1.300409 19.072668 0 34.533089 15.46042 34.533089 34.533089 0 12.715112-6.791026 23.696345-17.049809 29.764921l-229.160999 118.481728c-10.836743 3.467758-20.951037 0.57796-30.487372-8.669395-9.536334-9.102864-12.570622-20.228588-9.102864-33.23268l52.883307-307.76351L11.992663 426.823197c-10.258784-10.403274-14.015521-20.951037-11.270213-32.07676 4.045718-16.47185 12.281642-22.684916 24.129815-26.008184C128.162551 353.422323 234.073656 337.961902 342.441089 322.068012c47.248201-97.53069 94.207422-192.894031 141.311133-286.090024 5.057147-9.969804 14.448991-15.46042 29.042473-15.460421 14.593481 0 20.806547 3.756738 27.597573 15.460421 10.547764 19.217158 57.940454 114.5805 142.322562 286.090024l318.166784 46.670241c10.981233 4.623677 18.061239 11.270213 20.951037 20.084098 2.889798 8.813885 2.167349 19.361648-2.167348 31.78778L867.083957 570.590659l-0.14449-0.14449c-6.213066 6.213066-14.737971 9.969804-24.274305 9.969804-19.072668 0-34.533089-15.46042-34.533089-34.533089 0-7.368985 2.311839-14.593481 6.646536-20.517567l-0.43347-0.28898 101.865387-99.698039-259.50388-36.555947c-5.346127 0.43347-10.258784-1.300409-14.737971-5.057147-4.479187-3.901228-9.247354-10.403274-14.304501-19.795118L512.794695 132.208269l-116.314379 235.807535c-4.045718 7.080006-9.102864 12.426132-15.026951 15.7494-5.924086 3.323268-13.293072 5.057147-22.251446 5.057147L107.211514 425.522788 294.759419 608.591506c6.213066 6.646536 9.969804 11.992663 11.125723 15.89389 1.155919 3.901228 1.155919 10.836743 0 20.517567l-42.480034 256.469592 150.847467-80.04741z m344.608438-30.342882l103.743756-103.743756c13.437562-13.437562 35.255538-13.437562 48.83759 0 13.437562 13.437562 13.437562 35.255538 0 48.83759L807.698603 839.919853l103.743756 103.743756c13.437562 13.437562 13.437562 35.255538 0 48.83759-13.437562 13.437562-35.255538 13.437562-48.83759 0L758.861013 888.612953l-103.743756 103.743756c-13.437562 13.437562-35.255538 13.437562-48.83759 0-13.437562-13.437562-13.437562-35.255538 0-48.837589l103.743756-103.743757-103.743756-103.743756c-13.437562-13.437562-13.437562-35.255538 0-48.83759 13.437562-13.437562 35.255538-13.437562 48.83759 0l103.743756 103.888246z m0 0" p-id="4219"></path></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708250676998" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10597" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M832 337.6 832 106.688C832 83.072 812.864 64 789.376 64L106.688 64C83.072 64 64 83.072 64 106.688l0 682.688C64 812.928 83.072 832 106.688 832l251.456 0c62.912 96.192 171.328 160 294.592 160 194.112 0 352-157.952 352-352C1004.736 511.424 935.232 399.04 832 337.6zM128 768 128 128l640 0 0 179.776C731.776 295.168 693.12 288 652.736 288 458.688 288 300.8 445.952 300.8 640c0 45.184 8.896 88.256 24.448 128L128 768zM652.736 928C494.016 928 364.8 798.784 364.8 640s129.216-288 287.936-288 288 129.216 288 288S811.52 928 652.736 928z" p-id="10598"></path></svg>

After

Width:  |  Height:  |  Size: 889 B

View File

@ -0,0 +1,6 @@
<svg width="80" height="56" viewBox="0 0 80 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.5912 36.9635C24.5912 37.2397 24.3673 37.4635 24.0912 37.4635H20.8083C20.5322 37.4635 20.3083 37.2397 20.3083 36.9635V18.729H15.5C15.2239 18.729 15 18.5052 15 18.229V14.8324C15 14.5491 15.2355 14.3239 15.5188 14.3171C16.0773 14.3035 16.6182 14.2336 17.1414 14.1073C17.8452 13.9147 18.4685 13.5983 19.0114 13.1582C19.5744 12.6905 20.0469 12.0853 20.429 11.3425C20.7584 10.702 20.9906 9.92865 21.1257 9.0223C21.1633 8.77004 21.3761 8.57772 21.6312 8.57772H24.0912C24.3673 8.57772 24.5912 8.80157 24.5912 9.07772V36.9635Z" fill="#3370FF"/>
<path d="M31.118 19.6781C30.8466 19.6781 30.6241 19.4616 30.6234 19.1902C30.6195 17.7256 30.7625 16.3614 31.0522 15.0977C31.374 13.6671 31.8565 12.4292 32.5 11.3838C33.1434 10.3109 33.9477 9.48556 34.9128 8.90784C35.8981 8.30261 37.0241 8 38.2909 8C39.256 8 40.1709 8.20633 41.0355 8.61898C41.9202 9.03164 42.6944 9.62311 43.3579 10.3934C44.0215 11.1637 44.5442 12.1128 44.9263 13.2407C45.3284 14.3686 45.5295 15.6341 45.5295 17.0371C45.5295 18.4952 45.3586 19.7469 45.0168 20.7923C44.6749 21.8377 44.2225 22.773 43.6595 23.5983C43.0965 24.3961 42.4531 25.1252 41.7292 25.7854C41.0255 26.4457 40.3117 27.1059 39.5878 27.7662C38.8639 28.3989 38.1602 29.0867 37.4765 29.8294C36.7929 30.5722 36.1897 31.4388 35.6669 32.4292H45.1502C45.4263 32.4292 45.6502 32.653 45.6502 32.9292V36.9635C45.6502 37.2397 45.4263 37.4635 45.1502 37.4635H30.1474C30.1474 35.7854 30.3183 34.3274 30.6602 33.0894C31.0221 31.8514 31.5047 30.751 32.1079 29.7882C32.7111 28.7978 33.4149 27.89 34.2191 27.0646C35.0435 26.2393 35.9082 25.4003 36.813 24.5475C37.2755 24.1073 37.7681 23.6671 38.2909 23.227C38.8137 22.7593 39.2862 22.2503 39.7084 21.7001C40.1508 21.1499 40.5127 20.5309 40.7942 19.8432C41.0958 19.1554 41.2467 18.3714 41.2467 17.4911C41.2467 16.088 40.945 15.0014 40.3418 14.2311C39.7587 13.4333 39.0047 13.0344 38.0798 13.0344C37.4564 13.0344 36.9236 13.2407 36.4812 13.6534C36.059 14.0385 35.7171 14.5612 35.4557 15.2215C35.1944 15.8542 35.0033 16.5695 34.8827 17.3673C34.8039 17.9709 34.756 18.5746 34.7389 19.1782C34.7311 19.4542 34.508 19.6781 34.2319 19.6781H31.118Z" fill="#3370FF"/>
<path d="M55.6501 20.8189C55.6501 20.5193 55.912 20.2881 56.2115 20.2953C56.5059 20.3023 56.8114 20.2892 57.128 20.2558C57.6508 20.2008 58.1333 20.0495 58.5757 19.8019C59.0382 19.5268 59.4102 19.1417 59.6917 18.6465C59.9933 18.1513 60.1441 17.4911 60.1441 16.6657C60.1441 15.4278 59.8425 14.4787 59.2393 13.8184C58.636 13.1582 57.9423 12.8281 57.1581 12.8281C56.0723 12.8281 55.248 13.3232 54.6849 14.3136C54.2051 15.1647 53.9452 16.2199 53.9051 17.4793C53.8963 17.758 53.6727 17.9862 53.394 17.9862H50.3428C50.0613 17.9862 49.8346 17.7539 49.8492 17.4729C49.9158 16.1886 50.1001 15.0117 50.4021 13.9422C50.764 12.7043 51.2567 11.6451 51.88 10.7648C52.5234 9.88446 53.2875 9.21045 54.1722 8.74278C55.0569 8.24759 56.0422 8 57.128 8C57.9725 8 58.817 8.17882 59.6615 8.53645C60.506 8.86658 61.26 9.37552 61.9236 10.0633C62.6072 10.751 63.1602 11.5901 63.5824 12.5805C64.0047 13.5708 64.2158 14.7125 64.2158 16.0055C64.2158 17.4085 63.9645 18.6465 63.4618 19.7194C62.9792 20.7923 62.2453 21.5213 61.26 21.9065V21.989C62.4263 22.3466 63.3411 23.1169 64.0047 24.2999C64.6682 25.4828 65 26.8996 65 28.5502C65 30.0633 64.7788 31.4113 64.3365 32.5942C63.9142 33.7772 63.3411 34.7675 62.6173 35.5653C61.8934 36.3631 61.059 36.9684 60.1139 37.381C59.1689 37.7937 58.1836 38 57.1581 38C55.9718 38 54.886 37.7662 53.9008 37.2985C52.9356 36.8308 52.1112 36.1568 51.4276 35.2765C50.7439 34.3686 50.2111 33.2682 49.829 31.9752C49.503 30.8106 49.332 29.4898 49.316 28.0127C49.313 27.7389 49.5365 27.5186 49.8103 27.5186H52.9009C53.172 27.5186 53.3925 27.7347 53.4103 28.0052C53.4497 28.6028 53.5327 29.1834 53.6595 29.7469C53.8203 30.4347 54.0516 31.0399 54.3532 31.5626C54.6548 32.0578 55.0268 32.4567 55.4691 32.7593C55.9316 33.0619 56.4745 33.2132 57.0978 33.2132C58.063 33.2132 58.8773 32.8143 59.5409 32.0165C60.2044 31.1912 60.5362 30.077 60.5362 28.674C60.5362 27.5736 60.3753 26.7345 60.0536 26.1568C59.752 25.5791 59.3599 25.1664 58.8773 24.9188C58.3947 24.6437 57.8619 24.4924 57.2788 24.4649C56.8931 24.4272 56.5168 24.4025 56.15 24.3906C55.874 24.3816 55.6501 24.1585 55.6501 23.8824V20.8189Z" fill="#3370FF"/>
<path d="M64.5 43H15.5C15.2239 43 15 43.2239 15 43.5V48.125C15 48.4011 15.2239 48.625 15.5 48.625H64.5C64.7761 48.625 65 48.4011 65 48.125V43.5C65 43.2239 64.7761 43 64.5 43Z" fill="#00D6B9"/>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,6 @@
<svg width="80" height="56" viewBox="0 0 80 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.5912 36.9635C24.5912 37.2397 24.3673 37.4635 24.0912 37.4635H20.8083C20.5322 37.4635 20.3083 37.2397 20.3083 36.9635V18.729H15.5C15.2239 18.729 15 18.5052 15 18.229V14.8324C15 14.5491 15.2355 14.3239 15.5188 14.3171C16.0773 14.3035 16.6182 14.2336 17.1414 14.1073C17.8452 13.9147 18.4685 13.5983 19.0114 13.1582C19.5744 12.6905 20.0469 12.0853 20.429 11.3425C20.7584 10.702 20.9906 9.92865 21.1257 9.0223C21.1633 8.77004 21.3761 8.57772 21.6312 8.57772H24.0912C24.3673 8.57772 24.5912 8.80157 24.5912 9.07772V36.9635Z" fill="#3370FF"/>
<path d="M31.118 19.6781C30.8466 19.6781 30.6241 19.4616 30.6234 19.1902C30.6195 17.7256 30.7625 16.3614 31.0522 15.0977C31.374 13.6671 31.8565 12.4292 32.5 11.3838C33.1434 10.3109 33.9477 9.48556 34.9128 8.90784C35.8981 8.30261 37.0241 8 38.2909 8C39.256 8 40.1709 8.20633 41.0355 8.61898C41.9202 9.03164 42.6944 9.62311 43.3579 10.3934C44.0215 11.1637 44.5442 12.1128 44.9263 13.2407C45.3284 14.3686 45.5295 15.6341 45.5295 17.0371C45.5295 18.4952 45.3586 19.7469 45.0168 20.7923C44.6749 21.8377 44.2225 22.773 43.6595 23.5983C43.0965 24.3961 42.4531 25.1252 41.7292 25.7854C41.0255 26.4457 40.3117 27.1059 39.5878 27.7662C38.8639 28.3989 38.1602 29.0867 37.4765 29.8294C36.7929 30.5722 36.1897 31.4388 35.6669 32.4292H45.1502C45.4263 32.4292 45.6502 32.653 45.6502 32.9292V36.9635C45.6502 37.2397 45.4263 37.4635 45.1502 37.4635H30.1474C30.1474 35.7854 30.3183 34.3274 30.6602 33.0894C31.0221 31.8514 31.5047 30.751 32.1079 29.7882C32.7111 28.7978 33.4149 27.89 34.2191 27.0646C35.0435 26.2393 35.9082 25.4003 36.813 24.5475C37.2755 24.1073 37.7681 23.6671 38.2909 23.227C38.8137 22.7593 39.2862 22.2503 39.7084 21.7001C40.1508 21.1499 40.5127 20.5309 40.7942 19.8432C41.0958 19.1554 41.2467 18.3714 41.2467 17.4911C41.2467 16.088 40.945 15.0014 40.3418 14.2311C39.7587 13.4333 39.0047 13.0344 38.0798 13.0344C37.4564 13.0344 36.9236 13.2407 36.4812 13.6534C36.059 14.0385 35.7171 14.5612 35.4557 15.2215C35.1944 15.8542 35.0033 16.5695 34.8827 17.3673C34.8039 17.9709 34.756 18.5746 34.7389 19.1782C34.7311 19.4542 34.508 19.6781 34.2319 19.6781H31.118Z" fill="#3370FF"/>
<path d="M55.6501 20.8189C55.6501 20.5193 55.912 20.2881 56.2115 20.2953C56.5059 20.3023 56.8114 20.2892 57.128 20.2558C57.6508 20.2008 58.1333 20.0495 58.5757 19.8019C59.0382 19.5268 59.4102 19.1417 59.6917 18.6465C59.9933 18.1513 60.1441 17.4911 60.1441 16.6657C60.1441 15.4278 59.8425 14.4787 59.2393 13.8184C58.636 13.1582 57.9423 12.8281 57.1581 12.8281C56.0723 12.8281 55.248 13.3232 54.6849 14.3136C54.2051 15.1647 53.9452 16.2199 53.9051 17.4793C53.8963 17.758 53.6727 17.9862 53.394 17.9862H50.3428C50.0613 17.9862 49.8346 17.7539 49.8492 17.4729C49.9158 16.1886 50.1001 15.0117 50.4021 13.9422C50.764 12.7043 51.2567 11.6451 51.88 10.7648C52.5234 9.88446 53.2875 9.21045 54.1722 8.74278C55.0569 8.24759 56.0422 8 57.128 8C57.9725 8 58.817 8.17882 59.6615 8.53645C60.506 8.86658 61.26 9.37552 61.9236 10.0633C62.6072 10.751 63.1602 11.5901 63.5824 12.5805C64.0047 13.5708 64.2158 14.7125 64.2158 16.0055C64.2158 17.4085 63.9645 18.6465 63.4618 19.7194C62.9792 20.7923 62.2453 21.5213 61.26 21.9065V21.989C62.4263 22.3466 63.3411 23.1169 64.0047 24.2999C64.6682 25.4828 65 26.8996 65 28.5502C65 30.0633 64.7788 31.4113 64.3365 32.5942C63.9142 33.7772 63.3411 34.7675 62.6173 35.5653C61.8934 36.3631 61.059 36.9684 60.1139 37.381C59.1689 37.7937 58.1836 38 57.1581 38C55.9718 38 54.886 37.7662 53.9008 37.2985C52.9356 36.8308 52.1112 36.1568 51.4276 35.2765C50.7439 34.3686 50.2111 33.2682 49.829 31.9752C49.503 30.8106 49.332 29.4898 49.316 28.0127C49.313 27.7389 49.5365 27.5186 49.8103 27.5186H52.9009C53.172 27.5186 53.3925 27.7347 53.4103 28.0052C53.4497 28.6028 53.5327 29.1834 53.6595 29.7469C53.8203 30.4347 54.0516 31.0399 54.3532 31.5626C54.6548 32.0578 55.0268 32.4567 55.4691 32.7593C55.9316 33.0619 56.4745 33.2132 57.0978 33.2132C58.063 33.2132 58.8773 32.8143 59.5409 32.0165C60.2044 31.1912 60.5362 30.077 60.5362 28.674C60.5362 27.5736 60.3753 26.7345 60.0536 26.1568C59.752 25.5791 59.3599 25.1664 58.8773 24.9188C58.3947 24.6437 57.8619 24.4924 57.2788 24.4649C56.8931 24.4272 56.5168 24.4025 56.15 24.3906C55.874 24.3816 55.6501 24.1585 55.6501 23.8824V20.8189Z" fill="#3370FF"/>
<path d="M64.5 43H15.5C15.2239 43 15 43.2239 15 43.5V48.125C15 48.4011 15.2239 48.625 15.5 48.625H64.5C64.7761 48.625 65 48.4011 65 48.125V43.5C65 43.2239 64.7761 43 64.5 43Z" fill="#00D6B9"/>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 2.5C4 1.94772 4.44772 1.5 5 1.5H14.8608C14.9949 1.5 15.1234 1.55387 15.2174 1.64951L19.8566 6.36941C19.9485 6.46292 20 6.58879 20 6.7199V21.5C20 22.0523 19.5523 22.5 19 22.5H5C4.44772 22.5 4 22.0523 4 21.5V2.5Z" fill="#3370FF"/>
<path d="M15 1.51978C15.0817 1.54345 15.1567 1.58778 15.2174 1.64952L19.8566 6.36942C19.8946 6.40806 19.9256 6.45223 19.949 6.50001H16.1351C15.5082 6.50001 15 5.99179 15 5.36488V1.51978Z" fill="#2B5FD9"/>
<path d="M8.05554 9.27271C7.7794 9.27271 7.55554 9.49656 7.55554 9.77271V10.5909C7.55554 10.867 7.7794 11.0909 8.05554 11.0909H15.9444C16.2206 11.0909 16.4444 10.867 16.4444 10.5909V9.77271C16.4444 9.49656 16.2206 9.27271 15.9444 9.27271H8.05554Z" fill="white"/>
<path d="M8.05554 13.8182C7.7794 13.8182 7.55554 14.042 7.55554 14.3182V15.1363C7.55554 15.4125 7.7794 15.6363 8.05554 15.6363H11.5C11.7761 15.6363 12 15.4125 12 15.1363V14.3182C12 14.042 11.7761 13.8182 11.5 13.8182H8.05554Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -54,16 +54,20 @@ const themeAttrChange = (custom, property, value) => {
if (canvasAttrInit) {
Object.keys(canvasViewInfo.value).forEach(function (viewId) {
const viewInfo = canvasViewInfo.value[viewId]
if (custom === 'customAttr') {
merge(viewInfo['customAttr'], value)
} else {
Object.keys(value).forEach(function (key) {
if (viewInfo[custom][property][key] !== undefined) {
viewInfo[custom][property][key] = value[key]
}
})
try {
if (custom === 'customAttr') {
merge(viewInfo['customAttr'], value)
} else {
Object.keys(value).forEach(function (key) {
if (viewInfo[custom][property][key] !== undefined) {
viewInfo[custom][property][key] = value[key]
}
})
}
useEmitt().emitter.emit('renderChart-' + viewId, viewInfo)
} catch (e) {
console.warn('themeAttrChange-error')
}
useEmitt().emitter.emit('renderChart-' + viewId, viewInfo)
})
snapshotStore.recordSnapshotCache('renderChart')
}
@ -164,6 +168,7 @@ const saveSelfSubject = () => {
position: absolute;
top: 4px;
right: 4px;
font-size: 12px;
}
}

View File

@ -33,17 +33,21 @@ const onBaseChange = () => {
const themeAttrChange = (custom, property, value) => {
if (canvasAttrInit) {
Object.keys(canvasViewInfo.value).forEach(function (viewId) {
const viewInfo = canvasViewInfo.value[viewId]
if (custom === 'customAttr') {
merge(viewInfo['customAttr'], value)
} else {
Object.keys(value).forEach(function (key) {
if (viewInfo[custom][property][key] !== undefined) {
viewInfo[custom][property][key] = value[key]
}
})
try {
const viewInfo = canvasViewInfo.value[viewId]
if (custom === 'customAttr') {
merge(viewInfo['customAttr'], value)
} else {
Object.keys(value).forEach(function (key) {
if (viewInfo[custom][property][key] !== undefined) {
viewInfo[custom][property][key] = value[key]
}
})
}
useEmitt().emitter.emit('renderChart-' + viewId, viewInfo)
} catch (e) {
console.warn('themeAttrChange-error')
}
useEmitt().emitter.emit('renderChart-' + viewId, viewInfo)
})
snapshotStore.recordSnapshotCache('renderChart')
}
@ -66,7 +70,7 @@ onMounted(() => {
effect="dark"
size="middle"
:min="600"
:max="100000"
:max="50000"
v-model="canvasStyleData.width"
@change="onBaseChange"
controls-position="right"
@ -79,7 +83,7 @@ onMounted(() => {
effect="dark"
size="middle"
:min="600"
:max="100000"
:max="50000"
v-model="canvasStyleData.height"
@change="onBaseChange"
controls-position="right"

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import { ref, onMounted, onUnmounted } from 'vue'
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { changeSizeWithScale } from '@/utils/changeComponentsSizeWithScale'
import { useEmitt } from '@/hooks/web/useEmitt'
@ -41,8 +41,29 @@ const reposition = () => {
// wheel
let lastWheelNum = 0
//
const checkDialog = () => {
let haveDialog = false
document.querySelectorAll('.ed-overlay').forEach(element => {
if (window.getComputedStyle(element).getPropertyValue('display') != 'none') {
haveDialog = true
}
})
document.querySelectorAll('.ed-popover').forEach(element => {
if (window.getComputedStyle(element).getPropertyValue('display') != 'none') {
haveDialog = true
}
})
//
if (document.querySelector('.tox-dialog-wrap')) {
haveDialog = true
}
return haveDialog
}
const handleMouseWheel = e => {
if (editMode.value === 'preview') {
if (editMode.value === 'preview' || checkDialog()) {
return
}
let dvMain = document.getElementById('dv-main-center')
@ -71,6 +92,9 @@ onMounted(() => {
window.addEventListener('mousewheel', handleMouseWheel, { passive: false })
setTimeout(() => {
scale.value = canvasStyleData.value.scale
nextTick(() => {
useEmitt().emitter.emit('initScroll')
})
}, 1000)
})
@ -112,14 +136,16 @@ onUnmounted(() => {
<Icon name="dv-max"></Icon
></el-icon>
<el-divider direction="vertical" class="custom-divider" />
<el-icon @click="reposition" class="hover-icon-custom" style="margin-right: 12px">
<Icon name="dv-reposition"></Icon
></el-icon>
<el-tooltip effect="ndark" content="定位到中心点" placement="top">
<el-icon @click="reposition" class="hover-icon-custom" style="margin-right: 12px">
<Icon name="dv-reposition"></Icon
></el-icon>
</el-tooltip>
</div>
</el-row>
</template>
<style lang="less">
<style scoped lang="less">
.custom-main {
display: flex;
width: 100%;

View File

@ -189,7 +189,8 @@ const start = ref({
const width = ref(0)
const height = ref(0)
const isShowArea = ref(false)
const svgFilterAttrs = ['width', 'height', 'top', 'left', 'rotate']
const svgFilterAttrs = ['width', 'height', 'top', 'left', 'rotate', 'backgroundColor']
const commonFilterAttrs = ['width', 'height', 'top', 'left', 'rotate']
const userViewEnlargeRef = ref(null)
const linkJumpRef = ref(null)
const linkageRef = ref(null)
@ -206,13 +207,19 @@ watch(
watch(
() => canvasStyleData.value,
() => {
initWatermark()
nextTick(() => {
initWatermark()
})
},
{ deep: true }
)
const initWatermark = (waterDomId = 'editor-canvas-main') => {
if (dvInfo.value.watermarkInfo && isMainCanvas(canvasId.value)) {
if (
dvInfo.value.watermarkInfo &&
dvInfo.value.watermarkInfo.settingContent &&
isMainCanvas(canvasId.value)
) {
const scale = dashboardActive.value ? 1 : curScale.value
if (userInfo.value) {
activeWatermark(
@ -493,10 +500,18 @@ const handleContextMenu = e => {
//
if (!curComponent.value || (curComponent.value && !curComponent.value.editing)) {
contextmenuStore.showContextMenu({ top, left, position: 'canvasCore' })
const iconDom = document.getElementById('close-button')
if (iconDom) {
iconDom.click()
}
}
}
const getComponentStyle = style => {
return getStyle(style, commonFilterAttrs)
}
const getSvgComponentStyle = style => {
return getStyle(style, svgFilterAttrs)
}
@ -1375,7 +1390,7 @@ defineExpose({
:id="mainDomId"
ref="container"
class="editor"
:class="{ edit: isEdit }"
:class="{ edit: isEdit, 'dashboard-editor': dashboardActive }"
:style="editStyle"
@contextmenu="handleContextMenu"
>
@ -1440,7 +1455,23 @@ defineExpose({
:dv-info="dvInfo"
:canvas-active="canvasActive"
/>
<component
v-else-if="item.component.includes('Svg')"
:is="findComponent(item.component)"
:id="'component' + item.id"
:scale="curBaseScale"
class="component"
:is-edit="true"
:style="getSvgComponentStyle(item.style)"
:prop-value="item.propValue"
:element="item"
:request="item.request"
:canvas-style-data="canvasStyleData"
:canvas-view-info="canvasViewInfo"
:dv-info="dvInfo"
:active="item.id === curComponentId"
:canvas-active="canvasActive"
/>
<component
v-else
:is="findComponent(item.component)"
@ -1472,6 +1503,9 @@ defineExpose({
</template>
<style lang="less" scoped>
.dashboard-editor {
min-height: 100%;
}
.editor {
position: relative;
margin: auto;

View File

@ -115,7 +115,11 @@ const onClick = () => {
}
const getComponentStyleDefault = style => {
return getStyle(style, ['top', 'left', 'width', 'height', 'rotate'])
if (config.value.component.includes('Svg')) {
return getStyle(style, ['top', 'left', 'width', 'height', 'rotate', 'backgroundColor'])
} else {
return getStyle(style, ['top', 'left', 'width', 'height', 'rotate'])
}
}
const onMouseEnter = () => {
@ -133,7 +137,10 @@ const componentBackgroundStyle = computed(() => {
innerPadding,
borderRadius
} = config.value.commonBackground
const style = { padding: innerPadding + 'px', borderRadius: borderRadius + 'px' }
const style = {
padding: innerPadding * deepScale.value + 'px',
borderRadius: borderRadius + 'px'
}
let colorRGBA = ''
if (backgroundColorSelect && backgroundColor) {
colorRGBA = backgroundColor

View File

@ -53,8 +53,12 @@ const menuOpt = optName => {
}
const cut = () => {
const curInfo = getCurInfo()
copyStore.cut(curInfo.componentData)
if (curComponent.value) {
const curInfo = getCurInfo()
copyStore.cut(curInfo.componentData)
} else if (areaData.value.components.length) {
copyStore.cut()
}
menuOpt('cut')
}
@ -135,6 +139,11 @@ const decompose = () => {
menuOpt('decompose')
}
const alignment = params => {
composeStore.alignment(params)
snapshotStore.recordSnapshotCache('decompose')
}
// handleMouseDown areaData
const handleComposeMouseDown = e => {
e.preventDefault()
@ -147,10 +156,37 @@ const composeDivider = computed(() => {
</script>
<template>
<div class="context-menu-details" @mousedown="handleComposeMouseDown">
<div class="context-menu-base context-menu-details" @mousedown="handleComposeMouseDown">
<ul @mouseup="handleMouseUp">
<template v-if="areaData.components.length">
<li @mousedown="handleComposeMouseDown" @click="componentCompose">组合</li>
<el-dropdown
style="width: 100%"
trigger="hover"
effect="dark"
placement="right-start"
popper-class="context-menu-details"
>
<li>
<div>
<span>对齐</span><el-icon><ArrowRight /></el-icon>
</div>
</li>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item style="width: 118px" @click="alignment('left')"
>左对齐</el-dropdown-item
>
<el-dropdown-item style="width: 118px" @click="alignment('right')"
>右对齐</el-dropdown-item
>
<el-dropdown-item @click="alignment('top')">上对齐</el-dropdown-item>
<el-dropdown-item @click="alignment('bottom')">下对齐</el-dropdown-item>
<el-dropdown-item @click="alignment('transverse')">水平居中</el-dropdown-item>
<el-dropdown-item @click="alignment('direction')">垂直居中</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-divider class="custom-divider" />
<li @click="copy">复制</li>
<li @click="paste">粘贴</li>
@ -190,11 +226,13 @@ const composeDivider = computed(() => {
</div>
</template>
<style lang="less" scoped>
<style lang="less">
.context-menu-base {
width: 220px;
}
.context-menu-details {
z-index: 1000;
border: #434343 1px solid;
width: 220px;
ul {
padding: 4px 0;
background-color: #292929;
@ -205,6 +243,7 @@ const composeDivider = computed(() => {
}
li {
width: 100%;
font-size: 14px;
padding: 0 12px;
position: relative;
@ -219,13 +258,13 @@ const composeDivider = computed(() => {
i {
position: absolute;
left: 30px;
right: 0px;
top: 50%;
transform: translate(-50%, -50%);
}
&:hover {
background-color: #333;
background-color: #333 !important;
}
}
}
@ -233,5 +272,6 @@ const composeDivider = computed(() => {
.custom-divider {
border-color: #434343 !important;
margin: 0px;
}
</style>

View File

@ -53,6 +53,11 @@ const props = defineProps({
userId: {
type: String,
require: false
},
outerScale: {
type: Number,
required: false,
default: 1
}
})
@ -64,7 +69,9 @@ const {
canvasViewInfo,
showPosition,
previewActive,
downloadStatus
downloadStatus,
outerScale,
userId
} = toRefs(props)
const domId = 'preview-' + canvasId.value
const scaleWidth = ref(100)
@ -133,7 +140,9 @@ const restore = () => {
if (dashboardActive.value) {
cellWidth.value = canvasWidth / pcMatrixCount.value.x
cellHeight.value = canvasHeight / pcMatrixCount.value.y
scaleWidth.value = scaleWidth.value * 1.5
scaleWidth.value = isMainCanvas(canvasId.value)
? scaleWidth.value * 1.2
: outerScale.value * 100
} else {
changeRefComponentsSizeWithScale(
componentData.value,

View File

@ -242,6 +242,7 @@ const {
} = toRefs(props)
const domId = ref('shape-id-' + element.value.id)
const pointList = ['lt', 't', 'rt', 'r', 'rb', 'b', 'lb', 'l']
const pointCorner = ['lt', 'rt', 'rb', 'lb']
const pointList2 = ['r', 'l']
const initialAngle = {
//
@ -284,7 +285,7 @@ const active = computed(() => {
})
const boardMoveActive = computed(() => {
return ['map', 'table-info', 'table-normal'].includes(element.value.innerType)
return ['map', 'table-info', 'table-normal', 'table-pivot'].includes(element.value.innerType)
})
const dashboardActive = computed(() => {
@ -629,6 +630,7 @@ const handleMouseDownOnPoint = (point, e) => {
let isFirst = true
const needLockProportion = isNeedLockProportion()
const originRadio = curComponent.value.style.width / curComponent.value.style.height
const move = moveEvent => {
// move
// move
@ -649,6 +651,27 @@ const handleMouseDownOnPoint = (point, e) => {
})
//Temp dataV
offsetDataVAdaptor(style, point)
//
if (curComponent.value.maintainRadio) {
//
const heightOffset = style.height - defaultStyle.value.height
//
const widthOffset = style.width - defaultStyle.value.width
//
const adaptorWidthOffset = heightOffset * originRadio
//
const adaptorHeightOffset = widthOffset / originRadio
if (pointCorner.includes(point)) {
style.height = defaultStyle.value.height + adaptorHeightOffset
} else if (Math.abs(widthOffset) > Math.abs(adaptorWidthOffset)) {
//
style.height = defaultStyle.value.height + adaptorHeightOffset
} else {
//
style.width = defaultStyle.value.width + adaptorWidthOffset
}
}
dvMainStore.setShapeStyle(style)
//
dashboardActive.value && emit('onResizing', moveEvent)

View File

@ -2,7 +2,8 @@
import { propTypes } from '@/utils/propTypes'
import { ElSelect, ElOption } from 'element-plus-secondary'
import { computed, reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
const props = defineProps({
optionList: propTypes.arrayOf(
propTypes.shape({
@ -10,7 +11,13 @@ const props = defineProps({
name: propTypes.string
})
),
title: propTypes.string
title: propTypes.string,
property: {
type: Object,
default: () => {
placeholder: ''
}
}
})
const state = reactive({
@ -21,7 +28,7 @@ const emits = defineEmits(['filter-change'])
const selectStatus = ids => {
emits(
'filter-change',
ids.map(item => item.label)
ids.map(item => item.id || item.value)
)
}
@ -46,6 +53,7 @@ defineExpose({
v-model="state.activeStatus"
value-key="id"
filterable
:placeholder="t('common.please_select') + props.property.placeholder"
multiple
@change="selectStatus"
>

View File

@ -1,8 +1,15 @@
<script setup lang="ts">
import { propTypes } from '@/utils/propTypes'
import { ElTreeSelect } from 'element-plus-secondary'
import { computed, reactive, ref } from 'vue'
import { computed, reactive, ref, PropType, toRefs } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
const { t } = useI18n()
interface TreeConfig {
checkStrictly: boolean
showCheckbox: boolean
checkOnClickNode: boolean
placeholder: string
}
const props = defineProps({
optionList: propTypes.arrayOf(
propTypes.shape({
@ -12,7 +19,22 @@ const props = defineProps({
disabled: Boolean
})
),
title: propTypes.string
title: propTypes.string,
property: Object as PropType<TreeConfig>
})
const { property } = toRefs(props)
const treeConfig = computed(() => {
let obj = Object.assign(
{
checkStrictly: false,
showCheckbox: true,
checkOnClickNode: true,
placeholder: t('user.role')
},
property.value
)
return obj
})
const state = reactive({
@ -58,9 +80,10 @@ defineExpose({
:highlight-current="true"
multiple
:render-after-expand="false"
:placeholder="$t('common.please_select') + $t('user.role')"
show-checkbox
check-on-click-node
:placeholder="$t('common.please_select') + treeConfig.placeholder"
:show-checkbox="treeConfig.showCheckbox"
:check-strictly="treeConfig.checkStrictly"
:check-on-click-node="treeConfig.checkOnClickNode"
/>
</div>
</div>

View File

@ -107,6 +107,7 @@ defineExpose({
v-if="component.type === 'tree-select'"
:option-list="component.option"
:title="component.title"
:property="component.property"
@filter-change="v => filterChange(v, component.field, 'in')"
/>
<drawer-filter
@ -114,6 +115,7 @@ defineExpose({
v-if="component.type === 'select'"
:option-list="component.option"
:title="component.title"
:property="component.property"
@filter-change="v => filterChange(v, component.field, 'in')"
/>
<drawer-enum-filter

View File

@ -25,6 +25,12 @@ const valueTextFormTree = (val, options) => {
}
return result || val
}
const timestampFormatDate = value => {
if (!value) {
return '-'
}
return new Date(value)['format']()
}
const valueText = (field, val, options) => {
for (let index = 0; index < options.length; index++) {
const element = options[index]
@ -41,6 +47,9 @@ const valueText = (field, val, options) => {
return item.name || item.label
}
}
if (element.type === 'time') {
return timestampFormatDate(val)
}
if (isTree) {
return valueTextFormTree(val, selectOption)
}

View File

@ -3,7 +3,7 @@ import { Icon } from '@/components/icon-custom'
import { propTypes } from '@/utils/propTypes'
import type { Placement } from 'element-plus-secondary'
import { ref, PropType } from 'vue'
import { XpackComponent } from '@/components/plugin'
import ShareHandler from '@/views/share/share/ShareHandler.vue'
export interface Menu {
svgName?: string
label?: string
@ -44,7 +44,8 @@ const menus = ref([
])
const handleCommand = (command: string | number | object) => {
if (command === 'share') {
shareComponent.value.invokeMethod({ methodName: 'execute' })
// shareComponent.value.invokeMethod({ methodName: 'execute' })
shareComponent.value.execute()
return
}
emit('handleCommand', command)
@ -85,9 +86,8 @@ const emit = defineEmits(['handleCommand'])
</el-dropdown-menu>
</template>
</el-dropdown>
<XpackComponent
<ShareHandler
ref="shareComponent"
jsname="c2hhcmUtaGFuZGxlcg=="
:resource-id="props.node.id"
:resource-type="props.resourceType"
:weight="node.weight"

View File

@ -171,7 +171,7 @@ const state = reactive({
'richTextView',
'liquid',
'gauge',
'text',
'indicator',
'label',
'word-cloud',
'flow-map',
@ -181,7 +181,7 @@ const state = reactive({
'richTextView',
'liquid',
'gauge',
'text',
'indicator',
'label',
'word-cloud',
'flow-map',

View File

@ -10,27 +10,45 @@
:min="min"
:max="max"
:step="step"
v-model="curComponent.style[key]"
@change="onPositionChange"
v-model="positionMounted[key]"
@change="onPositionChange(key)"
controls-position="right"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item class="form-item" :class="'form-item-' + themes">
<el-checkbox
v-if="curComponent"
size="small"
:effect="themes"
v-model="curComponent['maintainRadio']"
@change="maintainRadioChange"
>
保持宽高比
</el-checkbox>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { computed, ref, watch } from 'vue'
import { positionData } from '@/utils/attr'
import { storeToRefs } from 'pinia'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import _ from 'lodash'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { groupSizeStyleAdaptor } from '@/utils/style'
const snapshotStore = snapshotStoreWithOut()
const dvMainStore = dvMainStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
const { curComponent, canvasStyleData } = storeToRefs(dvMainStore)
const positionMounted = ref({
width: 0,
height: 0,
top: 0,
left: 0
})
withDefaults(
defineProps<{
@ -60,9 +78,57 @@ const positionKeysGroup = computed(() => {
return _list
})
const onPositionChange = () => {
const onPositionChange = key => {
if (!positionMounted.value[key]) {
positionMounted.value[key] = 0
}
const originRadio = curComponent.value.style.width / curComponent.value.style.height
curComponent.value.style[key] = Math.round(
(positionMounted.value[key] * canvasStyleData.value.scale) / 100
)
if (curComponent.value.maintainRadio) {
if (key === 'width') {
curComponent.value.style['height'] = curComponent.value.style['width'] / originRadio
positionMounted.value['height'] = Math.round(positionMounted.value['width'] / originRadio)
} else if (key === 'height') {
curComponent.value.style['width'] = curComponent.value.style['height'] * originRadio
positionMounted.value['width'] = Math.round(positionMounted.value['height'] * originRadio)
}
}
if (curComponent.value.component === 'Group') {
//Group
const parentNode = document.querySelector('#editor-canvas-main')
groupSizeStyleAdaptor(curComponent.value)
}
snapshotStore.recordSnapshotCache()
}
const maintainRadioChange = () => {
snapshotStore.recordSnapshotCache()
}
const positionInit = () => {
if (curComponent.value) {
Object.keys(positionMounted.value).forEach(key => {
positionMounted.value[key] = Math.round(
(curComponent.value.style[key] * 100) / canvasStyleData.value.scale
)
})
}
}
watch(
() => curComponent.value,
() => {
positionInit()
},
{
deep: true,
immediate: true
}
)
</script>
<style lang="less" scoped>

View File

@ -41,17 +41,17 @@ export function watermark(settings, domId) {
// 如果将水印列数设置为0或水印列数设置过大超过页面最大宽度则重新计算水印列数和水印x轴间隔
if (
defaultSettings.watermark_cols === 0 ||
parseInt(
Math.floor(
defaultSettings.watermark_x +
defaultSettings.watermark_width * defaultSettings.watermark_cols +
defaultSettings.watermark_x_space * (defaultSettings.watermark_cols - 1)
) > page_width
) {
defaultSettings.watermark_cols = parseInt(
defaultSettings.watermark_cols = Math.floor(
(page_width - defaultSettings.watermark_x + defaultSettings.watermark_x_space) /
(defaultSettings.watermark_width + defaultSettings.watermark_x_space)
)
defaultSettings.watermark_x_space = parseInt(
defaultSettings.watermark_x_space = Math.floor(
(page_width -
defaultSettings.watermark_x -
defaultSettings.watermark_width * defaultSettings.watermark_cols) /
@ -61,17 +61,17 @@ export function watermark(settings, domId) {
// 如果将水印行数设置为0或水印行数设置过大超过页面最大长度则重新计算水印行数和水印y轴间隔
if (
defaultSettings.watermark_rows === 0 ||
parseInt(
Math.floor(
defaultSettings.watermark_y +
defaultSettings.watermark_height * defaultSettings.watermark_rows +
defaultSettings.watermark_y_space * (defaultSettings.watermark_rows - 1)
) > page_height
) {
defaultSettings.watermark_rows = parseInt(
defaultSettings.watermark_rows = Math.floor(
(defaultSettings.watermark_y_space + page_height - defaultSettings.watermark_y) /
(defaultSettings.watermark_height + defaultSettings.watermark_y_space)
)
defaultSettings.watermark_y_space = parseInt(
defaultSettings.watermark_y_space = Math.floor(
(page_height -
defaultSettings.watermark_y -
defaultSettings.watermark_height * defaultSettings.watermark_rows) /
@ -186,7 +186,7 @@ export function activeWatermark(
watermark_txt = getNow()
watermark_width = 200
} else {
watermark_txt = userLoginInfo.name
watermark_txt = userLoginInfo.account
}
const settings = {
watermark_txt: watermark_txt,

View File

@ -10,6 +10,7 @@ import axios, {
import { tryShowLoading, tryHideLoading } from '@/utils/loading'
import qs from 'qs'
import { usePermissionStoreWithOut } from '@/store/modules/permission'
import { useEmbedded } from '@/store/modules/embedded'
import { useLinkStoreWithOut } from '@/store/modules/link'
import { config } from './config'
import { configHandler } from './refresh'
@ -31,9 +32,10 @@ const { result_code } = config
import { useCache } from '@/hooks/web/useCache'
const { wsCache } = useCache()
const embeddedStore = useEmbedded()
export const PATH_URL = window.DataEaseBi
? window.DataEaseBi?.baseUrl + 'de2api/'
export const PATH_URL = embeddedStore.baseUrl
? embeddedStore?.baseUrl + 'de2api/'
: import.meta.env.VITE_API_BASEPATH
export interface AxiosInstanceWithLoading extends AxiosInstance {
@ -101,14 +103,14 @@ service.interceptors.request.use(
) {
config.data = qs.stringify(config.data)
}
if (window.DataEaseBi?.baseUrl) {
config.baseURL = window.DataEaseBi.baseUrl + 'de2api/'
if (embeddedStore.baseUrl) {
config.baseURL = PATH_URL
}
if (linkStore.getLinkToken) {
;(config.headers as AxiosRequestHeaders)['X-DE-LINK-TOKEN'] = linkStore.getLinkToken
} else if (window.DataEaseBi?.token) {
;(config.headers as AxiosRequestHeaders)['X-EMBEDDED-TOKEN'] = window.DataEaseBi.token
} else if (embeddedStore.token) {
;(config.headers as AxiosRequestHeaders)['X-EMBEDDED-TOKEN'] = embeddedStore.token
}
if (wsCache.get('user.language')) {
const key = wsCache.get('user.language')

View File

@ -0,0 +1,13 @@
<template>
<div class="attr-list de-collapse-style">
<CommonAttr :element="curComponent"></CommonAttr>
</div>
</template>
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
</script>

View File

@ -0,0 +1,30 @@
<template>
<div class="circle-shape"></div>
</template>
<script setup lang="ts">
const props = defineProps({
propValue: {
type: String,
required: true,
default: ''
},
element: {
type: Object,
default() {
return {
propValue: null
}
}
}
})
</script>
<style lang="less" scoped>
.circle-shape {
width: 100%;
height: 100%;
border-radius: 50% !important;
overflow: auto;
}
</style>

View File

@ -90,7 +90,9 @@ const backgroundCustomShow = computed(() => {
return (
dashboardActive.value ||
(!dashboardActive.value &&
!['CanvasBoard', 'CanvasIcon', 'Picture'].includes(element.value.component))
!['CanvasBoard', 'CanvasIcon', 'Picture', 'CircleShape', 'RectShape'].includes(
element.value.component
))
)
})
onMounted(() => {
@ -102,6 +104,12 @@ onMounted(() => {
})
})
})
const stopEvent = e => {
if (e && e.code === 'Enter') {
e.stopPropagation()
e.preventDefault()
}
}
</script>
<template>
@ -231,6 +239,8 @@ onMounted(() => {
></el-option>
</el-select>
<el-input-number
@keydown="stopEvent"
@keyup="stopEvent"
v-else
size="middle"
style="width: 100%"

View File

@ -60,6 +60,31 @@ export const CANVAS_MATERIAL = [
}
]
},
{
category: 'DeGraphical',
title: '图形',
span: 8,
details: [
{
value: 'RectShape',
type: 'graphical',
title: '矩形',
icon: 'graphical-rect'
},
{
value: 'SvgTriangle',
type: 'graphical',
title: '三角形',
icon: 'graphical-triangle'
},
{
value: 'CircleShape',
type: 'graphical',
title: '圆形',
icon: 'graphical-circular'
}
]
},
{
category: 'CanvasIcon',
title: '图标',

View File

@ -86,7 +86,7 @@ const groupActiveChange = category => {
:data-id="groupInfo.category + '&' + chartInfo.value"
>
<Icon
v-if="chartInfo.type === 'outer_svg'"
v-if="['outer_svg', 'graphical'].includes(chartInfo.type)"
class-name="item-top-icon"
:name="chartInfo.icon"
/>

View File

@ -58,6 +58,7 @@ export const commonAttr = {
events: {},
groupStyle: {}, // 当一个组件成为 Group 的子组件时使用
isLock: false, // 是否锁定组件
maintainRadio: false, // 布局时保持宽高比例
isShow: true, // 是否显示组件
collapseName: ['position', 'background', 'style', 'picture'], // 编辑组件时记录当前使用的是哪个折叠面板再次回来时恢复上次打开的折叠面板优化用户体验
linkage: {
@ -163,7 +164,7 @@ const list = [
},
{
component: 'CanvasBoard',
name: '边框',
name: '图形',
label: '边框',
propValue: '',
icon: 'other_material_board',
@ -180,6 +181,51 @@ const list = [
color: ''
}
},
{
component: 'RectShape',
name: '矩形',
label: '矩形',
propValue: '&nbsp;',
icon: 'icon_graphical',
style: {
width: 200,
height: 200,
borderWidth: 1,
borderRadius: 5,
borderStyle: 'solid',
borderColor: '#000',
backgroundColor: ''
}
},
{
component: 'CircleShape',
name: '图形',
label: '圆形',
propValue: '&nbsp;',
icon: 'icon_graphical',
style: {
width: 200,
height: 200,
borderWidth: 1,
borderStyle: 'solid',
borderColor: '#000',
backgroundColor: ''
}
},
{
component: 'SvgTriangle',
name: '图形',
label: '三角形',
icon: 'icon_graphical',
propValue: '',
style: {
width: 200,
height: 200,
borderWidth: 1,
borderColor: '#000',
backgroundColor: 'rgba(236,231,231,0.1)'
}
},
{
component: 'DeTabs',
name: '选项卡',

View File

@ -0,0 +1,213 @@
<script setup lang="ts">
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { storeToRefs } from 'pinia'
import { ElIcon, ElMessage } from 'element-plus-secondary'
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
import { imgUrlTrans } from '@/utils/imgUtils'
import eventBus from '@/utils/eventBus'
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
withDefaults(
defineProps<{
themes?: EditorTheme
}>(),
{
themes: 'dark'
}
)
const dvMainStore = dvMainStoreWithOut()
const snapshotStore = snapshotStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
const fileList = ref([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const uploadDisabled = ref(false)
const files = ref(null)
const maxImageSize = 15000000
const handlePictureCardPreview = file => {
dialogImageUrl.value = file.url
dialogVisible.value = true
}
const handleRemove = (_, fileList) => {
uploadDisabled.value = false
curComponent.value.propValue.url = null
fileList.value = []
snapshotStore.recordSnapshotCache()
}
async function upload(file) {
uploadFileResult(file.file, fileUrl => {
snapshotStore.recordSnapshotCache()
curComponent.value.propValue.url = fileUrl
})
}
const goFile = () => {
files.value.click()
}
const reUpload = e => {
const file = e.target.files[0]
if (file.size > maxImageSize) {
sizeMessage()
}
uploadFileResult(file, fileUrl => {
snapshotStore.recordSnapshotCache()
curComponent.value.propValue.url = fileUrl
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
})
}
const sizeMessage = () => {
ElMessage.success('图片大小不符合')
}
const init = () => {
if (curComponent.value.propValue.url) {
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
} else {
fileList.value = []
}
}
watch(
() => curComponent.value.propValue.url,
() => {
init()
}
)
onMounted(() => {
init()
eventBus.on('uploadImg', goFile)
})
onBeforeUnmount(() => {
eventBus.off('uploadImg', goFile)
})
</script>
<template>
<div class="attr-list de-collapse-style">
<CommonAttr
:themes="themes"
:element="curComponent"
:background-color-picker-width="197"
:background-border-select-width="197"
>
</CommonAttr>
</div>
</template>
<style lang="less" scoped>
.de-collapse-style {
:deep(.ed-collapse-item__header) {
height: 36px !important;
line-height: 36px !important;
font-size: 12px !important;
padding: 0 !important;
font-weight: 500 !important;
.ed-collapse-item__arrow {
margin: 0 6px 0 8px;
}
}
:deep(.ed-collapse-item__content) {
padding: 16px 8px 0;
}
:deep(.ed-form-item) {
display: block;
margin-bottom: 8px;
}
:deep(.ed-form-item__label) {
justify-content: flex-start;
}
}
.disabled :deep(.el-upload--picture-card) {
display: none;
}
.avatar-uploader :deep(.ed-upload) {
width: 80px;
height: 80px;
line-height: 90px;
}
.avatar-uploader :deep(.ed-upload-list li) {
width: 80px !important;
height: 80px !important;
}
:deep(.ed-upload--picture-card) {
background: #eff0f1;
border: 1px dashed #dee0e3;
border-radius: 4px;
.ed-icon {
color: #1f2329;
}
&:hover {
.ed-icon {
color: #3370ff;
}
}
}
.img-area {
height: 80px;
width: 80px;
margin-top: 10px;
overflow: hidden;
&.img-area_dark {
:deep(.ed-upload-list__item).is-success {
border-color: #434343;
}
:deep(.ed-upload--picture-card) {
background: #373737;
border-color: #434343;
.ed-icon {
color: #ebebeb;
}
&:hover {
.ed-icon {
color: #3370ff;
}
}
}
}
&.img-area_light {
:deep(.ed-upload-list__item).is-success {
border-color: #dee0e3;
}
}
}
.image-hint {
color: #8f959e;
size: 14px;
line-height: 22px;
font-weight: 400;
margin-top: 2px;
&.image-hint_dark {
color: #757575;
}
}
.re-update-span {
cursor: pointer;
color: #3370ff;
size: 14px;
line-height: 22px;
font-weight: 400;
}
</style>

View File

@ -0,0 +1,28 @@
<template>
<div class="rect-main"></div>
</template>
<script setup lang="ts">
import { computed, toRefs } from 'vue'
const props = defineProps({
element: {
type: Object,
default() {
return {
style: {}
}
}
}
})
const { element } = toRefs(props)
const style = computed(() => element.value.style)
</script>
<style lang="less" scoped>
.rect-main {
width: 100%;
height: 100%;
}
</style>

View File

@ -70,6 +70,7 @@
:canvas-id="element.id + '--' + tabItem.name"
:preview-active="editableTabsValue === tabItem.name"
:show-position="showPosition"
:outer-scale="scale"
></de-preview>
</el-tab-pane>
</de-custom-tab>
@ -150,6 +151,11 @@ const props = defineProps({
type: String,
required: false,
default: 'canvas'
},
scale: {
type: Number,
required: false,
default: 1
}
})
const { element, isEdit, showPosition, canvasStyleData, canvasViewInfo, dvInfo } = toRefs(props)

View File

@ -0,0 +1,380 @@
<script setup lang="ts">
import { getData } from '@/api/chart'
import { ref, reactive, shallowRef, computed, CSSProperties, toRefs } from 'vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle'
import { deepCopy } from '@/utils/utils'
import { cloneDeep, defaultsDeep, defaultTo } from 'lodash-es'
import {
BASE_VIEW_CONFIG,
CHART_CONT_FAMILY_MAP,
DEFAULT_INDICATOR_NAME_STYLE,
DEFAULT_INDICATOR_STYLE
} from '@/views/chart/components/editor/util/chart'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import { hexColorToRGBA } from '@/views/chart/components/js/util'
const props = defineProps({
view: {
type: Object,
default() {
return {
propValue: null
}
}
},
showPosition: {
type: String,
required: false,
default: 'canvas'
},
scale: {
type: Number,
required: false,
default: 1
},
terminal: {
type: String,
default: 'pc'
}
})
const { view, showPosition, scale, terminal } = toRefs(props)
const dvMainStore = dvMainStoreWithOut()
const errMsg = ref('')
const isError = ref(false)
const state = reactive({
data: null,
loading: false,
totalItems: 0
})
const chartData = shallowRef<Partial<Chart['data']>>({
fields: []
})
const resultObject = computed(() => {
const list = chartData.value?.series
if (list && list.length > 0) {
return list[0]
}
return undefined
})
const resultName = computed(() => {
return resultObject.value?.name
})
const result = computed(() => {
const list = resultObject.value?.data
let _result = undefined
if (list && list.length > 0) {
_result = list[0]
}
if (_result === null || _result === undefined) {
if (view.value.senior && view.value.senior?.functionCfg?.emptyDataStrategy === 'setZero') {
_result = 0
} else {
return '-'
}
}
return _result
})
const indicatorColor = ref(DEFAULT_INDICATOR_STYLE.color)
const thresholdColor = computed(() => {
let color = indicatorColor.value
if (result.value === '-') {
return color
}
const value = result.value
if (
view.value.senior &&
view.value.senior.threshold?.enable &&
view.value.senior.threshold?.labelThreshold?.length > 0
) {
const senior = view.value.senior
for (let i = 0; i < senior.threshold.labelThreshold.length; i++) {
let flag = false
const t = senior.threshold.labelThreshold[i]
const tv = parseFloat(t.value)
if (t.term === 'eq') {
if (value === tv) {
color = t.color
flag = true
}
} else if (t.term === 'not_eq') {
if (value !== tv) {
color = t.color
flag = true
}
} else if (t.term === 'lt') {
if (value < tv) {
color = t.color
flag = true
}
} else if (t.term === 'gt') {
if (value > tv) {
color = t.color
flag = true
}
} else if (t.term === 'le') {
if (value <= tv) {
color = t.color
flag = true
}
} else if (t.term === 'ge') {
if (value >= tv) {
color = t.color
flag = true
}
} else if (t.term === 'between') {
const min = parseFloat(t.min)
const max = parseFloat(t.max)
if (min <= value && value <= max) {
color = t.color
flag = true
}
}
if (flag) {
break
}
}
}
return color
})
const formattedResult = computed(() => {
let _result = result.value
if (_result === '-') {
return _result
}
//
if (view.value.yAxis && view.value.yAxis.length > 0 && view.value.yAxis[0].formatterCfg) {
return valueFormatter(_result, view.value.yAxis[0].formatterCfg)
}
return _result
})
const emit = defineEmits(['onChartClick', 'onDrillFilters', 'onJumpClick'])
const contentStyle = ref({
display: 'flex',
'flex-direction': 'column',
'align-items': 'center',
'justify-content': 'center',
height: '100%'
})
const indicatorClass = ref<CSSProperties>({
color: thresholdColor.value,
'font-size': DEFAULT_INDICATOR_STYLE.fontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.fontFamily],
DEFAULT_INDICATOR_STYLE.fontFamily
),
'font-weight': DEFAULT_INDICATOR_STYLE.isBolder ? 'bold' : 'normal',
'font-style': DEFAULT_INDICATOR_STYLE.isItalic ? 'italic' : 'normal',
'letter-spacing': DEFAULT_INDICATOR_STYLE.letterSpace + 'px',
'text-shadow': DEFAULT_INDICATOR_STYLE.fontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style'
})
const indicatorSuffixClass = ref<CSSProperties>({
color: DEFAULT_INDICATOR_STYLE.suffixColor,
'font-size': DEFAULT_INDICATOR_STYLE.suffixFontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.suffixFontFamily],
DEFAULT_INDICATOR_STYLE.suffixFontFamily
),
'font-weight': DEFAULT_INDICATOR_STYLE.suffixIsBolder ? 'bold' : 'normal',
'font-style': DEFAULT_INDICATOR_STYLE.suffixIsItalic ? 'italic' : 'normal',
'letter-spacing': DEFAULT_INDICATOR_STYLE.suffixLetterSpace + 'px',
'text-shadow': DEFAULT_INDICATOR_STYLE.suffixFontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style'
})
const showSuffix = ref<boolean>(DEFAULT_INDICATOR_STYLE.suffixEnable)
const suffixContent = ref('')
const indicatorNameShow = ref(false)
const indicatorNameClass = ref<CSSProperties>({
color: DEFAULT_INDICATOR_NAME_STYLE.color,
'font-size': DEFAULT_INDICATOR_NAME_STYLE.fontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[DEFAULT_INDICATOR_NAME_STYLE.fontFamily],
DEFAULT_INDICATOR_NAME_STYLE.fontFamily
),
'font-weight': DEFAULT_INDICATOR_NAME_STYLE.isBolder ? 'bold' : 'normal',
'font-style': DEFAULT_INDICATOR_NAME_STYLE.isItalic ? 'italic' : 'normal',
'letter-spacing': DEFAULT_INDICATOR_NAME_STYLE.letterSpace + 'px',
'text-shadow': DEFAULT_INDICATOR_NAME_STYLE.fontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style'
})
const renderChart = async view => {
if (!view) {
return
}
const TEMP_DEFAULT_CHART = cloneDeep(BASE_VIEW_CONFIG)
delete TEMP_DEFAULT_CHART.customAttr.basicStyle.alpha
const chart = deepCopy({
...defaultsDeep(view, TEMP_DEFAULT_CHART),
data: chartData.value
})
recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value)
recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value)
if (chart.customAttr) {
const customAttr = chart.customAttr
if (customAttr.indicator) {
switch (customAttr.indicator.hPosition) {
case 'left':
contentStyle.value['align-items'] = 'flex-start'
break
case 'right':
contentStyle.value['align-items'] = 'flex-end'
break
default:
contentStyle.value['align-items'] = 'center'
}
switch (customAttr.indicator.vPosition) {
case 'top':
contentStyle.value['justify-content'] = 'flex-start'
break
case 'bottom':
contentStyle.value['justify-content'] = 'flex-end'
break
default:
contentStyle.value['justify-content'] = 'center'
}
indicatorColor.value = customAttr.indicator.color
let suffixColor = customAttr.indicator.suffixColor
if (customAttr.basicStyle && customAttr.basicStyle.alpha !== undefined) {
indicatorColor.value = hexColorToRGBA(
customAttr.basicStyle.colors[0],
customAttr.basicStyle.alpha
)
suffixColor = hexColorToRGBA(customAttr.basicStyle.colors[1], customAttr.basicStyle.alpha)
}
indicatorClass.value = {
color: thresholdColor.value,
'font-size': customAttr.indicator.fontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicator.fontFamily],
DEFAULT_INDICATOR_STYLE.fontFamily
),
'font-weight': customAttr.indicator.isBolder ? 'bold' : 'normal',
'font-style': customAttr.indicator.isItalic ? 'italic' : 'normal',
'letter-spacing': customAttr.indicator.letterSpace + 'px',
'text-shadow': customAttr.indicator.fontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style'
}
indicatorSuffixClass.value = {
color: suffixColor,
'font-size': customAttr.indicator.suffixFontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicator.suffixFontFamily],
DEFAULT_INDICATOR_STYLE.suffixFontFamily
),
'font-weight': customAttr.indicator.suffixIsBolder ? 'bold' : 'normal',
'font-style': customAttr.indicator.suffixIsItalic ? 'italic' : 'normal',
'letter-spacing': customAttr.indicator.suffixLetterSpace + 'px',
'text-shadow': customAttr.indicator.suffixFontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style'
}
showSuffix.value = customAttr.indicator.suffixEnable
suffixContent.value = defaultTo(customAttr.indicator.suffix, '')
}
if (customAttr.indicatorName && customAttr.indicatorName.show) {
let nameColor = customAttr.indicatorName.color
if (customAttr.basicStyle && customAttr.basicStyle.alpha !== undefined) {
nameColor = hexColorToRGBA(customAttr.basicStyle.colors[2], customAttr.basicStyle.alpha)
}
indicatorNameShow.value = true
indicatorNameClass.value = {
color: nameColor,
'font-size': customAttr.indicatorName.fontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicatorName.fontFamily],
DEFAULT_INDICATOR_NAME_STYLE.fontFamily
),
'font-weight': customAttr.indicatorName.isBolder ? 'bold' : 'normal',
'font-style': customAttr.indicatorName.isItalic ? 'italic' : 'normal',
'letter-spacing': customAttr.indicatorName.letterSpace + 'px',
'text-shadow': customAttr.indicatorName.fontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style'
}
} else {
indicatorNameShow.value = false
}
}
}
const calcData = (view, callback) => {
if (view.tableId || view['dataFrom'] === 'template') {
state.loading = true
isError.value = false
const v = JSON.parse(JSON.stringify(view))
getData(v)
.then(res => {
if (res.code && res.code !== 0) {
isError.value = true
errMsg.value = res.msg
} else {
chartData.value = res?.data as Partial<Chart['data']>
emit('onDrillFilters', res?.drillFilters)
dvMainStore.setViewDataDetails(view.id, chartData.value)
renderChart(res)
}
callback?.()
})
.catch(() => {
callback?.()
})
} else {
if (view.type === 'map') {
renderChart(view)
}
callback?.()
}
}
defineExpose({
calcData,
renderChart
})
</script>
<template>
<div :style="contentStyle">
<div>
<span :style="indicatorClass">{{ formattedResult }}</span>
<span :style="indicatorSuffixClass" v-if="showSuffix">{{ suffixContent }}</span>
</div>
<div v-if="indicatorNameShow">
<span :style="indicatorNameClass">{{ resultName }}</span>
</div>
</div>
</template>
<style scoped lang="less"></style>

View File

@ -0,0 +1,13 @@
<template>
<div class="attr-list de-collapse-style">
<CommonAttr :element="curComponent"></CommonAttr>
</div>
</template>
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
</script>

View File

@ -0,0 +1,31 @@
<template>
<div class="circle-shape">
<v-text :prop-value="element.propValue" :element="element" />
</div>
</template>
<script setup lang="ts">
const props = defineProps({
propValue: {
type: String,
required: true,
default: ''
},
element: {
type: Object,
default() {
return {
propValue: null
}
}
}
})
</script>
<style lang="less" scoped>
.rect-shape {
width: 100%;
height: 100%;
overflow: auto;
}
</style>

View File

@ -127,7 +127,7 @@ const init = ref({
'| bdmap indent2em lineheight formatpainter axupimgs',
toolbar_location: '/',
font_formats:
'微软雅黑=Microsoft YaHei;宋体=SimSun;黑体=SimHei;仿宋=FangSong;华文黑体=STHeiti;华文楷体=STKaiti;华文宋体=STSong;华文仿宋=STFangsong;Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings',
'阿里巴巴普惠体=阿里巴巴普惠体 3.0 55 Regular L3;微软雅黑=Microsoft YaHei;宋体=SimSun;黑体=SimHei;仿宋=FangSong;华文黑体=STHeiti;华文楷体=STKaiti;华文宋体=STSong;华文仿宋=STFangsong;Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings',
fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px', //
menubar: false,
placeholder: '',
@ -271,8 +271,16 @@ const showPlaceHolder = computed<boolean>(() => {
)
})
const editActive = computed<boolean>(() => {
if (element.value.canvasId.includes('Group') && !active.value) {
return false
} else {
return true
}
})
const setEdit = () => {
if (computedCanEdit.value) {
if (computedCanEdit.value && editActive.value) {
canEdit.value = true
element.value['editing'] = true
myValue.value = element.value.propValue.textValue
@ -285,9 +293,29 @@ const reShow = () => {
editShow.value = false
nextTick(() => {
editShow.value = true
editCursor()
})
}
const editCursor = () => {
setTimeout(() => {
const myDiv = document.getElementById(tinymceId)
//
const range = document.createRange()
const sel = window.getSelection()
if (myDiv.childNodes) {
range.setStart(myDiv.childNodes[myDiv.childNodes.length - 1], 1)
range.collapse(false)
sel.removeAllRanges()
sel.addRange(range)
}
//
if (myDiv.focus) {
myDiv.focus()
}
}, 100)
}
const calcData = (view: Chart, callback) => {
isError.value = false
if (view.tableId || view['dataFrom'] === 'template') {

View File

@ -0,0 +1,13 @@
<template>
<div class="attr-list de-collapse-style">
<CommonAttr :element="curComponent"></CommonAttr>
</div>
</template>
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
</script>

View File

@ -0,0 +1,99 @@
<template>
<div class="svg-star-container">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon
ref="star"
:points="points"
:stroke="element.style.borderColor"
:fill="element.style.backgroundColor"
:stroke-width="element.style.borderWidth"
/>
</svg>
<v-text :prop-value="element.propValue" :element="element" />
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, toRefs, watch } from 'vue'
const props = defineProps({
propValue: {
type: String,
required: true,
default: ''
},
element: {
type: Object,
default() {
return {
propValue: null
}
}
}
})
const { propValue, element } = toRefs(props)
const points = ref('')
watch(
() => element.value.style.width,
val => {
draw()
}
)
watch(
() => element.value.style.height,
val => {
draw()
}
)
onMounted(() => {
draw()
})
const draw = () => {
const { width, height } = element.value.style
drawPolygon(width, height)
}
const drawPolygon = (width, height) => {
//
const pointsArray = [
[0.5, 0],
[0.625, 0.375],
[1, 0.375],
[0.75, 0.625],
[0.875, 1],
[0.5, 0.75],
[0.125, 1],
[0.25, 0.625],
[0, 0.375],
[0.375, 0.375]
]
const coordinatePoints = pointsArray.map(point => width * point[0] + ' ' + height * point[1])
points.value = coordinatePoints.toString()
}
</script>
<style lang="less" scoped>
.svg-star-container {
width: 100%;
height: 100%;
svg {
width: 100%;
height: 100%;
}
.v-text {
position: absolute;
top: 58%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
height: 40%;
}
}
</style>

View File

@ -0,0 +1,13 @@
<template>
<div class="attr-list de-collapse-style">
<CommonAttr :element="curComponent"></CommonAttr>
</div>
</template>
<script setup lang="ts">
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
</script>

View File

@ -0,0 +1,90 @@
<template>
<div class="svg-triangle-container">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon
ref="star"
:points="points"
:stroke="element.style.borderColor"
:fill="element.style.backgroundColor"
:stroke-width="element.style.borderWidth"
/>
</svg>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, toRefs, watch } from 'vue'
const props = defineProps({
propValue: {
type: String,
required: true,
default: ''
},
element: {
type: Object,
default() {
return {
propValue: null
}
}
}
})
const { propValue, element } = toRefs(props)
const points = ref('')
watch(
() => element.value.style.width,
val => {
draw()
}
)
watch(
() => element.value.style.height,
val => {
draw()
}
)
onMounted(() => {
draw()
})
const draw = () => {
const { width, height } = element.value.style
drawPolygon(width, height)
}
const drawPolygon = (width, height) => {
//
const pointsArray = [
[0.5, 0.05],
[1, 0.95],
[0, 0.95]
]
const coordinatePoints = pointsArray.map(point => width * point[0] + ' ' + height * point[1])
points.value = coordinatePoints.toString()
}
</script>
<style lang="less" scoped>
.svg-triangle-container {
width: 100%;
height: 100%;
svg {
width: 100%;
height: 100%;
}
.v-text {
position: absolute;
top: 72%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
height: 40%;
}
}
</style>

View File

@ -23,7 +23,7 @@ interface SelectConfig {
timeNum: number
relativeToCurrentType: string
around: string
arbitraryTime: string
arbitraryTime: Date
timeGranularity: DatePickType
}

View File

@ -1,10 +1,11 @@
<script lang="ts" setup>
import { toRefs, PropType, ref, onBeforeMount, watch, computed } from 'vue'
import { toRefs, nextTick, PropType, ref, onBeforeMount, watch, computed } from 'vue'
import { Calendar } from '@element-plus/icons-vue'
import { type DatePickType } from 'element-plus-secondary'
import { getCustomTime } from './time-format'
interface SelectConfig {
timeType: string
timeGranularityMultiple: DatePickType
defaultValue: [Date, Date]
selectValue: [Date, Date]
defaultValueCheck: boolean
@ -25,6 +26,7 @@ const props = defineProps({
type: Object as PropType<SelectConfig>,
default: () => {
return {
timeGranularityMultiple: 'datetimerange',
defaultValue: [],
selectValue: [],
timeType: 'fixed',
@ -43,13 +45,13 @@ const props = defineProps({
}
})
const selectValue = ref<[Date, Date]>([new Date(), new Date()])
const { config } = toRefs(props)
const timeConfig = computed(() => {
const {
timeNum,
relativeToCurrentType,
timeGranularityMultiple,
around,
defaultValueCheck,
arbitraryTime,
@ -63,6 +65,7 @@ const timeConfig = computed(() => {
timeNum,
relativeToCurrentType,
around,
timeGranularityMultiple,
defaultValueCheck,
arbitraryTime,
timeGranularity,
@ -106,6 +109,7 @@ const init = () => {
defaultValueCheck,
arbitraryTime,
timeGranularity,
timeGranularityMultiple,
timeNumRange,
relativeToCurrentTypeRange,
aroundRange,
@ -121,29 +125,39 @@ const init = () => {
relativeToCurrentType,
timeGranularity,
around,
arbitraryTime
arbitraryTime,
timeGranularityMultiple,
'start-config'
)
const endTime = getCustomTime(
timeNumRange,
relativeToCurrentTypeRange,
timeGranularity,
aroundRange,
arbitraryTimeRange
arbitraryTimeRange,
timeGranularityMultiple,
'end-config'
)
selectValue.value = [startTime, endTime]
}
onBeforeMount(() => {
init()
})
const formatDate = computed(() => {
return (config.value.timeGranularityMultiple as string) === 'yearrange' ? 'YYYY' : undefined
})
</script>
<template>
<el-date-picker
disabled
v-model="selectValue"
type="datetimerange"
:type="config.timeGranularityMultiple"
:prefix-icon="Calendar"
:format="formatDate"
:range-separator="$t('cron.to')"
:start-placeholder="$t('datasource.start_time')"
:end-placeholder="$t('datasource.end_time')"

View File

@ -197,6 +197,12 @@ const setTypeChange = () => {
nextTick(() => {
curComponent.value.field.id = ''
inputCom.value?.displayTypeChange?.()
if (
+curComponent.value.displayType === 7 &&
['yearrange', 'monthrange', 'datetimerange'].includes(curComponent.value.timeGranularity)
) {
curComponent.value.timeGranularityMultiple = curComponent.value.timeGranularity
}
})
}
@ -284,6 +290,7 @@ const validate = () => {
timeNum,
relativeToCurrentType,
around,
timeGranularityMultiple,
arbitraryTime,
timeGranularity,
timeNumRange,
@ -297,14 +304,18 @@ const validate = () => {
relativeToCurrentType,
timeGranularity,
around,
arbitraryTime
arbitraryTime,
timeGranularityMultiple,
'start-config'
)
const endTime = getCustomTime(
timeNumRange,
relativeToCurrentTypeRange,
timeGranularity,
aroundRange,
arbitraryTimeRange
arbitraryTimeRange,
timeGranularityMultiple,
'end-config'
)
if (+startTime > +endTime) {
ElMessage.error('结束时间必须大于开始时间!')
@ -635,6 +646,13 @@ const dynamicTime = computed(() => {
const relativeToCurrentTypeList = computed(() => {
if (!curComponent.value) return []
let index = ['year', 'month', 'date', 'datetime'].indexOf(curComponent.value.timeGranularity) + 1
if (+curComponent.value.displayType === 7) {
index =
['yearrange', 'monthrange', 'datetimerange'].indexOf(
curComponent.value.timeGranularityMultiple
) + 1
}
return [
{
label: '年',
@ -648,7 +666,7 @@ const relativeToCurrentTypeList = computed(() => {
label: '日',
value: 'date'
}
].slice(0, ['year', 'month', 'date', 'datetime'].indexOf(curComponent.value.timeGranularity) + 1)
].slice(0, index)
})
const timeGranularityChange = (val: string) => {
@ -662,6 +680,21 @@ const timeGranularityChange = (val: string) => {
curComponent.value.relativeToCurrent = relativeToCurrentList.value[0]?.value
}
}
const timeGranularityMultipleChange = (val: string) => {
if (
['yearrange', 'monthrange', 'datetimerange'].indexOf(val) <
['year', 'month', 'date'].indexOf(curComponent.value.relativeToCurrentType)
) {
curComponent.value.relativeToCurrentType = 'year'
}
if (
['yearrange', 'monthrange', 'datetimerange'].indexOf(val) <
['year', 'month', 'date'].indexOf(curComponent.value.relativeToCurrentTypeRange)
) {
curComponent.value.relativeToCurrentTypeRange = 'year'
}
}
const aroundList = [
{
label: '前',
@ -968,9 +1001,12 @@ defineExpose({
<div class="value">
<template v-if="curComponent.displayType === '7'">
<el-select
@change="timeGranularityMultipleChange"
placeholder="请选择时间粒度"
v-model="curComponent.timeGranularityMultiple"
>
<el-option label="年" value="yearrange" />
<el-option label="年月" value="monthrange" />
<el-option label="年月日时分秒" value="datetimerange" />
</el-select>
</template>
@ -1284,7 +1320,13 @@ defineExpose({
</div>
</template>
<template v-else-if="dynamicTime && curComponent.displayType === '7'">
<div class="setting">
<div
class="setting"
:class="
['yearrange', 'monthrange'].includes(curComponent.timeGranularityMultiple) &&
'is-year-month-range'
"
>
<div class="setting-label">开始时间</div>
<div class="setting-input with-date range">
<el-input-number
@ -1311,7 +1353,13 @@ defineExpose({
<el-time-picker v-model="curComponent.arbitraryTime" />
</div>
</div>
<div class="setting">
<div
class="setting"
:class="
['yearrange', 'monthrange'].includes(curComponent.timeGranularityMultiple) &&
'is-year-month-range'
"
>
<div class="setting-label">结束时间</div>
<div class="setting-input with-date range">
<el-input-number
@ -1651,6 +1699,7 @@ defineExpose({
padding-left: 24px;
display: flex;
flex-wrap: wrap;
.range-title,
.params-start,
.params-end {
@ -1729,6 +1778,20 @@ defineExpose({
}
}
}
&.is-year-month-range {
.setting-input {
&.with-date {
.ed-input-number,
.ed-select {
width: 103px;
}
}
.ed-date-editor.ed-input {
display: none;
}
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More