Merge branch 'dev-v2' into pr@dev-v2@feat_report_task
@ -865,7 +865,7 @@ public class ChartDataManage {
|
||||
return list;
|
||||
}
|
||||
|
||||
var assistLineCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("assistLineCfg")), ChartSeniorAssistCfgDTO.class);
|
||||
ChartSeniorAssistCfgDTO assistLineCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("assistLineCfg")), ChartSeniorAssistCfgDTO.class);
|
||||
if (null == assistLineCfg || !assistLineCfg.isEnable()) {
|
||||
return list;
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ public class DatasetDataManage {
|
||||
// build query sql
|
||||
SQLMeta sqlMeta = new SQLMeta();
|
||||
Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs);
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, crossDs, dsMap);
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, fields, crossDs, dsMap);
|
||||
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, fields, crossDs, dsMap);
|
||||
Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap);
|
||||
String querySQL;
|
||||
@ -459,7 +459,7 @@ public class DatasetDataManage {
|
||||
rowPermissionsTree = permissionManage.getRowPermissionsTree(datasetGroupInfoDTO.getId(), user.getUserId());
|
||||
}
|
||||
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, crossDs, dsMap);
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, datasetGroupInfoDTO.getAllFields(), crossDs, dsMap);
|
||||
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, fields, crossDs, dsMap);
|
||||
Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap);
|
||||
String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, true, 0, 1000);
|
||||
@ -585,7 +585,7 @@ public class DatasetDataManage {
|
||||
datasetGroupInfoDTO.setSortFields(Collections.singletonList(deSortField));
|
||||
}
|
||||
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, crossDs, dsMap);
|
||||
Field2SQLObj.field2sqlObj(sqlMeta, fields, datasetGroupInfoDTO.getAllFields(), crossDs, dsMap);
|
||||
WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, fields, crossDs, dsMap);
|
||||
Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap);
|
||||
String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, 0, 1000);
|
||||
|
@ -47,7 +47,7 @@ public class SQLConstants {
|
||||
|
||||
public static final String FIELD_NAME = "%s.`%s`";
|
||||
|
||||
public static final String FIELD_DOT = "`%s`";
|
||||
public static final String FIELD_DOT = "%s";
|
||||
|
||||
public static final String UNIX_TIMESTAMP = "DE_UNIX_TIMESTAMP(%s)";
|
||||
|
||||
|
@ -45,6 +45,9 @@ public class CustomWhere2Str {
|
||||
// 给计算字段处加一个占位符,后续SQL方言转换后再替换
|
||||
originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId());
|
||||
fieldsDialect.put(originName, calcFieldExp);
|
||||
if (isCross) {
|
||||
originName = calcFieldExp;
|
||||
}
|
||||
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) {
|
||||
originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName());
|
||||
} else {
|
||||
@ -86,18 +89,17 @@ public class CustomWhere2Str {
|
||||
res.add("(" + whereName + " IN ('" + String.join("','", request.getEnumCheckField()) + "'))");
|
||||
}
|
||||
} else {
|
||||
if (field.getDeType() == 1) {
|
||||
// 规定几种日期格式,一一匹配,匹配到就是该格式
|
||||
whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName);
|
||||
}
|
||||
|
||||
List<ChartCustomFilterItemDTO> filter = request.getFilter();
|
||||
for (ChartCustomFilterItemDTO filterItemDTO : filter) {
|
||||
String value = filterItemDTO.getValue();
|
||||
String whereTerm = Utils.transFilterTerm(filterItemDTO.getTerm());
|
||||
String whereValue = "";
|
||||
|
||||
// String whereNameReal;
|
||||
if (field.getDeType() == 1) {
|
||||
// 规定几种日期格式,一一匹配,匹配到就是该格式
|
||||
whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName);
|
||||
}
|
||||
|
||||
if (StringUtils.equalsIgnoreCase(filterItemDTO.getTerm(), "null")) {
|
||||
whereValue = "";
|
||||
} else if (StringUtils.equalsIgnoreCase(filterItemDTO.getTerm(), "not_null")) {
|
||||
@ -113,12 +115,12 @@ public class CustomWhere2Str {
|
||||
} else {
|
||||
// 如果是时间字段过滤,当条件是等于和不等于的时候转换成between和not between
|
||||
if (field.getDeType() == 1) {
|
||||
if (StringUtils.containsIgnoreCase(whereTerm, "=")) {
|
||||
if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) {
|
||||
whereTerm = " BETWEEN ";
|
||||
// 把value类似过滤组件处理,获得start time和end time
|
||||
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
|
||||
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime"));
|
||||
} else if (StringUtils.containsIgnoreCase(whereTerm, "<>")) {
|
||||
} else if (StringUtils.equalsIgnoreCase(whereTerm, " <> ")) {
|
||||
whereTerm = " NOT BETWEEN ";
|
||||
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
|
||||
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime"));
|
||||
|
@ -39,6 +39,9 @@ public class Dimension2SQLObj {
|
||||
// 给计算字段处加一个占位符,后续SQL方言转换后再替换
|
||||
originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId());
|
||||
fieldsDialect.put(originField, calcFieldExp);
|
||||
if (isCross) {
|
||||
originField = calcFieldExp;
|
||||
}
|
||||
} else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_COPY)) {
|
||||
originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getDataeaseName());
|
||||
} else {
|
||||
|
@ -53,6 +53,9 @@ public class ExtWhere2Str {
|
||||
// 给计算字段处加一个占位符,后续SQL方言转换后再替换
|
||||
originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId());
|
||||
fieldsDialect.put(originName, calcFieldExp);
|
||||
if (isCross) {
|
||||
originName = calcFieldExp;
|
||||
}
|
||||
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) {
|
||||
originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName());
|
||||
} else {
|
||||
|
@ -20,7 +20,7 @@ import java.util.*;
|
||||
*/
|
||||
public class Field2SQLObj {
|
||||
|
||||
public static void field2sqlObj(SQLMeta meta, List<DatasetTableFieldDTO> fields, boolean isCross, Map<Long, DatasourceSchemaDTO> dsMap) {
|
||||
public static void field2sqlObj(SQLMeta meta, List<DatasetTableFieldDTO> fields, List<DatasetTableFieldDTO> originFields, boolean isCross, Map<Long, DatasourceSchemaDTO> dsMap) {
|
||||
SQLObj tableObj = meta.getTable();
|
||||
if (ObjectUtils.isEmpty(tableObj)) {
|
||||
return;
|
||||
@ -33,10 +33,13 @@ public class Field2SQLObj {
|
||||
String originField;
|
||||
if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_CALC)) {
|
||||
// 解析origin name中有关联的字段生成sql表达式
|
||||
String calcFieldExp = Utils.calcFieldRegex(x.getOriginName(), tableObj, fields, isCross, dsMap);
|
||||
String calcFieldExp = Utils.calcFieldRegex(x.getOriginName(), tableObj, originFields, isCross, dsMap);
|
||||
// 给计算字段处加一个占位符,后续SQL方言转换后再替换
|
||||
originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId());
|
||||
fieldsDialect.put(originField, calcFieldExp);
|
||||
if (isCross) {
|
||||
originField = calcFieldExp;
|
||||
}
|
||||
// 此处是数据集预览,获取数据库原始字段枚举值等操作使用,如果遇到聚合函数则将originField设置为null
|
||||
for (String func : FunctionConstant.AGG_FUNC) {
|
||||
if (Utils.matchFunction(func, calcFieldExp)) {
|
||||
|
@ -11,8 +11,8 @@ import io.dataease.engine.constant.SQLConstants;
|
||||
import io.dataease.engine.utils.Utils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -24,8 +24,8 @@ public class Order2SQLObj {
|
||||
|
||||
public static void getOrders(SQLMeta meta, List<DatasetTableFieldDTO> fields, List<DeSortField> sortFields, boolean isCross, Map<Long, DatasourceSchemaDTO> dsMap) {
|
||||
SQLObj tableObj = meta.getTable();
|
||||
List<SQLObj> xOrders = meta.getXOrders();
|
||||
if (ObjectUtils.isEmpty(tableObj) || CollectionUtils.isEmpty(xOrders)) {
|
||||
List<SQLObj> xOrders = meta.getXOrders() == null ? new ArrayList<>() : meta.getXOrders();
|
||||
if (ObjectUtils.isEmpty(tableObj)) {
|
||||
return;
|
||||
}
|
||||
if (ObjectUtils.isNotEmpty(sortFields)) {
|
||||
@ -35,6 +35,7 @@ public class Order2SQLObj {
|
||||
SQLObj order = buildSortField(deSortField, tableObj, i, fields, isCross, dsMap);
|
||||
xOrders.add(order);
|
||||
}
|
||||
meta.setXOrders(xOrders);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,9 @@ public class Quota2SQLObj {
|
||||
// 给计算字段处加一个占位符,后续SQL方言转换后再替换
|
||||
originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, y.getId());
|
||||
fieldsDialect.put(originField, calcFieldExp);
|
||||
if (isCross) {
|
||||
originField = calcFieldExp;
|
||||
}
|
||||
} else if (ObjectUtils.isNotEmpty(y.getExtField()) && Objects.equals(y.getExtField(), ExtFieldConstant.EXT_COPY)) {
|
||||
originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getDataeaseName());
|
||||
} else {
|
||||
|
@ -88,6 +88,9 @@ public class WhereTree2Str {
|
||||
// 给计算字段处加一个占位符,后续SQL方言转换后再替换
|
||||
originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId());
|
||||
fieldsDialect.put(originName, calcFieldExp);
|
||||
if (isCross) {
|
||||
originName = calcFieldExp;
|
||||
}
|
||||
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && Objects.equals(field.getExtField(), ExtFieldConstant.EXT_COPY)) {
|
||||
originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName());
|
||||
} else {
|
||||
@ -149,12 +152,12 @@ public class WhereTree2Str {
|
||||
} else {
|
||||
// 如果是时间字段过滤,当条件是等于和不等于的时候转换成between和not between
|
||||
if (field.getDeType() == 1) {
|
||||
if (StringUtils.containsIgnoreCase(whereTerm, "=")) {
|
||||
if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) {
|
||||
whereTerm = " BETWEEN ";
|
||||
// 把value类似过滤组件处理,获得start time和end time
|
||||
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
|
||||
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime"));
|
||||
} else if (StringUtils.containsIgnoreCase(whereTerm, "<>")) {
|
||||
} else if (StringUtils.equalsIgnoreCase(whereTerm, " <> ")) {
|
||||
whereTerm = " NOT BETWEEN ";
|
||||
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
|
||||
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime"));
|
||||
|
@ -3,6 +3,7 @@ package io.dataease.visualization.server;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO;
|
||||
import io.dataease.api.visualization.VisualizationLinkJumpApi;
|
||||
import io.dataease.api.visualization.dto.VisualizationComponentDTO;
|
||||
import io.dataease.api.visualization.dto.VisualizationLinkJumpDTO;
|
||||
import io.dataease.api.visualization.dto.VisualizationLinkJumpInfoDTO;
|
||||
import io.dataease.api.visualization.request.VisualizationLinkJumpBaseRequest;
|
||||
@ -144,14 +145,18 @@ public class VisualizationLinkJumpService implements VisualizationLinkJumpApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VisualizationViewTableVO> viewTableDetailList(Long dvId) {
|
||||
public VisualizationComponentDTO viewTableDetailList(Long dvId) {
|
||||
DataVisualizationInfo dvInfo = dataVisualizationInfoMapper.selectById(dvId);
|
||||
List<VisualizationViewTableVO> result;
|
||||
String componentData;
|
||||
if (dvInfo != null) {
|
||||
List<VisualizationViewTableVO> result = extVisualizationLinkJumpMapper.getViewTableDetails(dvId);
|
||||
return result.stream().filter(viewTableInfo -> dvInfo.getComponentData().indexOf(viewTableInfo.getId().toString()) > -1).collect(Collectors.toList());
|
||||
}else {
|
||||
return new ArrayList<>();
|
||||
result = extVisualizationLinkJumpMapper.getViewTableDetails(dvId).stream().filter(viewTableInfo -> dvInfo.getComponentData().indexOf(viewTableInfo.getId().toString()) > -1).collect(Collectors.toList());
|
||||
componentData = dvInfo.getComponentData();
|
||||
} else {
|
||||
result = new ArrayList<>();
|
||||
componentData = "[]";
|
||||
}
|
||||
return new VisualizationComponentDTO(componentData,result);
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
"axios": "^1.3.3",
|
||||
"crypto-js": "^4.1.1",
|
||||
"dayjs": "^1.11.9",
|
||||
"element-plus-secondary": "^0.5.5",
|
||||
"element-plus-secondary": "^0.5.6",
|
||||
"element-resize-detector": "^1.2.4",
|
||||
"file-saver": "^2.0.5",
|
||||
"html-to-image": "^1.11.11",
|
||||
|
@ -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="1713773038663" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6292" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M960 64H64C28.8 64 0 92.8 0 128v768c0 35.2 28.8 64 64 64h896c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z m-26.56 808h-832v-704h832v704z" p-id="6293"></path><path d="M695.36 735.04c-32.64 0-60.48-9.28-81.92-28.16-22.4-19.2-33.92-44.48-33.92-74.88 0-55.04 32.96-120.96 190.72-120.96h5.12c-0.64-11.52-1.6-18.24-2.24-21.76-0.64-2.88-2.24-7.04-9.6-11.52-3.84-2.24-13.44-6.4-36.48-6.4-49.6 0-49.92 8-50.56 20.16l-0.64 18.24h-88.96l1.28-20.48c5.44-85.76 78.4-96.64 141.76-96.64 40.32 0 72.64 8.64 96.32 25.92 25.6 18.56 38.4 53.12 38.4 102.4v206.72h-88.64v-11.84c-23.68 13.12-50.56 19.2-80.64 19.2z m64.64-147.52c-90.56 0-90.56 31.36-90.56 41.92 0 11.2 4.48 15.68 8.32 18.56 14.4 10.56 45.76 11.52 71.68-1.28 10.88-5.44 19.2-11.84 25.92-20.16v-38.72h-15.36z m-177.6 140.8h-100.16l-45.44-121.92h-137.6L256 728.32H160l165.12-439.36h82.24l175.04 439.36z m-255.36-202.56h80.32l-40.96-110.72-39.36 110.72z" p-id="6294"></path></svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -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="1713772528957" class="icon" viewBox="0 0 1029 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5278" xmlns:xlink="http://www.w3.org/1999/xlink" width="200.9765625" height="200"><path d="M860.16025 508.587c0-20.48-3.413-40.96-20.48-58.027L505.17325 95.573c-27.306-27.306-68.266-27.306-95.573 0l-98.987 102.4-143.36-153.6c-13.653-13.653-34.133-13.653-47.786 0-13.654 17.067-13.654 37.547 0 51.2l143.36 150.187L20.48025 498.347c-27.307 27.306-27.307 71.68 0 102.4l341.333 354.986c27.307 27.307 68.267 27.307 95.574 0L843.09325 552.96c10.24-13.653 17.067-30.72 17.067-44.373z m-740.693-6.827l191.146-201.387L430.08025 426.667c13.653 13.653 34.133 13.653 47.787 0 13.653-13.654 13.653-37.547 0-51.2L358.40025 249.173l95.573-102.4 337.92 354.987H119.46725z m907.946 334.507c-6.826-75.094-136.533-286.72-136.533-286.72s-126.293 201.386-136.533 286.72C737.28025 976.213 822.61325 993.28 890.88025 993.28c68.267 0 146.773-13.653 136.533-157.013z m0 0" p-id="5279"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -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="1713772449367" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4293" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M770 900c34.242 0 62 27.758 62 62 0 34.242-27.758 62-62 62H254c-34.242 0-62-27.758-62-62 0-34.242 27.758-62 62-62h516z m-78-736c59.05 0 107.032 47.391 107.986 106.214L800 272v33.867c0 19.882-16.118 36-36 36-19.683 0-35.677-15.797-35.995-35.405l-0.005-0.595V272c0-19.683-15.797-35.677-35.405-35.995L692 236H270c-19.683 0-35.677 15.797-35.995 35.405L234 272v424c0 19.683 15.797 35.677 35.405 35.995L270 732h162.756c19.882 0 36 16.118 36 36 0 19.683-15.797 35.677-35.405 36H270c-59.05 0-107.032-47.391-107.986-106.214L162 696V272c0-59.05 47.391-107.032 106.214-107.986L270 164h422z m171.445 200.445l49.497 49.497c9.372 9.372 9.372 24.568 0 33.94l-0.088 0.088-281.16 278.274-95.972 28.583c-8.47 2.522-17.38-2.298-19.902-10.767a16 16 0 0 1 0.228-9.84l31.74-90.946L829.59 364.358c9.387-9.29 24.515-9.252 33.854 0.087z" p-id="4294"></path></svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -1 +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="1689150709983" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4725" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M231.424 227.04128v160.89088h338.37056a63.8976 63.8976 0 0 1 63.8976 63.8976v314.40896H794.624V331.776a104.61184 104.61184 0 0 0-104.61184-104.61184z" p-id="4726" data-spm-anchor-id="a313x.7781069.0.i0" class="selected"></path></svg>
|
||||
<?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="1713521630002" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4283" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M396 140h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m-44 684h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m524-204h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM192 344h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m0 160h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m0 160h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m0 160h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m320 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m160 0h-56c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m140-284c0 4.4 3.6 8 8 8h56c4.4 0 8-3.6 8-8V370c0-127-103-230-230-230H484c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h170c87.3 0 158 70.7 158 158v170zM236 96H92c-4.4 0-8 3.6-8 8v144c0 4.4 3.6 8 8 8h144c4.4 0 8-3.6 8-8V104c0-4.4-3.6-8-8-8z m-48 101.6c0 1.3-1.1 2.4-2.4 2.4h-43.2c-1.3 0-2.4-1.1-2.4-2.4v-43.2c0-1.3 1.1-2.4 2.4-2.4h43.2c1.3 0 2.4 1.1 2.4 2.4v43.2zM920 780H776c-4.4 0-8 3.6-8 8v144c0 4.4 3.6 8 8 8h144c4.4 0 8-3.6 8-8V788c0-4.4-3.6-8-8-8z m-48 101.6c0 1.3-1.1 2.4-2.4 2.4h-43.2c-1.3 0-2.4-1.1-2.4-2.4v-43.2c0-1.3 1.1-2.4 2.4-2.4h43.2c1.3 0 2.4 1.1 2.4 2.4v43.2z" p-id="4284"></path></svg>
|
||||
|
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 1.7 KiB |
@ -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="1713774473081" class="icon" viewBox="0 0 1129 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9335" xmlns:xlink="http://www.w3.org/1999/xlink" width="220.5078125" height="200"><path d="M0 741.517241h1129.931034v282.482759H0zM0 353.103448h1129.931034v211.862069H0zM0 0h1129.931034v141.241379H0z" p-id="9336"></path></svg>
|
After Width: | Height: | Size: 478 B |
@ -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="1713752109906" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4245" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M176 261.75H92v-168h84z m288-168H272v168h192z m288 0H560v168h192z m180 0h-84v168h84z m-798 378H92v126h42z m420 126h84v-126h-84z m-168 0h84v-126h-84z m-168 0h84v-126h-84z m504 0h84v-126h-84z m168 0h42v-126h-42z m42 252H92v84h840z" p-id="4246"></path></svg>
|
After Width: | Height: | Size: 590 B |
@ -1 +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="1693218467455" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15153" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M116.181404 133.722146 116.181404 441.133425 201.417293 441.133425 201.417293 133.722146 317.598697 133.722146 317.598697 64 0 64 0 133.722146 116.181404 133.722146ZM412.356282 125.799174 412.356282 64 335.263948 64 335.263948 125.799174 412.356282 125.799174ZM335.263948 168.055021 335.263948 441.133425 412.356282 441.133425 412.356282 168.055021 335.263948 168.055021ZM550.003263 168.055021 550.003263 86.184319 472.91093 86.184319 472.91093 168.055021 426.221206 168.055021 426.221206 218.233837 472.91093 218.233837 472.91093 379.33425C472.91093 393.067469 475.263489 404.159517 479.968678 412.610729 484.673868 421.06194 491.098164 427.576318 499.241762 432.154058 507.385359 436.731797 516.795596 439.812922 527.472757 441.397524 538.149917 442.982126 549.4603 443.774415 561.404242 443.774415 569.004932 443.774415 576.786475 443.598351 584.749103 443.246218 592.711731 442.894084 599.950376 442.189827 606.465253 441.133425L606.465253 383.031637C602.845877 383.735905 599.045588 384.264097 595.064275 384.616231 591.082961 384.968365 586.92074 385.144429 582.577488 385.144429 569.547733 385.144429 560.86136 383.031658 556.518108 378.806052 552.174856 374.580447 550.003263 366.129362 550.003263 353.452545L550.003263 218.233837 606.465253 218.233837 606.465253 168.055021 550.003263 168.055021ZM624.673409 64 624.673409 441.133425 701.765741 441.133425 701.765741 64 624.673409 64ZM930.620557 275.279229 805.209786 275.279229C805.571725 269.997222 806.748006 264.011037 808.738662 257.320495 810.729318 250.629953 814.167674 244.291639 819.05383 238.305364 823.939994 232.31909 830.454771 227.301258 838.598368 223.25172 846.741965 219.20218 856.966547 217.177441 869.272429 217.177441 888.09319 217.177441 902.118061 222.107241 911.347469 231.966988 920.576883 241.826734 927.001178 256.264004 930.620557 275.279229L930.620557 275.279229ZM805.209786 322.817057 1007.71289 322.817057C1009.16064 301.689028 1007.350976 281.441637 1002.283853 262.074278 997.216723 242.706918 988.982765 225.45262 977.581728 210.310867 966.180691 195.169113 951.612922 183.10871 933.877978 174.129299 916.143034 165.149886 895.33193 160.660248 871.444045 160.660248 850.089722 160.660248 830.635866 164.357597 813.081888 171.752407 795.527917 179.147217 780.417248 189.270913 767.749427 202.123796 755.081613 214.97668 745.30944 230.206239 738.432627 247.81293 731.555808 265.41962 728.117453 284.434561 728.117453 304.858322 728.117453 325.986351 731.465325 345.35342 738.161171 362.96011 744.857018 380.566801 754.357741 395.708327 766.663622 408.385144 778.969498 421.061962 793.98969 430.833528 811.724634 437.700138 829.459578 444.566747 849.36585 448 871.444045 448 903.29456 448 930.439475 440.957429 952.87961 426.872077 975.319744 412.786724 991.968627 389.370177 1002.826752 356.621733L934.963782 356.621733C932.430221 365.072945 925.55351 373.083869 914.33344 380.654746 903.113376 388.225622 889.721882 392.011004 874.158566 392.011004 852.442304 392.011004 835.793421 386.553012 824.211418 375.636864 812.629414 364.720716 806.295597 347.114289 805.209786 322.817057ZM0 576 1024 576 1024 640 0 640 0 576ZM0 768 1024 768 1024 832 0 832 0 768ZM0 960 768 960 768 1024 0 1024 0 960Z" fill="#666666" p-id="15154"></path></svg>
|
||||
<?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="1693218467455" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15153" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M116.181404 133.722146 116.181404 441.133425 201.417293 441.133425 201.417293 133.722146 317.598697 133.722146 317.598697 64 0 64 0 133.722146 116.181404 133.722146ZM412.356282 125.799174 412.356282 64 335.263948 64 335.263948 125.799174 412.356282 125.799174ZM335.263948 168.055021 335.263948 441.133425 412.356282 441.133425 412.356282 168.055021 335.263948 168.055021ZM550.003263 168.055021 550.003263 86.184319 472.91093 86.184319 472.91093 168.055021 426.221206 168.055021 426.221206 218.233837 472.91093 218.233837 472.91093 379.33425C472.91093 393.067469 475.263489 404.159517 479.968678 412.610729 484.673868 421.06194 491.098164 427.576318 499.241762 432.154058 507.385359 436.731797 516.795596 439.812922 527.472757 441.397524 538.149917 442.982126 549.4603 443.774415 561.404242 443.774415 569.004932 443.774415 576.786475 443.598351 584.749103 443.246218 592.711731 442.894084 599.950376 442.189827 606.465253 441.133425L606.465253 383.031637C602.845877 383.735905 599.045588 384.264097 595.064275 384.616231 591.082961 384.968365 586.92074 385.144429 582.577488 385.144429 569.547733 385.144429 560.86136 383.031658 556.518108 378.806052 552.174856 374.580447 550.003263 366.129362 550.003263 353.452545L550.003263 218.233837 606.465253 218.233837 606.465253 168.055021 550.003263 168.055021ZM624.673409 64 624.673409 441.133425 701.765741 441.133425 701.765741 64 624.673409 64ZM930.620557 275.279229 805.209786 275.279229C805.571725 269.997222 806.748006 264.011037 808.738662 257.320495 810.729318 250.629953 814.167674 244.291639 819.05383 238.305364 823.939994 232.31909 830.454771 227.301258 838.598368 223.25172 846.741965 219.20218 856.966547 217.177441 869.272429 217.177441 888.09319 217.177441 902.118061 222.107241 911.347469 231.966988 920.576883 241.826734 927.001178 256.264004 930.620557 275.279229L930.620557 275.279229ZM805.209786 322.817057 1007.71289 322.817057C1009.16064 301.689028 1007.350976 281.441637 1002.283853 262.074278 997.216723 242.706918 988.982765 225.45262 977.581728 210.310867 966.180691 195.169113 951.612922 183.10871 933.877978 174.129299 916.143034 165.149886 895.33193 160.660248 871.444045 160.660248 850.089722 160.660248 830.635866 164.357597 813.081888 171.752407 795.527917 179.147217 780.417248 189.270913 767.749427 202.123796 755.081613 214.97668 745.30944 230.206239 738.432627 247.81293 731.555808 265.41962 728.117453 284.434561 728.117453 304.858322 728.117453 325.986351 731.465325 345.35342 738.161171 362.96011 744.857018 380.566801 754.357741 395.708327 766.663622 408.385144 778.969498 421.061962 793.98969 430.833528 811.724634 437.700138 829.459578 444.566747 849.36585 448 871.444045 448 903.29456 448 930.439475 440.957429 952.87961 426.872077 975.319744 412.786724 991.968627 389.370177 1002.826752 356.621733L934.963782 356.621733C932.430221 365.072945 925.55351 373.083869 914.33344 380.654746 903.113376 388.225622 889.721882 392.011004 874.158566 392.011004 852.442304 392.011004 835.793421 386.553012 824.211418 375.636864 812.629414 364.720716 806.295597 347.114289 805.209786 322.817057ZM0 576 1024 576 1024 640 0 640 0 576ZM0 768 1024 768 1024 832 0 832 0 768ZM0 960 768 960 768 1024 0 1024 0 960Z" p-id="15154"></path></svg>
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
12
core/core-frontend/src/assets/svg/icon_warning_colorful.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1052_111876)">
|
||||
<path d="M8.00033 15.3332C12.0504 15.3332 15.3337 12.0499 15.3337 7.99984C15.3337 3.94975 12.0504 0.666504 8.00033 0.666504C3.95024 0.666504 0.666992 3.94975 0.666992 7.99984C0.666992 12.0499 3.95024 15.3332 8.00033 15.3332Z" fill="#FF8800"/>
|
||||
<path d="M7.66634 4.6665C7.48225 4.6665 7.33301 4.81574 7.33301 4.99984V8.99984C7.33301 9.18393 7.48225 9.33317 7.66634 9.33317H8.33301C8.5171 9.33317 8.66634 9.18393 8.66634 8.99984V4.99984C8.66634 4.81574 8.5171 4.6665 8.33301 4.6665H7.66634Z" fill="white"/>
|
||||
<path d="M7.66634 9.99984C7.48225 9.99984 7.33301 10.1491 7.33301 10.3332V10.9998C7.33301 11.1839 7.48225 11.3332 7.66634 11.3332H8.33301C8.5171 11.3332 8.66634 11.1839 8.66634 10.9998V10.3332C8.66634 10.1491 8.5171 9.99984 8.33301 9.99984H7.66634Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1052_111876">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1022 B |
@ -63,33 +63,31 @@ const checkDialog = () => {
|
||||
}
|
||||
|
||||
const handleMouseWheel = e => {
|
||||
if (editMode.value === 'preview' || checkDialog()) {
|
||||
if (
|
||||
editMode.value === 'preview' ||
|
||||
checkDialog() ||
|
||||
(Math.abs(e.deltaX) !== 0 && Math.abs(e.deltaY) !== 0)
|
||||
) {
|
||||
return
|
||||
}
|
||||
let dvMain = document.getElementById('dv-main-center')
|
||||
let dvMainLeftSlide = document.getElementById('dv-main-left-sidebar')
|
||||
let areaLeftWidth = dvMainLeftSlide.clientWidth
|
||||
let areaRight = dvMain.clientWidth + areaLeftWidth
|
||||
if (areaLeftWidth < e.clientX && e.clientX < areaRight) {
|
||||
const delta = e.wheelDelta ? e.wheelDelta : -e.detail
|
||||
if ((lastWheelNum === 240 && delta === 240) || delta > 240) {
|
||||
//放大
|
||||
scaleIncrease(3)
|
||||
} else if ((lastWheelNum === -240 && delta === -240) || delta < -240) {
|
||||
// 缩小
|
||||
if (e.ctrlKey) {
|
||||
if (e.deltaY > 0) {
|
||||
//向内 缩小
|
||||
scaleDecrease(3)
|
||||
}
|
||||
|
||||
if (delta >= 240 || delta <= -240) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
lastWheelNum = delta
|
||||
if (e.deltaY < 0) {
|
||||
//向外 放大
|
||||
scaleIncrease(3)
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('mousewheel', handleMouseWheel, { passive: false })
|
||||
window.addEventListener('wheel', handleMouseWheel, { passive: false })
|
||||
setTimeout(() => {
|
||||
scale.value = canvasStyleData.value.scale
|
||||
nextTick(() => {
|
||||
@ -99,7 +97,7 @@ onMounted(() => {
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('mousewheel', handleMouseWheel)
|
||||
window.removeEventListener('wheel', handleMouseWheel)
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
|
@ -216,11 +216,10 @@ watch(
|
||||
)
|
||||
|
||||
watch(
|
||||
() => areaData.value.components,
|
||||
() => {
|
||||
() => areaData.value.components.length,
|
||||
(val, oldVal) => {
|
||||
groupAreaClickChange()
|
||||
},
|
||||
{ deep: true }
|
||||
}
|
||||
)
|
||||
|
||||
const initWatermark = (waterDomId = 'editor-canvas-main') => {
|
||||
@ -1062,8 +1061,8 @@ const clearInfoBox = e => {
|
||||
const cellInit = () => {
|
||||
// 此处向下取整 保留1位小数,why: 矩阵模式计算 x,y时 会使用 style.left/cellWidth style.top/cellWidth
|
||||
// 当初始状态细微的差距(主要是减少)都会导致 x,y 减少一个矩阵大小造成偏移,
|
||||
cellWidth.value = Math.floor((baseWidth.value + baseMarginLeft.value) * 10) / 10
|
||||
cellHeight.value = Math.floor((baseHeight.value + baseMarginTop.value) * 10) / 10
|
||||
cellWidth.value = Math.floor((baseWidth.value + baseMarginLeft.value) * 1000) / 1000
|
||||
cellHeight.value = Math.floor((baseHeight.value + baseMarginTop.value) * 1000) / 1000
|
||||
}
|
||||
|
||||
const canvasSizeInit = () => {
|
||||
@ -1359,9 +1358,9 @@ const contextMenuShow = computed(() => {
|
||||
const markLineShow = computed(() => isMainCanvas(canvasId.value))
|
||||
|
||||
// 点击事件导致选择区域变更
|
||||
const groupAreaClickChange = () => {
|
||||
const groupAreaClickChange = async () => {
|
||||
let groupAreaCom
|
||||
const groupAreaHis = componentData.value.filter(ele => ele.id === 100000001)
|
||||
const groupAreaHis = dvMainStore.componentData.filter(ele => ele.component === 'GroupArea')
|
||||
if (groupAreaHis && groupAreaHis.length > 0) {
|
||||
groupAreaCom = groupAreaHis[0]
|
||||
}
|
||||
@ -1369,7 +1368,8 @@ const groupAreaClickChange = () => {
|
||||
if (areaData.value.components.length > 1) {
|
||||
// 重新计算边界
|
||||
composeStore.calcComposeArea()
|
||||
if (!groupAreaCom) {
|
||||
const hist2 = dvMainStore.componentData.filter(ele => ele.component === 'GroupArea')
|
||||
if (groupAreaHis.length === 0) {
|
||||
// 如果不存在 新建视括组件
|
||||
groupAreaCom = findNewComponent('GroupArea', 'GroupArea')
|
||||
dvMainStore.addComponent({ component: groupAreaCom, index: undefined })
|
||||
@ -1379,7 +1379,9 @@ const groupAreaClickChange = () => {
|
||||
groupAreaCom.style.width = areaData.value.style.width
|
||||
groupAreaCom.style.height = areaData.value.style.height
|
||||
} else if (groupAreaCom) {
|
||||
dvMainStore.deleteComponentById(100000001)
|
||||
groupAreaHis.forEach(ele => {
|
||||
dvMainStore.deleteComponentById(ele.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,7 +231,8 @@
|
||||
>
|
||||
<span class="custom-option">
|
||||
<Icon
|
||||
:icon-class="item.type"
|
||||
:name="item.type"
|
||||
class-name="view-type-icon"
|
||||
style="width: 14px; height: 14px"
|
||||
/>
|
||||
<span style="float: left; margin-left: 4px; font-size: 14px">{{
|
||||
@ -245,7 +246,7 @@
|
||||
<el-select
|
||||
v-model="targetViewInfo.targetFieldId"
|
||||
:placeholder="'请选择字段'"
|
||||
:disabled="!targetViewInfo.sourceFieldActiveId"
|
||||
:disabled="fieldIdDisabledCheck(targetViewInfo)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
@ -405,7 +406,7 @@ import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapsho
|
||||
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
|
||||
import { filterEmptyFolderTree } from '@/utils/canvasUtils'
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { dvInfo, canvasViewInfo } = storeToRefs(dvMainStore)
|
||||
const { dvInfo, canvasViewInfo, componentData } = storeToRefs(dvMainStore)
|
||||
const linkJumpInfoTree = ref(null)
|
||||
const { t } = useI18n()
|
||||
const dialogShow = ref(false)
|
||||
@ -643,12 +644,28 @@ const codeMirrorContentSet = content => {
|
||||
const getPanelViewList = dvId => {
|
||||
viewTableDetailList(dvId).then(rsp => {
|
||||
state.viewIdFieldArrayMap = {}
|
||||
state.currentLinkPanelViewArray = rsp.data
|
||||
state.currentLinkPanelViewArray = rsp.data.visualizationViewTables
|
||||
if (state.currentLinkPanelViewArray) {
|
||||
state.currentLinkPanelViewArray.forEach(view => {
|
||||
state.viewIdFieldArrayMap[view.id] = view.tableFields
|
||||
})
|
||||
}
|
||||
// 增加过滤组件匹配
|
||||
JSON.parse(rsp.data.bashComponentData).forEach(componentItem => {
|
||||
if (componentItem.component === 'VQuery') {
|
||||
componentItem.propValue.forEach(filterItem => {
|
||||
state.currentLinkPanelViewArray.push({
|
||||
id: filterItem.id,
|
||||
type: 'filter',
|
||||
name: filterItem.name,
|
||||
title: filterItem.name
|
||||
})
|
||||
state.viewIdFieldArrayMap[filterItem.id] = [
|
||||
{ id: '1000001', name: t('visualization.filter_no_select') }
|
||||
]
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const dvNodeClick = data => {
|
||||
@ -667,8 +684,26 @@ const addLinkJumpField = () => {
|
||||
const deleteLinkJumpField = index => {
|
||||
state.linkJumpInfo.targetViewInfoList.splice(index, 1)
|
||||
}
|
||||
|
||||
const fieldIdDisabledCheck = targetViewInfo => {
|
||||
return (
|
||||
(state.viewIdFieldArrayMap[targetViewInfo.targetViewId] &&
|
||||
state.viewIdFieldArrayMap[targetViewInfo.targetViewId].length === 1 &&
|
||||
state.viewIdFieldArrayMap[targetViewInfo.targetViewId][0].id === '1000001') ||
|
||||
!targetViewInfo.sourceFieldActiveId
|
||||
)
|
||||
}
|
||||
|
||||
const viewInfoOnChange = targetViewInfo => {
|
||||
targetViewInfo.targetFieldId = null
|
||||
if (
|
||||
state.viewIdFieldArrayMap[targetViewInfo.targetViewId] &&
|
||||
state.viewIdFieldArrayMap[targetViewInfo.targetViewId].length === 1 &&
|
||||
state.viewIdFieldArrayMap[targetViewInfo.targetViewId][0].id === '1000001'
|
||||
) {
|
||||
targetViewInfo.targetFieldId = '1000001'
|
||||
} else {
|
||||
targetViewInfo.targetFieldId = null
|
||||
}
|
||||
}
|
||||
const sourceFieldCheckedChange = data => {
|
||||
nextTick(() => {
|
||||
|
@ -19,10 +19,13 @@
|
||||
:title="t('chart.text_color')"
|
||||
v-model="styleForm[styleColorKey.value]"
|
||||
class="color-picker-style"
|
||||
:prefix-icon="expandIcon(styleColorKey.icon)"
|
||||
:triggerWidth="styleColorKey.width"
|
||||
is-custom
|
||||
:predefine="state.predefineColors"
|
||||
@change="changeStyle"
|
||||
/>
|
||||
>
|
||||
</el-color-picker>
|
||||
</el-form-item>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
@ -41,12 +44,17 @@
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-select
|
||||
style="width: 50px"
|
||||
:style="{ width: styleOptionMountedKey.width }"
|
||||
:effect="themes"
|
||||
v-model="styleMounted[styleOptionMountedKey.value]"
|
||||
size="small"
|
||||
@change="sizeChange(styleOptionMountedKey.value)"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon :class="{ 'dark-icon': themes === 'dark' }">
|
||||
<Icon :name="styleOptionMountedKey.icon" />
|
||||
</el-icon>
|
||||
</template>
|
||||
<el-option
|
||||
class="custom-style-option"
|
||||
v-for="option in styleOptionMountedKey.customOption"
|
||||
@ -72,10 +80,14 @@
|
||||
:style="{ width: styleOptionKey.width }"
|
||||
:effect="themes"
|
||||
v-model="styleForm[styleOptionKey.value]"
|
||||
placeholder="透明度"
|
||||
size="small"
|
||||
@change="changeStyle"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon>
|
||||
<Icon :name="styleOptionKey.icon" />
|
||||
</el-icon>
|
||||
</template>
|
||||
<el-option
|
||||
class="custom-style-option"
|
||||
v-for="option in styleOptionKey.customOption"
|
||||
@ -118,48 +130,50 @@
|
||||
</el-tooltip>
|
||||
<template v-if="styleForm.textAlign">
|
||||
<div class="m-divider" :class="'custom-divider-' + themes"></div>
|
||||
<el-tooltip effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
{{ t('chart.text_pos_left') }}
|
||||
</template>
|
||||
<div
|
||||
class="icon-btn"
|
||||
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'left' }"
|
||||
@click="setPosition('textAlign', 'left')"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_left-alignment_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
{{ t('chart.text_pos_center') }}
|
||||
</template>
|
||||
<div
|
||||
class="icon-btn"
|
||||
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'center' }"
|
||||
@click="setPosition('textAlign', 'center')"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_center-alignment_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
{{ t('chart.text_pos_right') }}
|
||||
</template>
|
||||
<div
|
||||
class="icon-btn"
|
||||
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'right' }"
|
||||
@click="setPosition('textAlign', 'right')"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_right-alignment_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div style="display: flex">
|
||||
<el-tooltip effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
{{ t('chart.text_pos_left') }}
|
||||
</template>
|
||||
<div
|
||||
class="icon-btn"
|
||||
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'left' }"
|
||||
@click="setPosition('textAlign', 'left')"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_left-alignment_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
{{ t('chart.text_pos_center') }}
|
||||
</template>
|
||||
<div
|
||||
class="icon-btn"
|
||||
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'center' }"
|
||||
@click="setPosition('textAlign', 'center')"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_center-alignment_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
{{ t('chart.text_pos_right') }}
|
||||
</template>
|
||||
<div
|
||||
class="icon-btn"
|
||||
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'right' }"
|
||||
@click="setPosition('textAlign', 'right')"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_right-alignment_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="styleForm.headHorizontalPosition">
|
||||
<div class="m-divider"></div>
|
||||
@ -220,8 +234,8 @@
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, toRefs, watch } from 'vue'
|
||||
<script lang="tsx" setup>
|
||||
import { computed, h, reactive, ref, toRefs, watch } from 'vue'
|
||||
import { COLOR_PANEL } from '@/views/chart/components/editor/util/chart'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
@ -243,7 +257,9 @@ const props = withDefaults(
|
||||
themes: 'dark'
|
||||
}
|
||||
)
|
||||
|
||||
const expandIcon = (name: string) => {
|
||||
return h(Icon, { className: '', name })
|
||||
}
|
||||
const { themes, element } = toRefs(props)
|
||||
const emits = defineEmits(['onTextChange'])
|
||||
const styleMounted = ref({
|
||||
@ -277,11 +293,21 @@ const state = reactive({
|
||||
})
|
||||
|
||||
const styleColorKeyArray = [
|
||||
{ value: 'color', label: '颜色' },
|
||||
{ value: 'borderColor', label: '边框颜色' },
|
||||
{ value: 'headFontColor', label: '头部字体颜色' },
|
||||
{ value: 'headFontActiveColor', label: '激活字体颜色' },
|
||||
{ value: 'backgroundColor', label: '背景色' }
|
||||
{ value: 'color', label: '颜色', width: 90, icon: 'dv-style-color' },
|
||||
{ value: 'borderColor', label: '边框颜色', width: 90, icon: 'dv-style-borderColor' },
|
||||
{
|
||||
value: 'headFontColor',
|
||||
label: '头部字体颜色',
|
||||
width: 90,
|
||||
icon: 'dv-style-headFontColor'
|
||||
},
|
||||
{
|
||||
value: 'headFontActiveColor',
|
||||
label: '激活字体颜色',
|
||||
width: 90,
|
||||
icon: 'dv-style-headFontActiveColor'
|
||||
},
|
||||
{ value: 'backgroundColor', label: '背景色', width: 90, icon: 'dv-style-backgroundColor' }
|
||||
]
|
||||
|
||||
const fontSizeList = computed(() => {
|
||||
@ -325,16 +351,52 @@ const borderStyleList = [
|
||||
|
||||
//大小随画布缩放动态变化
|
||||
const styleOptionMountedKeyArray = [
|
||||
{ value: 'fontSize', label: '字体大小', customOption: fontSizeList.value },
|
||||
{ value: 'activeFontSize', label: '激活字体大小', customOption: fontSizeList.value }
|
||||
{
|
||||
value: 'fontSize',
|
||||
label: '字体大小',
|
||||
customOption: fontSizeList.value,
|
||||
width: '90px',
|
||||
icon: 'dv-style-fontSize'
|
||||
},
|
||||
{
|
||||
value: 'activeFontSize',
|
||||
label: '激活字体大小',
|
||||
customOption: fontSizeList.value,
|
||||
width: '90px',
|
||||
icon: 'dv-style-activeFont'
|
||||
}
|
||||
]
|
||||
|
||||
//大小不变
|
||||
const styleOptionKeyArray = [
|
||||
{ value: 'opacity', label: '透明度', customOption: opacitySizeList, width: '50px' },
|
||||
{ value: 'borderWidth', label: '边框宽度', customOption: borderWidthList.value, width: '50px' },
|
||||
{ value: 'borderRadius', label: '圆角', customOption: borderRadiusList.value, width: '50px' },
|
||||
{ value: 'borderStyle', label: '边框样式', customOption: borderStyleList, width: '60px' }
|
||||
{
|
||||
value: 'opacity',
|
||||
label: '透明度',
|
||||
customOption: opacitySizeList,
|
||||
width: '90px',
|
||||
icon: 'dv-style-opacity'
|
||||
},
|
||||
{
|
||||
value: 'borderWidth',
|
||||
label: '边框宽度',
|
||||
customOption: borderWidthList.value,
|
||||
width: '90px',
|
||||
icon: 'dv-style-borderSize'
|
||||
},
|
||||
{
|
||||
value: 'borderRadius',
|
||||
label: '圆角',
|
||||
customOption: borderRadiusList.value,
|
||||
width: '90px',
|
||||
icon: 'dv-style-borderRadius'
|
||||
},
|
||||
{
|
||||
value: 'borderStyle',
|
||||
label: '边框样式',
|
||||
customOption: borderStyleList,
|
||||
width: '90px',
|
||||
icon: 'dv-style-borderStyle'
|
||||
}
|
||||
]
|
||||
|
||||
const styleInit = () => {
|
||||
@ -514,4 +576,8 @@ watch(
|
||||
.custom-row-inner {
|
||||
margin: 8px 0px 24px;
|
||||
}
|
||||
|
||||
.dark-icon {
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
|
@ -264,16 +264,18 @@ const componentMoveIn = component => {
|
||||
dvMainStore.setCurComponent({ component: null, index: null })
|
||||
component.canvasId = element.value.id + '--' + tabItem.name
|
||||
const refInstance = currentInstance.refs['tabCanvas_' + index][0]
|
||||
const matrixBase = refInstance.getBaseMatrixSize() //矩阵基础大小
|
||||
canvasChangeAdaptor(component, matrixBase)
|
||||
tabItem.componentData.push(component)
|
||||
nextTick(() => {
|
||||
component.x = 1
|
||||
component.y = 1
|
||||
component.style.left = 0
|
||||
component.style.top = 0
|
||||
refInstance.addItemBox(component) //在适当的时候初始化布局组件
|
||||
})
|
||||
if (refInstance) {
|
||||
const matrixBase = refInstance.getBaseMatrixSize() //矩阵基础大小
|
||||
canvasChangeAdaptor(component, matrixBase)
|
||||
tabItem.componentData.push(component)
|
||||
nextTick(() => {
|
||||
component.x = 1
|
||||
component.y = 1
|
||||
component.style.left = 0
|
||||
component.style.top = 0
|
||||
refInstance.addItemBox(component) //在适当的时候初始化布局组件
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { deepCopy } from '@/utils/utils'
|
||||
import { cloneDeep, defaultsDeep, defaultTo } from 'lodash-es'
|
||||
import {
|
||||
BASE_VIEW_CONFIG,
|
||||
CHART_CONT_FAMILY_MAP,
|
||||
CHART_FONT_FAMILY_MAP,
|
||||
DEFAULT_INDICATOR_NAME_STYLE,
|
||||
DEFAULT_INDICATOR_STYLE
|
||||
} from '@/views/chart/components/editor/util/chart'
|
||||
@ -170,7 +170,7 @@ const formattedResult = computed(() => {
|
||||
|
||||
const emit = defineEmits(['onChartClick', 'onDrillFilters', 'onJumpClick'])
|
||||
|
||||
const contentStyle = ref({
|
||||
const contentStyle = ref<CSSProperties>({
|
||||
display: 'flex',
|
||||
'flex-direction': 'column',
|
||||
'align-items': 'center',
|
||||
@ -182,7 +182,7 @@ 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],
|
||||
CHART_FONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.fontFamily],
|
||||
DEFAULT_INDICATOR_STYLE.fontFamily
|
||||
),
|
||||
'font-weight': DEFAULT_INDICATOR_STYLE.isBolder ? 'bold' : 'normal',
|
||||
@ -196,7 +196,7 @@ 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],
|
||||
CHART_FONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.suffixFontFamily],
|
||||
DEFAULT_INDICATOR_STYLE.suffixFontFamily
|
||||
),
|
||||
'font-weight': DEFAULT_INDICATOR_STYLE.suffixIsBolder ? 'bold' : 'normal',
|
||||
@ -212,11 +212,15 @@ const suffixContent = ref('')
|
||||
|
||||
const indicatorNameShow = ref(false)
|
||||
|
||||
const indicatorNameWrapperStyle = reactive<CSSProperties>({
|
||||
'margin-top': DEFAULT_INDICATOR_NAME_STYLE.nameValueSpacing + 'px'
|
||||
})
|
||||
|
||||
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],
|
||||
CHART_FONT_FAMILY_MAP[DEFAULT_INDICATOR_NAME_STYLE.fontFamily],
|
||||
DEFAULT_INDICATOR_NAME_STYLE.fontFamily
|
||||
),
|
||||
'font-weight': DEFAULT_INDICATOR_NAME_STYLE.isBolder ? 'bold' : 'normal',
|
||||
@ -237,16 +241,16 @@ const renderChart = async view => {
|
||||
const chart = deepCopy({
|
||||
...defaultsDeep(view, TEMP_DEFAULT_CHART),
|
||||
data: chartData.value
|
||||
})
|
||||
}) as ChartObj
|
||||
|
||||
recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value)
|
||||
recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value)
|
||||
|
||||
if (chart.customAttr) {
|
||||
const customAttr = chart.customAttr
|
||||
const { indicator, indicatorName, basicStyle } = chart.customAttr
|
||||
|
||||
if (customAttr.indicator) {
|
||||
switch (customAttr.indicator.hPosition) {
|
||||
if (indicator) {
|
||||
switch (indicator.hPosition) {
|
||||
case 'left':
|
||||
contentStyle.value['align-items'] = 'flex-start'
|
||||
break
|
||||
@ -256,7 +260,7 @@ const renderChart = async view => {
|
||||
default:
|
||||
contentStyle.value['align-items'] = 'center'
|
||||
}
|
||||
switch (customAttr.indicator.vPosition) {
|
||||
switch (indicator.vPosition) {
|
||||
case 'top':
|
||||
contentStyle.value['justify-content'] = 'flex-start'
|
||||
break
|
||||
@ -267,73 +271,68 @@ const renderChart = async view => {
|
||||
contentStyle.value['justify-content'] = 'center'
|
||||
}
|
||||
|
||||
indicatorColor.value = customAttr.indicator.color
|
||||
let suffixColor = customAttr.indicator.suffixColor
|
||||
indicatorColor.value = indicator.color
|
||||
let suffixColor = indicator.suffixColor
|
||||
|
||||
if (
|
||||
customAttr.basicStyle &&
|
||||
customAttr.basicStyle.alpha !== undefined &&
|
||||
!batchOptStatus.value
|
||||
) {
|
||||
indicatorColor.value = hexColorToRGBA(
|
||||
customAttr.basicStyle.colors[0],
|
||||
customAttr.basicStyle.alpha
|
||||
)
|
||||
suffixColor = hexColorToRGBA(customAttr.basicStyle.colors[1], customAttr.basicStyle.alpha)
|
||||
if (basicStyle?.alpha !== undefined && !batchOptStatus.value) {
|
||||
indicatorColor.value = hexColorToRGBA(basicStyle.colors[0], basicStyle.alpha)
|
||||
suffixColor = hexColorToRGBA(basicStyle.colors[1], basicStyle.alpha)
|
||||
}
|
||||
|
||||
indicatorClass.value = {
|
||||
color: thresholdColor.value,
|
||||
'font-size': customAttr.indicator.fontSize + 'px',
|
||||
'font-size': indicator.fontSize + 'px',
|
||||
'font-family': defaultTo(
|
||||
CHART_CONT_FAMILY_MAP[customAttr.indicator.fontFamily],
|
||||
CHART_FONT_FAMILY_MAP[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-weight': indicator.isBolder ? 'bold' : 'normal',
|
||||
'font-style': indicator.isItalic ? 'italic' : 'normal',
|
||||
'letter-spacing': indicator.letterSpace + 'px',
|
||||
'text-shadow': indicator.fontShadow ? '2px 2px 4px' : 'none',
|
||||
'font-synthesis': 'weight style'
|
||||
}
|
||||
|
||||
indicatorSuffixClass.value = {
|
||||
color: suffixColor,
|
||||
'font-size': customAttr.indicator.suffixFontSize + 'px',
|
||||
'font-size': indicator.suffixFontSize + 'px',
|
||||
'font-family': defaultTo(
|
||||
CHART_CONT_FAMILY_MAP[customAttr.indicator.suffixFontFamily],
|
||||
CHART_FONT_FAMILY_MAP[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-weight': indicator.suffixIsBolder ? 'bold' : 'normal',
|
||||
'font-style': indicator.suffixIsItalic ? 'italic' : 'normal',
|
||||
'letter-spacing': indicator.suffixLetterSpace + 'px',
|
||||
'text-shadow': indicator.suffixFontShadow ? '2px 2px 4px' : 'none',
|
||||
'font-synthesis': 'weight style'
|
||||
}
|
||||
|
||||
showSuffix.value = customAttr.indicator.suffixEnable
|
||||
suffixContent.value = defaultTo(customAttr.indicator.suffix, '')
|
||||
showSuffix.value = indicator.suffixEnable
|
||||
suffixContent.value = defaultTo(indicator.suffix, '')
|
||||
}
|
||||
if (customAttr.indicatorName && customAttr.indicatorName.show) {
|
||||
let nameColor = customAttr.indicatorName.color
|
||||
if (indicatorName?.show) {
|
||||
let nameColor = indicatorName.color
|
||||
|
||||
if (customAttr.basicStyle && customAttr.basicStyle.alpha !== undefined) {
|
||||
nameColor = hexColorToRGBA(customAttr.basicStyle.colors[2], customAttr.basicStyle.alpha)
|
||||
if (basicStyle?.alpha !== undefined) {
|
||||
nameColor = hexColorToRGBA(basicStyle.colors[2], basicStyle.alpha)
|
||||
}
|
||||
|
||||
indicatorNameShow.value = true
|
||||
indicatorNameClass.value = {
|
||||
color: nameColor,
|
||||
'font-size': customAttr.indicatorName.fontSize + 'px',
|
||||
'font-size': indicatorName.fontSize + 'px',
|
||||
'font-family': defaultTo(
|
||||
CHART_CONT_FAMILY_MAP[customAttr.indicatorName.fontFamily],
|
||||
CHART_FONT_FAMILY_MAP[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-weight': indicatorName.isBolder ? 'bold' : 'normal',
|
||||
'font-style': indicatorName.isItalic ? 'italic' : 'normal',
|
||||
'letter-spacing': indicatorName.letterSpace + 'px',
|
||||
'text-shadow': indicatorName.fontShadow ? '2px 2px 4px' : 'none',
|
||||
'font-synthesis': 'weight style'
|
||||
}
|
||||
indicatorNameWrapperStyle['margin-top'] =
|
||||
(indicatorName.nameValueSpacing ?? DEFAULT_INDICATOR_NAME_STYLE.nameValueSpacing) + 'px'
|
||||
} else {
|
||||
indicatorNameShow.value = false
|
||||
}
|
||||
@ -363,9 +362,6 @@ const calcData = (view, callback) => {
|
||||
callback?.()
|
||||
})
|
||||
} else {
|
||||
if (view.type === 'map') {
|
||||
renderChart(view)
|
||||
}
|
||||
callback?.()
|
||||
}
|
||||
}
|
||||
@ -382,7 +378,7 @@ defineExpose({
|
||||
<span :style="indicatorClass">{{ formattedResult }}</span>
|
||||
<span :style="indicatorSuffixClass" v-if="showSuffix">{{ suffixContent }}</span>
|
||||
</div>
|
||||
<div v-if="indicatorNameShow">
|
||||
<div :style="indicatorNameWrapperStyle" v-if="indicatorNameShow">
|
||||
<span :style="indicatorNameClass">{{ resultName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -10,9 +10,10 @@
|
||||
<chart-error v-if="isError" :err-msg="errMsg" />
|
||||
<Editor
|
||||
v-if="editShow && !isError"
|
||||
:id="tinymceId"
|
||||
v-model="myValue"
|
||||
class="custom-text-content"
|
||||
:style="wrapperStyle"
|
||||
:id="tinymceId"
|
||||
:init="init"
|
||||
:disabled="!canEdit || disabled"
|
||||
/>
|
||||
@ -46,6 +47,7 @@ import 'tinymce/plugins/contextmenu' // contextmenu
|
||||
import 'tinymce/plugins/directionality'
|
||||
import 'tinymce/plugins/nonbreaking'
|
||||
import 'tinymce/plugins/pagebreak'
|
||||
import './plugins' //自定义插件
|
||||
import { computed, nextTick, reactive, ref, toRefs, watch, onMounted, PropType } from 'vue'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import eventBus from '@/utils/eventBus'
|
||||
@ -119,11 +121,11 @@ const init = ref({
|
||||
skin_url: formatDataEaseBi('./tinymce-dataease-private/skins/ui/oxide'), // 皮肤
|
||||
content_css: formatDataEaseBi('./tinymce-dataease-private/skins/content/default/content.css'),
|
||||
plugins:
|
||||
'advlist autolink link image lists charmap media wordcount table contextmenu directionality pagebreak', // 插件
|
||||
'vertical-content advlist autolink link image lists charmap media wordcount table contextmenu directionality pagebreak', // 插件
|
||||
// 工具栏
|
||||
toolbar:
|
||||
'undo redo |fontselect fontsizeselect |forecolor backcolor bold italic |underline strikethrough link| formatselect |' +
|
||||
'alignleft aligncenter alignright | bullist numlist |' +
|
||||
'top-align center-align bottom-align | alignleft aligncenter alignright | bullist numlist |' +
|
||||
' blockquote subscript superscript removeformat | table image | fullscreen ' +
|
||||
'| bdmap indent2em lineheight formatpainter axupimgs',
|
||||
toolbar_location: '/',
|
||||
@ -134,7 +136,9 @@ const init = ref({
|
||||
placeholder: '',
|
||||
outer_placeholder: '双击输入文字',
|
||||
inline: true, // 开启内联模式
|
||||
branding: false
|
||||
branding: false,
|
||||
icons: 'vertical-content',
|
||||
vertical_align: element.value.propValue.verticalAlign
|
||||
})
|
||||
|
||||
const editStatus = computed(() => {
|
||||
@ -169,6 +173,36 @@ watch(
|
||||
}
|
||||
}
|
||||
)
|
||||
const ALIGN_MAP = {
|
||||
'top-align': {
|
||||
display: 'flex',
|
||||
'flex-direction': 'column',
|
||||
'justify-content': 'flex-start'
|
||||
},
|
||||
'center-align': {
|
||||
display: 'flex',
|
||||
'flex-direction': 'column',
|
||||
'justify-content': 'center'
|
||||
},
|
||||
'bottom-align': {
|
||||
display: 'flex',
|
||||
'flex-direction': 'column',
|
||||
'justify-content': 'flex-end'
|
||||
}
|
||||
}
|
||||
const wrapperStyle = computed(() => {
|
||||
const align = element.value.propValue.verticalAlign
|
||||
if (!align) {
|
||||
return {}
|
||||
}
|
||||
return ALIGN_MAP[align]
|
||||
})
|
||||
useEmitt({
|
||||
name: 'vertical-change-' + tinymceId,
|
||||
callback: align => {
|
||||
element.value.propValue.verticalAlign = align
|
||||
}
|
||||
})
|
||||
|
||||
const viewInit = () => {
|
||||
useEmitt({
|
||||
@ -496,6 +530,14 @@ defineExpose({
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.tox {
|
||||
border-radius: 4px !important;
|
||||
border-bottom: 1px solid #ccc !important;
|
||||
z-index: 1000;
|
||||
}
|
||||
.tox-tbtn {
|
||||
height: auto !important;
|
||||
}
|
||||
.tox-collection__item-label {
|
||||
p {
|
||||
color: #1a1a1a !important;
|
||||
|
@ -0,0 +1,11 @@
|
||||
import tinymce from 'tinymce/tinymce'
|
||||
|
||||
const plugins = import.meta.glob(['./*.ts', '!./index.ts'], { eager: true })
|
||||
for (const pluginName in plugins) {
|
||||
const plugin = plugins[pluginName]['default']
|
||||
const exist = tinymce.PluginManager.get(plugin.name)
|
||||
if (exist) {
|
||||
continue
|
||||
}
|
||||
tinymce.PluginManager.add(plugin.name, plugin.plugin)
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
import { type Editor } from 'tinymce'
|
||||
import tinymce from 'tinymce/tinymce'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
const { emitter } = useEmitt()
|
||||
const TOP_ALIGN_BTN =
|
||||
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' +
|
||||
'<path d="M2.5 3C2.22386 3 2 3.22386 2 3.5V4.5C2 4.77614 2.22386 5 2.5 5H21.5C21.7761 5 22 4.77614 22 4.5V3.5C22 3.22386 21.7761 3 21.5 3H2.5Z" fill="currentColor"/>' +
|
||||
'<path d="M6.19133 14.4465L11 9.63788V21.467C11 21.7615 11.2388 22.0003 11.5333 22.0003H12.4667C12.7612 22.0003 13 21.7615 13 21.467V9.61452L17.832 14.4465C18.0403 14.6548 18.378 14.6548 18.5863 14.4465L19.2462 13.7866C19.4545 13.5783 19.4545 13.2406 19.2462 13.0323L12.458 6.2441C12.3362 6.12232 12.1702 6.07174 12.0117 6.09237C11.8531 6.07174 11.6871 6.12232 11.5653 6.2441L4.77712 13.0323C4.56884 13.2406 4.56884 13.5783 4.77712 13.7866L5.43709 14.4465C5.64537 14.6548 5.98305 14.6548 6.19133 14.4465Z" fill="currentColor"/>' +
|
||||
'</svg>'
|
||||
const CENTER_ALIGN_BTN =
|
||||
'<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' +
|
||||
'<path d="M11 6.36207L9.19133 4.5534C8.98305 4.34513 8.64537 4.34513 8.43709 4.55341L7.77712 5.21337C7.56884 5.42165 7.56884 5.75934 7.77712 5.96762L11.5653 9.75584C11.6871 9.87762 11.8531 9.9282 12.0117 9.90757C12.1702 9.9282 12.3362 9.87762 12.458 9.75584L16.2462 5.96762C16.4545 5.75934 16.4545 5.42165 16.2462 5.21337L15.5863 4.55341C15.378 4.34513 15.0403 4.34513 14.832 4.5534L13 6.38542V1.53297C13 1.23841 12.7612 0.999634 12.4667 0.999634H11.5333C11.2388 0.999634 11 1.23841 11 1.53297V6.36207Z" fill="currentColor"/>' +
|
||||
'<path d="M11 17.5499L9.19133 19.3586C8.98305 19.5669 8.64537 19.5669 8.43709 19.3586L7.77712 18.6986C7.56884 18.4903 7.56884 18.1527 7.77712 17.9444L11.5653 14.1562C11.6871 14.0344 11.8531 13.9838 12.0117 14.0044C12.1702 13.9838 12.3362 14.0344 12.458 14.1562L16.2462 17.9444C16.4545 18.1527 16.4545 18.4903 16.2462 18.6986L15.5863 19.3586C15.378 19.5669 15.0403 19.5669 14.832 19.3586L13 17.5266V22.379C13 22.6736 12.7612 22.9124 12.4667 22.9124H11.5333C11.2388 22.9124 11 22.6736 11 22.379V17.5499Z" fill="currentColor"/>' +
|
||||
'<path d="M2.5 10.9999C2.22386 10.9999 2 11.2238 2 11.4999V12.4999C2 12.7761 2.22386 12.9999 2.5 12.9999H21.5C21.7761 12.9999 22 12.7761 22 12.4999V11.4999C22 11.2238 21.7761 10.9999 21.5 10.9999H2.5Z" fill="currentColor"/>' +
|
||||
'</svg>'
|
||||
const BOTTOM_ALIGN_BTN =
|
||||
'<svg t="1713518245725" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17410" width="24" height="24">' +
|
||||
'<path d="M508.842667 42.666667a42.666667 42.666667 0 0 1 42.666666 42.666666V725.333333a42.666667 42.666667 0 0 1-85.333333 0l0-640a42.666667 42.666667 0 0 1 42.666667-42.666666z" fill="#373C43" p-id="17411"></path><path d="M502.314667 707.84l275.541333-266.069333a42.666667 42.666667 0 1 1 59.306667 61.44L531.029333 798.634667a42.538667 42.538667 0 0 1-60.16-0.853334l-291.242666-298.666666a42.666667 42.666667 0 0 1 61.098666-59.605334l261.589334 268.245334z" fill="#373C43" p-id="17412"></path><path d="M935.509333 981.333333m-42.666666 0l-768 0q-42.666667 0-42.666667-42.666666l0 0q0-42.666667 42.666667-42.666667l768 0q42.666667 0 42.666666 42.666667l0 0q0 42.666667-42.666666 42.666666Z" fill="#8D9399" p-id="17413">' +
|
||||
'</path>' +
|
||||
'</svg>'
|
||||
const pack = tinymce.IconManager.has('vertical-content')
|
||||
if (!pack) {
|
||||
tinymce.IconManager.add('vertical-content', {
|
||||
icons: {
|
||||
'top-align': TOP_ALIGN_BTN,
|
||||
'center-align': CENTER_ALIGN_BTN,
|
||||
'bottom-align': BOTTOM_ALIGN_BTN
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'vertical-content',
|
||||
plugin: function (editor: Editor) {
|
||||
const wrapperDom = editor.targetElm
|
||||
const verticalAlign = editor.settings.vertical_align
|
||||
const btnMap = {
|
||||
'top-align': {
|
||||
component: null,
|
||||
tooltip: '置顶'
|
||||
},
|
||||
'center-align': {
|
||||
component: null,
|
||||
tooltip: '居中'
|
||||
},
|
||||
'bottom-align': {
|
||||
component: null,
|
||||
tooltip: '置底'
|
||||
}
|
||||
}
|
||||
for (const key in btnMap) {
|
||||
editor.ui.registry.addToggleButton(key, {
|
||||
icon: key,
|
||||
tooltip: btnMap[key].tooltip,
|
||||
onAction: api => {
|
||||
for (const btnKey in btnMap) {
|
||||
if (btnKey === key) {
|
||||
// 反选清空样式
|
||||
const align = api.isActive() ? '' : key
|
||||
emitter.emit('vertical-change-' + wrapperDom.id, align)
|
||||
btnMap[key].component.setActive(!api.isActive())
|
||||
} else {
|
||||
const active = btnMap[btnKey].component.isActive()
|
||||
if (active) {
|
||||
btnMap[btnKey].component.setActive(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onSetup(a) {
|
||||
if (verticalAlign === key) {
|
||||
a.setActive(true)
|
||||
}
|
||||
return api => (btnMap[key].component = api)
|
||||
}
|
||||
})
|
||||
}
|
||||
return {
|
||||
getMetadata: function () {
|
||||
return {
|
||||
name: 'Vertical align',
|
||||
url: 'https://dataease.io'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,7 +13,10 @@ import {
|
||||
watch,
|
||||
computed,
|
||||
onMounted,
|
||||
CSSProperties
|
||||
onBeforeMount,
|
||||
CSSProperties,
|
||||
shallowRef,
|
||||
provide
|
||||
} from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
@ -156,7 +159,52 @@ const onComponentClick = () => {
|
||||
}
|
||||
|
||||
const { emitter } = useEmitt()
|
||||
const unMountSelect = shallowRef([])
|
||||
onBeforeMount(() => {
|
||||
unMountSelect.value = list.value.map(ele => ele.id)
|
||||
})
|
||||
|
||||
const releaseSelect = id => {
|
||||
unMountSelect.value = unMountSelect.value.filter(ele => ele !== id)
|
||||
}
|
||||
|
||||
const queryDataForId = id => {
|
||||
let requiredName = ''
|
||||
const emitterList = (element.value.propValue || [])
|
||||
.filter(ele => ele.id === id)
|
||||
.reduce((pre, next) => {
|
||||
if (next.required) {
|
||||
if (!next.defaultValueCheck) {
|
||||
requiredName = next.name
|
||||
}
|
||||
|
||||
if (
|
||||
(Array.isArray(next.selectValue) && !next.selectValue.length) ||
|
||||
(next.selectValue !== 0 && !next.selectValue)
|
||||
) {
|
||||
requiredName = next.name
|
||||
}
|
||||
}
|
||||
const keyList = Object.entries(next.checkedFieldsMap)
|
||||
.filter(ele => next.checkedFields.includes(ele[0]))
|
||||
.filter(ele => !!ele[1])
|
||||
.map(ele => ele[0])
|
||||
pre = [...new Set([...keyList, ...pre])]
|
||||
return pre
|
||||
}, [])
|
||||
if (!!requiredName) {
|
||||
ElMessage.error(`【${requiredName}】查询条件是必填项,请设置选项值后,再进行查询!`)
|
||||
return
|
||||
}
|
||||
if (!emitterList.length) return
|
||||
emitterList.forEach(ele => {
|
||||
emitter.emit(`query-data-${ele}`)
|
||||
})
|
||||
}
|
||||
|
||||
provide('unmount-select', unMountSelect)
|
||||
provide('release-unmount-select', releaseSelect)
|
||||
provide('query-data-for-id', queryDataForId)
|
||||
onBeforeUnmount(() => {
|
||||
emitter.off(`addQueryCriteria${element.value.id}`)
|
||||
emitter.off(`editQueryCriteria${element.value.id}`)
|
||||
@ -245,10 +293,20 @@ const delQueryConfig = index => {
|
||||
|
||||
const resetData = () => {
|
||||
;(list.value || []).reduce((pre, next) => {
|
||||
next.conditionValueF = next.defaultConditionValueF
|
||||
next.conditionValueOperatorF = next.defaultConditionValueOperatorF
|
||||
next.conditionValueS = next.defaultConditionValueS
|
||||
next.conditionValueOperatorS = next.defaultConditionValueOperatorS
|
||||
|
||||
if (!next.defaultValueCheck) {
|
||||
next.defaultValue = next.multiple || +next.displayType === 7 ? [] : undefined
|
||||
}
|
||||
next.selectValue = Array.isArray(next.defaultValue) ? [...next.defaultValue] : next.defaultValue
|
||||
if (next.optionValueSource === 1 && next.defaultMapValue?.length) {
|
||||
next.mapValue = Array.isArray(next.defaultMapValue)
|
||||
? [...next.defaultMapValue]
|
||||
: next.defaultMapValue
|
||||
}
|
||||
const keyList = Object.entries(next.checkedFieldsMap)
|
||||
.filter(ele => next.checkedFields.includes(ele[0]))
|
||||
.filter(ele => !!ele[1])
|
||||
@ -261,6 +319,11 @@ const resetData = () => {
|
||||
const clearData = () => {
|
||||
;(list.value || []).reduce((pre, next) => {
|
||||
next.selectValue = next.multiple || +next.displayType === 7 ? [] : undefined
|
||||
if (next.optionValueSource === 1 && next.defaultMapValue?.length) {
|
||||
next.mapValue = next.multiple ? [] : undefined
|
||||
}
|
||||
next.conditionValueF = ''
|
||||
next.conditionValueS = ''
|
||||
const keyList = Object.entries(next.checkedFieldsMap)
|
||||
.filter(ele => next.checkedFields.includes(ele[0]))
|
||||
.filter(ele => !!ele[1])
|
||||
@ -557,7 +620,7 @@ const autoStyle = computed(() => {
|
||||
}
|
||||
.query-button {
|
||||
align-self: flex-end;
|
||||
line-height: 28px;
|
||||
line-height: 40px;
|
||||
margin: auto 0 5px auto;
|
||||
z-index: 0;
|
||||
}
|
||||
|
@ -248,6 +248,9 @@ const handleDatasetChange = () => {
|
||||
const handleFieldChange = () => {
|
||||
if (!curComponent.value.defaultValueCheck) return
|
||||
curComponent.value.defaultValue = curComponent.value.multiple ? [] : undefined
|
||||
if (!curComponent.value.displayId) {
|
||||
curComponent.value.displayId = curComponent.value.field.id
|
||||
}
|
||||
}
|
||||
|
||||
const handleValueSourceChange = () => {
|
||||
@ -545,6 +548,7 @@ const validate = () => {
|
||||
|
||||
const handleBeforeClose = () => {
|
||||
inputCom.value?.mult?.handleClickOutside?.()
|
||||
inputCom.value?.single?.handleClickOutside?.()
|
||||
handleDialogClick()
|
||||
dialogVisible.value = false
|
||||
visiblePopover.value = false
|
||||
@ -553,6 +557,8 @@ const handleBeforeClose = () => {
|
||||
const confirmClick = () => {
|
||||
if (validate()) return
|
||||
inputCom.value?.mult?.handleClickOutside?.()
|
||||
inputCom.value?.single?.handleClickOutside?.()
|
||||
handleDialogClick()
|
||||
visiblePopover.value = false
|
||||
dialogVisible.value = false
|
||||
conditions.value.forEach(ele => {
|
||||
@ -675,6 +681,7 @@ const parameterCompletion = () => {
|
||||
timeType: 'fixed',
|
||||
required: false,
|
||||
defaultMapValue: [],
|
||||
mapValue: [],
|
||||
parametersStart: null,
|
||||
conditionType: 0,
|
||||
conditionValueOperatorF: 'eq',
|
||||
@ -781,7 +788,7 @@ const handleDialogClick = () => {
|
||||
|
||||
const operators = [
|
||||
{
|
||||
label: '精准匹配',
|
||||
label: '精确匹配',
|
||||
value: 'eq'
|
||||
},
|
||||
{
|
||||
@ -1569,7 +1576,6 @@ defineExpose({
|
||||
</el-select>
|
||||
<el-input
|
||||
class="condition-value-input"
|
||||
size="small"
|
||||
v-model="curComponent.defaultConditionValueF"
|
||||
/>
|
||||
<div class="bottom-line"></div>
|
||||
@ -1593,7 +1599,6 @@ defineExpose({
|
||||
</el-select>
|
||||
<el-input
|
||||
class="condition-value-input"
|
||||
size="small"
|
||||
v-model="curComponent.defaultConditionValueS"
|
||||
/>
|
||||
<div class="bottom-line next-line"></div>
|
||||
@ -1654,7 +1659,10 @@ defineExpose({
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="list-item" v-if="+curComponent.displayType === 0">
|
||||
<div
|
||||
class="list-item"
|
||||
v-if="+curComponent.displayType === 0 && curComponent.optionValueSource !== 1"
|
||||
>
|
||||
<div class="label">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
@ -2219,7 +2227,7 @@ defineExpose({
|
||||
.value {
|
||||
width: 321px;
|
||||
.condition-type {
|
||||
margin-top: 8px;
|
||||
margin-top: 3px !important;
|
||||
display: flex;
|
||||
position: relative;
|
||||
.ed-input__wrapper {
|
||||
@ -2271,7 +2279,7 @@ defineExpose({
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
bottom: 3px;
|
||||
width: 220px;
|
||||
z-index: 10;
|
||||
|
||||
|
@ -1,11 +1,23 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, toRefs, PropType, onBeforeMount, shallowRef, watch, nextTick, computed } from 'vue'
|
||||
import {
|
||||
ref,
|
||||
toRefs,
|
||||
PropType,
|
||||
onBeforeMount,
|
||||
shallowRef,
|
||||
watch,
|
||||
nextTick,
|
||||
computed,
|
||||
inject,
|
||||
Ref
|
||||
} from 'vue'
|
||||
import { enumValueObj, type EnumValue, getEnumValue } from '@/api/dataset'
|
||||
import { cloneDeep, debounce } from 'lodash-es'
|
||||
|
||||
interface SelectConfig {
|
||||
selectValue: any
|
||||
defaultMapValue: any
|
||||
mapValue: any
|
||||
defaultValue: any
|
||||
checkedFieldsMap: object
|
||||
displayType: string
|
||||
@ -53,7 +65,9 @@ const selectValue = ref()
|
||||
const loading = ref(false)
|
||||
const multiple = ref(false)
|
||||
const options = shallowRef([])
|
||||
|
||||
const unMountSelect: Ref = inject('unmount-select')
|
||||
const releaseSelect = inject('release-unmount-select', Function, true)
|
||||
const queryDataForId = inject('query-data-for-id', Function, true)
|
||||
const setDefaultMapValue = arr => {
|
||||
const { displayId, field } = config.value
|
||||
if (!displayId || displayId === field?.id) {
|
||||
@ -81,13 +95,16 @@ const handleValueChange = () => {
|
||||
config.value.selectValue = Array.isArray(selectValue.value)
|
||||
? [...selectValue.value]
|
||||
: selectValue.value
|
||||
config.value.defaultMapValue = setDefaultMapValue(
|
||||
config.value.mapValue = setDefaultMapValue(
|
||||
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
config.value.defaultValue = value
|
||||
config.value.mapValue = setDefaultMapValue(
|
||||
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
|
||||
)
|
||||
config.value.defaultMapValue = setDefaultMapValue(
|
||||
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
|
||||
)
|
||||
@ -152,12 +169,29 @@ const handleFieldIdChange = (val: EnumValue) => {
|
||||
selectValue.value = Array.isArray(config.value.defaultValue)
|
||||
? [...config.value.defaultValue]
|
||||
: config.value.defaultValue
|
||||
let shouldReSearch = false
|
||||
if (unMountSelect.value.includes(config.value.id)) {
|
||||
const mapValue = setDefaultMapValue(
|
||||
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
|
||||
)
|
||||
if (mapValue.length !== config.value.defaultMapValue.length) {
|
||||
shouldReSearch = true
|
||||
} else if (!mapValue.every(value => config.value.defaultMapValue.includes(value))) {
|
||||
shouldReSearch = true
|
||||
}
|
||||
releaseSelect(config.value.id)
|
||||
}
|
||||
config.value.mapValue = setDefaultMapValue(
|
||||
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
|
||||
)
|
||||
if (shouldReSearch) {
|
||||
queryDataForId(config.value.id)
|
||||
}
|
||||
} else {
|
||||
selectValue.value = Array.isArray(selectValue.value)
|
||||
? [...selectValue.value]
|
||||
: selectValue.value
|
||||
}
|
||||
setEmptyData()
|
||||
})
|
||||
}
|
||||
|
||||
@ -176,8 +210,8 @@ watch(
|
||||
)
|
||||
|
||||
const setEmptyData = () => {
|
||||
const { showEmpty, displayType } = config.value
|
||||
if (+displayType !== 0) return
|
||||
const { showEmpty, displayType, optionValueSource } = config.value
|
||||
if (+displayType !== 0 || optionValueSource === 1) return
|
||||
const [s] = options.value
|
||||
if (showEmpty) {
|
||||
if (s?.value !== '_empty_$') {
|
||||
@ -268,6 +302,7 @@ watch(
|
||||
watch(
|
||||
[() => config.value.checkedFields, () => config.value.checkedFieldsMap],
|
||||
() => {
|
||||
if (!props.isConfig) return
|
||||
debounceOptions(config.value.optionValueSource)
|
||||
},
|
||||
{
|
||||
@ -350,6 +385,7 @@ const selectStyle = computed(() => {
|
||||
})
|
||||
|
||||
const mult = ref()
|
||||
const single = ref()
|
||||
|
||||
onBeforeMount(() => {
|
||||
init()
|
||||
@ -357,7 +393,8 @@ onBeforeMount(() => {
|
||||
|
||||
defineExpose({
|
||||
displayTypeChange,
|
||||
mult
|
||||
mult,
|
||||
single
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -390,6 +427,7 @@ defineExpose({
|
||||
v-loading="loading"
|
||||
@change="handleValueChange"
|
||||
clearable
|
||||
ref="single"
|
||||
:style="selectStyle"
|
||||
filterable
|
||||
radio
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, onBeforeMount, type PropType } from 'vue'
|
||||
import { toRefs, onBeforeMount, type PropType, inject, type CSSProperties } from 'vue'
|
||||
interface SelectConfig {
|
||||
conditionValueOperatorF: string
|
||||
conditionValueF: string
|
||||
@ -14,7 +14,7 @@ interface SelectConfig {
|
||||
|
||||
const operators = [
|
||||
{
|
||||
label: '精准匹配',
|
||||
label: '精确匹配',
|
||||
value: 'eq'
|
||||
},
|
||||
{
|
||||
@ -57,10 +57,11 @@ const setParams = () => {
|
||||
onBeforeMount(() => {
|
||||
setParams()
|
||||
})
|
||||
const customStyle = inject<{ background: string }>('$custom-style-filter')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-search-select">
|
||||
<div class="text-search-select" :style="{ background: customStyle.background }">
|
||||
<div class="condition-type">
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
@ -143,7 +144,7 @@ onBeforeMount(() => {
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
bottom: 3px;
|
||||
width: 195px;
|
||||
z-index: 10;
|
||||
|
||||
|
@ -15,10 +15,11 @@ const infoFormat = (obj: ComponentInfo) => {
|
||||
name,
|
||||
deType
|
||||
},
|
||||
displayId: '',
|
||||
displayId: id,
|
||||
sortId: '',
|
||||
sort: 'asc',
|
||||
defaultMapValue: [],
|
||||
mapValue: [],
|
||||
conditionType: 0,
|
||||
conditionValueOperatorF: 'eq',
|
||||
conditionValueF: '',
|
||||
|
@ -83,13 +83,15 @@ const getValueByDefaultValueCheckOrFirstLoad = (
|
||||
firstLoad: boolean,
|
||||
multiple: boolean,
|
||||
defaultMapValue: any,
|
||||
optionValueSource: number
|
||||
optionValueSource: number,
|
||||
mapValue: any,
|
||||
displayType: string
|
||||
) => {
|
||||
if (optionValueSource === 1) {
|
||||
if (firstLoad && !selectValue?.length) {
|
||||
if (optionValueSource === 1 && defaultMapValue?.length && ![1, 7].includes(+displayType)) {
|
||||
if (firstLoad) {
|
||||
return defaultValueCheck ? defaultMapValue : multiple ? [] : ''
|
||||
}
|
||||
return (selectValue?.length ? defaultMapValue : selectValue) || ''
|
||||
return (selectValue?.length ? mapValue : selectValue) || ''
|
||||
}
|
||||
|
||||
if (firstLoad && !selectValue?.length) {
|
||||
@ -152,7 +154,7 @@ const getOperator = (
|
||||
const operatorS = firstLoad ? defaultConditionValueOperatorS : conditionValueOperatorS
|
||||
if (displayType === '8') {
|
||||
if (conditionType === 0) {
|
||||
return defaultConditionValueOperatorF
|
||||
return operatorF
|
||||
}
|
||||
const operatorArr = [valueF === '' ? '' : operatorF, valueS === '' ? '' : operatorS].filter(
|
||||
ele => ele !== ''
|
||||
@ -180,7 +182,7 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
item.checkedFields.includes(curComponentId) &&
|
||||
item.checkedFieldsMap[curComponentId]
|
||||
) {
|
||||
let selectValue = ''
|
||||
let selectValue
|
||||
const {
|
||||
selectValue: value,
|
||||
timeGranularityMultiple,
|
||||
@ -200,6 +202,7 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
defaultValue,
|
||||
optionValueSource,
|
||||
defaultMapValue,
|
||||
mapValue,
|
||||
parameters = [],
|
||||
parametersCheck = false,
|
||||
isTree = false,
|
||||
@ -247,6 +250,7 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
)
|
||||
item.defaultValue = [startTime, endTime]
|
||||
item.selectValue = [startTime, endTime]
|
||||
selectValue = [startTime, endTime]
|
||||
}
|
||||
} else if (displayType === '8') {
|
||||
selectValue = getResult(
|
||||
@ -265,7 +269,9 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
firstLoad,
|
||||
multiple,
|
||||
defaultMapValue,
|
||||
optionValueSource
|
||||
optionValueSource,
|
||||
mapValue,
|
||||
displayType
|
||||
)
|
||||
}
|
||||
if (
|
||||
@ -294,23 +300,25 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
|
||||
firstLoad,
|
||||
optionValueSource
|
||||
)
|
||||
filter.push({
|
||||
componentId: ele.id,
|
||||
fieldId: item.checkedFieldsMap[curComponentId],
|
||||
operator,
|
||||
value: result,
|
||||
parameters: parametersCheck
|
||||
? +displayType === 7
|
||||
? [
|
||||
parametersStart,
|
||||
parametersEnd?.id
|
||||
? { ...parametersEnd, id: `${parametersEnd.id}_START_END_SPLIT` }
|
||||
: parametersEnd
|
||||
]
|
||||
: parameters
|
||||
: [],
|
||||
isTree
|
||||
})
|
||||
if (result?.length) {
|
||||
filter.push({
|
||||
componentId: ele.id,
|
||||
fieldId: item.checkedFieldsMap[curComponentId],
|
||||
operator,
|
||||
value: result,
|
||||
parameters: parametersCheck
|
||||
? +displayType === 7
|
||||
? [
|
||||
parametersStart,
|
||||
parametersEnd?.id
|
||||
? { ...parametersEnd, id: `${parametersEnd.id}_START_END_SPLIT` }
|
||||
: parametersEnd
|
||||
]
|
||||
: parameters
|
||||
: [],
|
||||
isTree
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -80,7 +80,7 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
.ai-main-active {
|
||||
border: 1px solid #d9d9d9;
|
||||
border: 1px solid rgba(239, 240, 241, 1);
|
||||
box-shadow: 0px 6px 24px 0px #1f232914;
|
||||
}
|
||||
.ai-main-active-min {
|
||||
|
84
core/core-frontend/src/layout/components/AiTips.vue
Normal file
@ -0,0 +1,84 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
const visible = ref(true)
|
||||
const emits = defineEmits(['confirm'])
|
||||
|
||||
const confirm = () => {
|
||||
emits('confirm')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// do
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<el-popover
|
||||
:visible="visible"
|
||||
placement="bottom"
|
||||
popper-class="ai-popper-tips"
|
||||
:width="288"
|
||||
show-arrow
|
||||
>
|
||||
<div class="ai-popper-tips-content">
|
||||
<p class="title">DataEase 智能客服</p>
|
||||
<p class="constant">
|
||||
你好,我是DataEase智能客服<br />点击一下,开启高效解答模式~<br />
|
||||
</p>
|
||||
<div class="bottom">
|
||||
<el-button size="middle" @click="confirm"> 我知道了 </el-button>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<div class="ai-popper-tips-icon">
|
||||
<el-icon style="margin: 2px" class="ai-icon">
|
||||
<Icon name="dv-ai" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.ai-popper-tips {
|
||||
z-index: 10001 !important;
|
||||
padding: 24px !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
.ed-popper__arrow::before {
|
||||
border: 1px solid var(--ed-color-primary) !important;
|
||||
background: var(--ed-color-primary) !important;
|
||||
}
|
||||
}
|
||||
.ai-popper-tips-content {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
.title {
|
||||
font-family: PingFang SC;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
}
|
||||
.content {
|
||||
font-family: PingFang SC;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
.bottom {
|
||||
line-height: 22px;
|
||||
text-align: right;
|
||||
button {
|
||||
font-weight: 500;
|
||||
color: rgba(51, 112, 255, 1) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-popper-tips-icon {
|
||||
margin: 0 8px;
|
||||
z-index: 10003;
|
||||
border-radius: 50%;
|
||||
background: #ffffff;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
</style>
|
@ -17,6 +17,7 @@ import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
|
||||
import AiComponent from '@/layout/components/AiComponent.vue'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { findBaseParams } from '@/api/aiComponent'
|
||||
import AiTips from '@/layout/components/AiTips.vue'
|
||||
const appearanceStore = useAppearanceStoreWithOut()
|
||||
const { push } = useRouter()
|
||||
const route = useRoute()
|
||||
@ -43,6 +44,7 @@ const permissionStore = usePermissionStore()
|
||||
const routers: any[] = formatRoute(permissionStore.getRoutersNotHidden as AppCustomRouteRecordRaw[])
|
||||
const showSystem = ref(false)
|
||||
const showToolbox = ref(false)
|
||||
const showOverlay = ref(true)
|
||||
const handleSelect = (index: string) => {
|
||||
// 自定义事件
|
||||
if (isExternal(index)) {
|
||||
@ -61,6 +63,12 @@ const navigateBg = computed(() => appearanceStore.getNavigateBg)
|
||||
const navigate = computed(() => appearanceStore.getNavigate)
|
||||
|
||||
const initAiBase = async () => {
|
||||
const aiTipsCheck = localStorage.getItem('DE-AI-TIPS-CHECK')
|
||||
if (aiTipsCheck === 'CHECKED') {
|
||||
showOverlay.value = false
|
||||
} else {
|
||||
showOverlay.value = true
|
||||
}
|
||||
await findBaseParams().then(rsp => {
|
||||
const params = rsp.data
|
||||
if (params && params['ai.baseUrl']) {
|
||||
@ -68,6 +76,11 @@ const initAiBase = async () => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const aiTipsConfirm = () => {
|
||||
localStorage.setItem('DE-AI-TIPS-CHECK', 'CHECKED')
|
||||
showOverlay.value = false
|
||||
}
|
||||
onMounted(() => {
|
||||
initShowSystem()
|
||||
initShowToolbox()
|
||||
@ -96,19 +109,30 @@ onMounted(() => {
|
||||
</el-menu>
|
||||
<div class="operate-setting" v-if="!desktop">
|
||||
<XpackComponent jsname="c3dpdGNoZXI=" />
|
||||
<el-icon style="margin: 0 10px" class="ai-icon" v-if="aiBaseUrl">
|
||||
<el-icon style="margin: 0 10px" class="ai-icon" v-if="aiBaseUrl && !showOverlay">
|
||||
<Icon name="dv-ai" @click="handleAiClick" />
|
||||
</el-icon>
|
||||
<ai-tips @confirm="aiTipsConfirm" v-if="showOverlay" class="ai-icon-tips"></ai-tips>
|
||||
<ToolboxCfg v-if="showToolbox" />
|
||||
<TopDoc />
|
||||
<SystemCfg v-if="showSystem" />
|
||||
<AccountOperator />
|
||||
<ai-component v-if="aiBaseUrl" :base-url="aiBaseUrl"></ai-component>
|
||||
<div v-if="showOverlay" class="overlay"></div>
|
||||
</div>
|
||||
</el-header>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色 */
|
||||
z-index: 10000;
|
||||
}
|
||||
.header-light {
|
||||
background-color: #ffffff !important;
|
||||
box-shadow: 0px 0.5px 0px 0px #1f232926 !important;
|
||||
@ -208,4 +232,9 @@ onMounted(() => {
|
||||
.ai-icon {
|
||||
font-size: 24px !important;
|
||||
}
|
||||
|
||||
.ai-icon-tips {
|
||||
font-size: 24px !important;
|
||||
z-index: 10001;
|
||||
}
|
||||
</style>
|
||||
|
@ -449,7 +449,9 @@ export default {
|
||||
latitude: '纬度',
|
||||
gradient: '渐变',
|
||||
layer_controller: '指标切换',
|
||||
suspension: '悬浮',
|
||||
show_zoom: '显示缩放按钮',
|
||||
button_color: '按钮颜色',
|
||||
button_background_color: '按钮背景色',
|
||||
chart_background: '组件背景',
|
||||
date_format: '请选择日期解析格式',
|
||||
solid_color: '纯色',
|
||||
@ -646,6 +648,9 @@ export default {
|
||||
table_item_font_color: '表格字体',
|
||||
table_show_index: '显示序号',
|
||||
table_header_sort: '开启表头排序',
|
||||
table_show_row_tooltip: '开启行头提示',
|
||||
table_show_col_tooltip: '开启列头提示',
|
||||
table_show_cell_tooltip: '开启单元格提示',
|
||||
stripe: '斑马纹',
|
||||
start_angle: '起始角度',
|
||||
end_angle: '结束角度',
|
||||
@ -977,6 +982,7 @@ export default {
|
||||
dimension_font_family: '名称字体',
|
||||
dimension_text_style: '名称样式',
|
||||
dimension_letter_space: '名称字间距',
|
||||
name_value_spacing: '名称/值间距',
|
||||
font_family: '字体',
|
||||
letter_space: '字间距',
|
||||
font_shadow: '字体阴影',
|
||||
@ -1102,7 +1108,9 @@ export default {
|
||||
add_condition: '添加条件',
|
||||
chart_quadrant: '象限图',
|
||||
quadrant: '象限',
|
||||
font_size: '字号'
|
||||
font_size: '字号',
|
||||
word_size_range: '字号区间',
|
||||
word_spacing: '文字间隔'
|
||||
},
|
||||
dataset: {
|
||||
scope_edit: '仅编辑时生效',
|
||||
|
167
core/core-frontend/src/models/chart/chart-attr.d.ts
vendored
@ -38,6 +38,14 @@ declare interface ChartAttr {
|
||||
* 象限设置
|
||||
*/
|
||||
quadrant: QuadrantAttr
|
||||
/**
|
||||
* 指标值
|
||||
*/
|
||||
indicator: ChartIndicatorStyle
|
||||
/**
|
||||
* 指标名称
|
||||
*/
|
||||
indicatorName: ChartIndicatorNameStyle
|
||||
}
|
||||
/**
|
||||
* 基础样式设置
|
||||
@ -161,9 +169,10 @@ declare interface ChartBasicStyle {
|
||||
*/
|
||||
areaBorderColor: string
|
||||
/**
|
||||
* @deprecated
|
||||
* 悬浮工具栏
|
||||
*/
|
||||
suspension: boolean
|
||||
suspension?: boolean
|
||||
/**
|
||||
* 地图底色
|
||||
*/
|
||||
@ -192,6 +201,18 @@ declare interface ChartBasicStyle {
|
||||
* 环形图/玫瑰图外径占比
|
||||
*/
|
||||
radius: number
|
||||
/**
|
||||
* 是否显示地图缩放按钮
|
||||
*/
|
||||
showZoom: boolean
|
||||
/**
|
||||
* 地图缩放按钮颜色
|
||||
*/
|
||||
zoomButtonColor: string
|
||||
/**
|
||||
* 地图缩放按钮背景颜色
|
||||
*/
|
||||
zoomBackground: string
|
||||
}
|
||||
/**
|
||||
* 表头属性
|
||||
@ -229,6 +250,14 @@ declare interface ChartTableHeaderAttr {
|
||||
* 表头排序开关
|
||||
*/
|
||||
tableHeaderSort: boolean
|
||||
/**
|
||||
* 行头鼠标悬浮提示开关
|
||||
*/
|
||||
showRowTooltip: boolean
|
||||
/**
|
||||
* 列头鼠标悬浮提示开关
|
||||
*/
|
||||
showColTooltip: boolean
|
||||
}
|
||||
/**
|
||||
* 单元格属性
|
||||
@ -262,6 +291,10 @@ declare interface ChartTableCellAttr {
|
||||
* 斑马纹单数行颜色
|
||||
*/
|
||||
tableItemSubBgColor: string
|
||||
/**
|
||||
* 鼠标悬浮提示
|
||||
*/
|
||||
showTooltip: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
@ -517,6 +550,14 @@ declare interface ChartMiscAttr {
|
||||
* 指标/文本卡垂直位置
|
||||
*/
|
||||
vPosition: 'top' | 'center' | 'bottom'
|
||||
/**
|
||||
* 词云图字体大小区间
|
||||
*/
|
||||
wordSizeRange: [number, number]
|
||||
/**
|
||||
* 词云图文字间距
|
||||
*/
|
||||
wordSpacing: number
|
||||
}
|
||||
/**
|
||||
* 动态极值配置
|
||||
@ -702,3 +743,127 @@ declare interface QuadrantLineStyle {
|
||||
*/
|
||||
opacity: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 指标卡值样式
|
||||
*/
|
||||
declare interface ChartIndicatorStyle {
|
||||
/**
|
||||
* 是否显示
|
||||
*/
|
||||
show: boolean
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
fontSize: number
|
||||
/**
|
||||
* 字体颜色
|
||||
*/
|
||||
color: string
|
||||
/**
|
||||
* 水平位置
|
||||
*/
|
||||
hPosition: 'left' | 'center' | 'right'
|
||||
/**
|
||||
* 垂直位置
|
||||
*/
|
||||
vPosition: 'top' | 'center' | 'bottom'
|
||||
/**
|
||||
* 是否斜体
|
||||
*/
|
||||
isItalic: boolean
|
||||
/**
|
||||
* 是否加粗
|
||||
*/
|
||||
isBolder: boolean
|
||||
/**
|
||||
* 字体类型
|
||||
*/
|
||||
fontFamily: string
|
||||
/**
|
||||
* 字间距
|
||||
*/
|
||||
letterSpace: number
|
||||
/**
|
||||
* 是否显示字体阴影
|
||||
*/
|
||||
fontShadow: boolean
|
||||
/**
|
||||
* 是否显示后缀
|
||||
*/
|
||||
suffixEnable: boolean
|
||||
/**
|
||||
* 后缀内容
|
||||
*/
|
||||
suffix: string
|
||||
/**
|
||||
* 后缀字体大小
|
||||
*/
|
||||
suffixFontSize: number
|
||||
/**
|
||||
* 后缀字体颜色
|
||||
*/
|
||||
suffixColor: string
|
||||
/**
|
||||
* 后缀是否斜体
|
||||
*/
|
||||
suffixIsItalic: boolean
|
||||
/**
|
||||
* 后缀是否加粗
|
||||
*/
|
||||
suffixIsBolder: boolean
|
||||
/**
|
||||
* 后缀字体类型
|
||||
*/
|
||||
suffixFontFamily: string
|
||||
/**
|
||||
* 后缀字间距
|
||||
*/
|
||||
suffixLetterSpace: number
|
||||
/**
|
||||
* 后置是否显示阴影
|
||||
*/
|
||||
suffixFontShadow: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 指标卡名称样式
|
||||
*/
|
||||
declare interface ChartIndicatorNameStyle {
|
||||
/**
|
||||
* 是否显示
|
||||
*/
|
||||
show: boolean
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
fontSize: number
|
||||
/**
|
||||
* 字体颜色
|
||||
*/
|
||||
color: string
|
||||
/**
|
||||
* 是否斜体
|
||||
*/
|
||||
isItalic: boolean
|
||||
/**
|
||||
* 是否加粗
|
||||
*/
|
||||
isBolder: boolean
|
||||
/**
|
||||
* 字体类型
|
||||
*/
|
||||
fontFamily: string
|
||||
/**
|
||||
* 字间距
|
||||
*/
|
||||
letterSpace: number
|
||||
/**
|
||||
* 是否显示字体阴影
|
||||
*/
|
||||
fontShadow: boolean
|
||||
/**
|
||||
* 指标/名称间距
|
||||
*/
|
||||
nameValueSpacing: number
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ declare interface AssistLine {
|
||||
*/
|
||||
summary: string
|
||||
|
||||
axisType: 'left' | 'right'
|
||||
yAxisType: 'left' | 'right'
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,39 +32,6 @@ declare interface ChartStyle {
|
||||
}
|
||||
}
|
||||
|
||||
declare interface ChartIndicatorStyle {
|
||||
show: boolean
|
||||
fontSize: string
|
||||
color: string
|
||||
hPosition: 'left' | 'center' | 'right'
|
||||
vPosition: 'top' | 'center' | 'bottom'
|
||||
isItalic: boolean
|
||||
isBolder: boolean
|
||||
fontFamily: string
|
||||
letterSpace: string
|
||||
fontShadow: boolean
|
||||
|
||||
suffixEnable: boolean
|
||||
suffix: string
|
||||
suffixFontSize: string
|
||||
suffixColor: string
|
||||
suffixIsItalic: boolean
|
||||
suffixIsBolder: boolean
|
||||
suffixFontFamily: string
|
||||
suffixLetterSpace: string
|
||||
suffixFontShadow: boolean
|
||||
}
|
||||
declare interface ChartIndicatorNameStyle {
|
||||
show: boolean
|
||||
fontSize: string
|
||||
color: string
|
||||
isItalic: boolean
|
||||
isBolder: boolean
|
||||
fontFamily: string
|
||||
letterSpace: string
|
||||
fontShadow: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 标题样式设置
|
||||
*/
|
||||
|
@ -2,7 +2,22 @@ import { createRouter, createWebHashHistory } from 'vue-router'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import type { App } from 'vue'
|
||||
|
||||
export const routes: AppRouteRecordRaw[] = []
|
||||
export const routes: AppRouteRecordRaw[] = [
|
||||
{
|
||||
path: '/dvCanvas',
|
||||
name: 'dvCanvas',
|
||||
hidden: true,
|
||||
meta: {},
|
||||
component: () => import('@/views/data-visualization/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'dashboard',
|
||||
hidden: true,
|
||||
meta: {},
|
||||
component: () => import('@/views/dashboard/index.vue')
|
||||
}
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
|
@ -812,7 +812,7 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
const checkQDList = [...data.dimensionList, ...data.quotaList]
|
||||
for (let indexOuter = 0; indexOuter < this.componentData.length; indexOuter++) {
|
||||
const element = this.componentData[indexOuter]
|
||||
if (element.component === 'UserView' && element.innerType != 'VQuery') {
|
||||
if (['UserView', 'VQuery'].includes(element.component)) {
|
||||
this.trackFilterCursor(element, checkQDList, trackInfo, preActiveComponentIds, viewId)
|
||||
this.componentData[indexOuter] = element
|
||||
} else if (element.component === 'Group') {
|
||||
@ -900,18 +900,36 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
if (element.component === 'VQuery') {
|
||||
element.propValue.forEach(filterItem => {
|
||||
if (filterItem.id === targetViewId) {
|
||||
let queryParams = paramValue
|
||||
if (!['1', '7'].includes(filterItem.displayType)) {
|
||||
// 查询组件除了时间组件 其他入参只支持文本 这里全部转为文本
|
||||
queryParams = paramValue.map(number => String(number))
|
||||
}
|
||||
filterItem.defaultValueCheck = true
|
||||
if (filterItem.displayType === '0' && filterItem.multiple) {
|
||||
filterItem.selectValue = paramValue
|
||||
filterItem.defaultValue = paramValue
|
||||
} else if (filterItem.displayType === '0' && !filterItem.multiple) {
|
||||
filterItem.selectValue = paramValue[0]
|
||||
filterItem.defaultValue = paramValue[0]
|
||||
filterItem.timeType = 'fixed'
|
||||
if (['0', '2'].includes(filterItem.displayType)) {
|
||||
// 0 文本类型 1 数字类型
|
||||
if (filterItem.multiple) {
|
||||
// multiple === true 多选
|
||||
filterItem.selectValue = queryParams
|
||||
filterItem.defaultValue = queryParams
|
||||
} else {
|
||||
// 单选
|
||||
filterItem.selectValue = queryParams[0]
|
||||
filterItem.defaultValue = queryParams[0]
|
||||
}
|
||||
} else if (filterItem.displayType === '1') {
|
||||
// 1 时间类型
|
||||
filterItem.selectValue = queryParams[0]
|
||||
filterItem.defaultValue = queryParams[0]
|
||||
} else if (filterItem.displayType === '7') {
|
||||
// 7 时间范围类型
|
||||
filterItem.selectValue = queryParams
|
||||
filterItem.defaultValue = queryParams
|
||||
} else if (filterItem.displayType === '8') {
|
||||
filterItem.conditionValueF = parmaValueSource
|
||||
} else {
|
||||
filterItem.selectValue = paramValue[0]
|
||||
filterItem.defaultValue = paramValue[0]
|
||||
// 8 文本搜索
|
||||
filterItem.conditionValueF = parmaValueSource + ''
|
||||
filterItem.defaultConditionValueF = parmaValueSource + ''
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -933,10 +951,11 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
const sourceInfo = viewId + '#' + QDItem.id
|
||||
// 获取所有目标联动信息
|
||||
const targetInfoList = trackInfo[sourceInfo] || []
|
||||
const paramValue = [QDItem.value]
|
||||
targetInfoList.forEach(targetInfo => {
|
||||
const targetInfoArray = targetInfo.split('#')
|
||||
const targetViewId = targetInfoArray[0] // 目标图表
|
||||
if (element.id === targetViewId) {
|
||||
if (element.component === 'UserView' && element.id === targetViewId) {
|
||||
// 如果目标图表 和 当前循环组件id相等 则进行条件增减
|
||||
const targetFieldId = targetInfoArray[1] // 目标图表列ID
|
||||
const condition = {
|
||||
@ -959,6 +978,43 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
currentFilters.push(condition)
|
||||
preActiveComponentIds.includes(element.id) || preActiveComponentIds.push(element.id)
|
||||
}
|
||||
if (element.component === 'VQuery') {
|
||||
element.propValue.forEach(filterItem => {
|
||||
if (filterItem.id === targetViewId) {
|
||||
let queryParams = paramValue
|
||||
if (!['1', '7'].includes(filterItem.displayType)) {
|
||||
// 查询组件除了时间组件 其他入参只支持文本 这里全部转为文本
|
||||
queryParams = paramValue.map(number => String(number))
|
||||
}
|
||||
filterItem.defaultValueCheck = true
|
||||
filterItem.timeType = 'fixed'
|
||||
if (['0', '2'].includes(filterItem.displayType)) {
|
||||
// 0 文本类型 1 数字类型
|
||||
if (filterItem.multiple) {
|
||||
// multiple === true 多选
|
||||
filterItem.selectValue = queryParams
|
||||
filterItem.defaultValue = queryParams
|
||||
} else {
|
||||
// 单选
|
||||
filterItem.selectValue = queryParams[0]
|
||||
filterItem.defaultValue = queryParams[0]
|
||||
}
|
||||
} else if (filterItem.displayType === '1') {
|
||||
// 1 时间类型
|
||||
filterItem.selectValue = queryParams[0]
|
||||
filterItem.defaultValue = queryParams[0]
|
||||
} else if (filterItem.displayType === '7') {
|
||||
// 7 时间范围类型
|
||||
filterItem.selectValue = queryParams
|
||||
filterItem.defaultValue = queryParams
|
||||
} else if (filterItem.displayType === '8') {
|
||||
// 8 文本搜索
|
||||
filterItem.conditionValueF = queryParams[0]
|
||||
filterItem.defaultConditionValueF = queryParams[0]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
element.linkageFilters = currentFilters
|
||||
|
@ -121,12 +121,14 @@ export const customAttrTrans = {
|
||||
'valueFontSize',
|
||||
'spaceSplit', // 间隔
|
||||
'scatterSymbolSize', // 气泡大小,散点图
|
||||
'radarSize' // 雷达占比
|
||||
'radarSize', // 雷达占比
|
||||
'wordSizeRange',
|
||||
'wordSpacing'
|
||||
],
|
||||
label: ['fontSize'],
|
||||
tooltip: ['fontSize'],
|
||||
indicator: ['fontSize', 'suffixFontSize'],
|
||||
indicatorName: ['fontSize']
|
||||
indicatorName: ['fontSize', 'nameValueSpacing']
|
||||
}
|
||||
export const customStyleTrans = {
|
||||
text: ['fontSize'],
|
||||
@ -278,6 +280,13 @@ export const mobileSpecialProps = {
|
||||
}
|
||||
|
||||
export function getScaleValue(propValue, scale) {
|
||||
if (propValue instanceof Array) {
|
||||
propValue.forEach((v, i) => {
|
||||
const val = Math.round(v * scale)
|
||||
propValue[i] = val > 1 ? val : 1
|
||||
})
|
||||
return propValue
|
||||
}
|
||||
const propValueTemp = Math.round(propValue * scale)
|
||||
return propValueTemp > 1 ? propValueTemp : 1
|
||||
}
|
||||
|
@ -420,3 +420,20 @@ export async function decompressionPre(params, callBack) {
|
||||
})
|
||||
callBack(deTemplateData)
|
||||
}
|
||||
|
||||
export function trackBarStyleCheck(element, trackbarStyle, scale) {
|
||||
const { width, height } = element.style
|
||||
const widthReal = width
|
||||
const heightReal = height
|
||||
if (trackbarStyle.left < 0) {
|
||||
trackbarStyle.left = 0
|
||||
} else if (widthReal - trackbarStyle.left < 60) {
|
||||
trackbarStyle.left = trackbarStyle.left - 60
|
||||
}
|
||||
|
||||
if (trackbarStyle.top < 0) {
|
||||
trackbarStyle.top = 0
|
||||
} else if (heightReal - trackbarStyle.top < 100) {
|
||||
trackbarStyle.top = trackbarStyle.top - 100
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ onMounted(() => {
|
||||
<span class="el-dropdown-link inner-dropdown-menu menu-item-padding">
|
||||
<span class="menu-item-content">
|
||||
<el-icon>
|
||||
<Icon name="icon_functions_outlined" />
|
||||
<Icon name="icon_dashboard_outlined" />
|
||||
</el-icon>
|
||||
<span>{{ t('chart.chart_type') }}</span>
|
||||
</span>
|
||||
|
@ -54,11 +54,6 @@ const state = reactive({
|
||||
quotaFields: []
|
||||
})
|
||||
|
||||
const axisType = [
|
||||
{ type: 'left', name: t('chart.drag_block_value_axis_left') },
|
||||
{ type: 'right', name: t('chart.drag_block_value_axis_right') }
|
||||
]
|
||||
|
||||
watch(
|
||||
() => props.chart.senior.assistLineCfg,
|
||||
() => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick, onMounted, PropType, reactive, ref, watch } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { getGeoJsonFile, parseJson } from '../../../js/util'
|
||||
import { forEach, debounce } from 'lodash-es'
|
||||
import { EmptyBackground } from '@/components/empty-background'
|
||||
@ -118,14 +117,6 @@ const updateAreaData = debounce(() => {
|
||||
const onMapMappingChange = () => {
|
||||
emit('onMapMappingChange', state.mappingForm)
|
||||
}
|
||||
const mergeCellMethod = ({ columnIndex }) => {
|
||||
if (columnIndex === 1) {
|
||||
return [1, 2]
|
||||
}
|
||||
if (columnIndex === 2) {
|
||||
return [0, 0]
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
@ -141,7 +132,6 @@ onMounted(() => {
|
||||
:cell-class-name="'area-map-table-cell-' + themes"
|
||||
:row-class-name="'area-map-table-row-' + themes"
|
||||
:data="areaData"
|
||||
:span-method="mergeCellMethod"
|
||||
>
|
||||
<el-table-column label="图形" prop="originName" width="80" show-overflow-tooltip />
|
||||
<el-table-column width="144">
|
||||
|
@ -26,7 +26,7 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const axisTypes = [
|
||||
const yAxisTypes = [
|
||||
{ type: 'left', name: t('chart.drag_block_value_axis_left') },
|
||||
{ type: 'right', name: t('chart.drag_block_value_axis_right') }
|
||||
]
|
||||
@ -39,7 +39,7 @@ const state = reactive({
|
||||
fieldId: '',
|
||||
summary: 'avg',
|
||||
axis: 'y', // 主轴
|
||||
axisType: 'left',
|
||||
yAxisType: 'left',
|
||||
value: '0',
|
||||
lineType: 'solid',
|
||||
color: '#ff0000',
|
||||
@ -76,8 +76,23 @@ const init = () => {
|
||||
state.lineArr = JSON.parse(JSON.stringify(props.line))
|
||||
|
||||
state.lineArr.forEach(line => {
|
||||
if (find(props.quotaFields, d => d.id === line.fieldId) == undefined) {
|
||||
line.fieldId = undefined
|
||||
if (props.useQuotaExt) {
|
||||
if (
|
||||
line.yAxisType === 'left' &&
|
||||
find(props.quotaFields, d => d.id === line.fieldId) == undefined
|
||||
) {
|
||||
line.fieldId = undefined
|
||||
}
|
||||
if (
|
||||
line.yAxisType === 'right' &&
|
||||
find(props.quotaExtFields, d => d.id === line.fieldId) == undefined
|
||||
) {
|
||||
line.fieldId = undefined
|
||||
}
|
||||
} else {
|
||||
if (find(props.quotaFields, d => d.id === line.fieldId) == undefined) {
|
||||
line.fieldId = undefined
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -98,8 +113,8 @@ const removeLine = index => {
|
||||
changeAssistLine()
|
||||
}
|
||||
|
||||
const changeAxisType = item => {
|
||||
if (props.useQuotaExt && item.axisType === 'right') {
|
||||
const changeYAxisType = item => {
|
||||
if (props.useQuotaExt && item.yAxisType === 'right') {
|
||||
item.fieldId = props.quotaExtFields ? props.quotaExtFields[0]?.id : null
|
||||
item.curField = getQuotaExtField(item.fieldId)
|
||||
} else {
|
||||
@ -113,7 +128,7 @@ const changeAssistLine = () => {
|
||||
emit('onAssistLineChange', state.lineArr)
|
||||
}
|
||||
const changeAssistLineField = item => {
|
||||
if (props.useQuotaExt && item.axisType === 'right') {
|
||||
if (props.useQuotaExt && item.yAxisType === 'right') {
|
||||
item.curField = getQuotaExtField(item.fieldId)
|
||||
} else {
|
||||
item.curField = getQuotaField(item.fieldId)
|
||||
@ -169,9 +184,9 @@ onMounted(() => {
|
||||
/>
|
||||
</el-col>
|
||||
<el-col v-if="useQuotaExt" :span="3">
|
||||
<el-select v-model="item.axisType" class="select-item" @change="changeAxisType(item)">
|
||||
<el-select v-model="item.yAxisType" class="select-item" @change="changeYAxisType(item)">
|
||||
<el-option
|
||||
v-for="opt in axisTypes"
|
||||
v-for="opt in yAxisTypes"
|
||||
:key="opt.type"
|
||||
:label="opt.name"
|
||||
:value="opt.type"
|
||||
@ -206,7 +221,7 @@ onMounted(() => {
|
||||
@change="changeAssistLineField(item)"
|
||||
>
|
||||
<el-option
|
||||
v-for="quota in useQuotaExt && item.axisType === 'right'
|
||||
v-for="quota in useQuotaExt && item.yAxisType === 'right'
|
||||
? quotaExtFields
|
||||
: quotaFields"
|
||||
:key="quota.id"
|
||||
|
@ -116,11 +116,14 @@ const onChangeXAxisForm = (val, prop) => {
|
||||
}
|
||||
|
||||
const onChangeYAxisForm = (val, prop) => {
|
||||
if (prop === 'show' && chart.value.type === 'chart-mix') {
|
||||
chart.value.customStyle.yAxisExt.show = val.show
|
||||
onChangeYAxisExtForm(chart.value.customStyle.yAxisExt, 'show')
|
||||
}
|
||||
state.initReady && emit('onChangeYAxisForm', val, prop)
|
||||
}
|
||||
|
||||
const onChangeYAxisExtForm = (val, prop) => {
|
||||
console.log(val, prop)
|
||||
state.initReady && emit('onChangeYAxisExtForm', val, prop)
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ const changeBasicStyle = (prop?: string, requestData = false) => {
|
||||
}
|
||||
const init = () => {
|
||||
const basicStyle = cloneDeep(props.chart.customAttr.basicStyle)
|
||||
configCompat(basicStyle)
|
||||
state.basicStyleForm = defaultsDeep(basicStyle, cloneDeep(DEFAULT_BASIC_STYLE)) as ChartBasicStyle
|
||||
if (!state.customColor) {
|
||||
state.customColor = state.basicStyleForm.colors[0]
|
||||
@ -56,6 +57,12 @@ const init = () => {
|
||||
}
|
||||
initTableColumnWidth()
|
||||
}
|
||||
const configCompat = (basicStyle: ChartBasicStyle) => {
|
||||
// 悬浮改为图例和缩放按钮
|
||||
if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
|
||||
basicStyle.showZoom = false
|
||||
}
|
||||
}
|
||||
const COLUMN_WIDTH_TYPE = ['table-info', 'table-normal']
|
||||
const initTableColumnWidth = () => {
|
||||
if (!COLUMN_WIDTH_TYPE.includes(props.chart.type)) {
|
||||
@ -191,6 +198,39 @@ onMounted(() => {
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
|
||||
<div class="alpha-setting" v-if="showProperty('alpha')">
|
||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||
{{ t('chart.not_alpha') }}
|
||||
</label>
|
||||
<el-row style="flex: 1" :gutter="8">
|
||||
<el-col :span="13">
|
||||
<el-form-item class="form-item alpha-slider" :class="'form-item-' + themes">
|
||||
<el-slider
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.alpha"
|
||||
@change="changeBasicStyle('alpha')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="11" style="padding-top: 2px">
|
||||
<el-form-item class="form-item" :class="'form-item-' + themes">
|
||||
<el-input
|
||||
type="number"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.alpha"
|
||||
:min="0"
|
||||
:max="100"
|
||||
class="basic-input-number"
|
||||
:controls="false"
|
||||
@change="changeBasicStyle('alpha')"
|
||||
>
|
||||
<template #suffix> % </template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!--map start-->
|
||||
<el-row :gutter="8">
|
||||
<el-col :span="12" v-if="showProperty('areaBorderColor')">
|
||||
@ -230,21 +270,51 @@ onMounted(() => {
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
v-if="showProperty('suspension')"
|
||||
>
|
||||
<el-form-item class="form-item" :class="'form-item-' + themes" v-if="showProperty('zoom')">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.suspension"
|
||||
v-model="state.basicStyleForm.showZoom"
|
||||
:predefine="predefineColors"
|
||||
@change="changeBasicStyle('suspension')"
|
||||
@change="changeBasicStyle('zoomShow')"
|
||||
>
|
||||
{{ t('chart.suspension') }}
|
||||
{{ t('chart.show_zoom') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<div v-if="showProperty('zoom') && state.basicStyleForm.showZoom">
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
:label="t('chart.button_color')"
|
||||
>
|
||||
<el-color-picker
|
||||
is-custom
|
||||
class="color-picker-style"
|
||||
v-model="state.basicStyleForm.zoomButtonColor"
|
||||
:persistent="false"
|
||||
:effect="themes"
|
||||
:trigger-width="108"
|
||||
:predefine="predefineColors"
|
||||
@change="changeBasicStyle('zoomButtonColor')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
:label="t('chart.button_background_color')"
|
||||
>
|
||||
<el-color-picker
|
||||
is-custom
|
||||
class="color-picker-style"
|
||||
v-model="state.basicStyleForm.zoomBackground"
|
||||
:persistent="false"
|
||||
:effect="themes"
|
||||
:trigger-width="108"
|
||||
:predefine="predefineColors"
|
||||
@change="changeBasicStyle('zoomBackground')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<!--map end-->
|
||||
|
||||
@ -335,39 +405,6 @@ onMounted(() => {
|
||||
</el-row>
|
||||
<!--table end-->
|
||||
|
||||
<div class="alpha-setting" v-if="showProperty('alpha')">
|
||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||
{{ t('chart.not_alpha') }}
|
||||
</label>
|
||||
<el-row style="flex: 1" :gutter="8">
|
||||
<el-col :span="13">
|
||||
<el-form-item class="form-item alpha-slider" :class="'form-item-' + themes">
|
||||
<el-slider
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.alpha"
|
||||
@change="changeBasicStyle('alpha')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="11" style="padding-top: 2px">
|
||||
<el-form-item class="form-item" :class="'form-item-' + themes">
|
||||
<el-input
|
||||
type="number"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.alpha"
|
||||
:min="0"
|
||||
:max="100"
|
||||
class="basic-input-number"
|
||||
:controls="false"
|
||||
@change="changeBasicStyle('alpha')"
|
||||
>
|
||||
<template #suffix> % </template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!--table2 start-->
|
||||
<el-form-item
|
||||
:label="t('chart.table_column_width_config')"
|
||||
|
@ -49,7 +49,6 @@ const changeAxisStyle = (val, prop) => {
|
||||
}
|
||||
|
||||
const changeSubAxisStyle = (val, prop) => {
|
||||
console.log(val, prop)
|
||||
emit('onChangeYAxisExtForm', val, prop)
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
DEFAULT_BASIC_STYLE
|
||||
} from '@/views/chart/components/editor/util/chart'
|
||||
import { cloneDeep, defaultsDeep } from 'lodash-es'
|
||||
import { ElIcon } from 'element-plus-secondary'
|
||||
import Icon from '@/components/icon-custom/src/Icon.vue'
|
||||
import { hexColorToRGBA } from '@/views/chart/components/js/util'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
@ -251,6 +250,24 @@ defineExpose({ getFormData })
|
||||
{{ t('chart.font_shadow') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item name-value-spacing-input"
|
||||
:class="'form-item-' + themes"
|
||||
:label="t('chart.name_value_spacing')"
|
||||
>
|
||||
<el-input-number
|
||||
step-strictly
|
||||
v-model="state.indicatorNameForm.nameValueSpacing"
|
||||
size="small"
|
||||
:min="0"
|
||||
:max="100"
|
||||
:value-on-clear="0"
|
||||
:precision="0"
|
||||
:step="1"
|
||||
:effect="themes"
|
||||
@change="changeTitleStyle('nameValueSpacing')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
@ -366,4 +383,14 @@ defineExpose({ getFormData })
|
||||
color: var(--N600-Dark, #a6a6a6);
|
||||
}
|
||||
}
|
||||
.name-value-spacing-input {
|
||||
display: flex !important;
|
||||
:deep(label) {
|
||||
line-height: 28px !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
:deep(.ed-input__inner) {
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -7,11 +7,12 @@ import cloneDeep from 'lodash-es/cloneDeep'
|
||||
import defaultsDeep from 'lodash-es/defaultsDeep'
|
||||
import { formatterType, unitType } from '../../../js/formatter'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import { partition } from 'lodash-es'
|
||||
import { partition, uniqWith, isEqual } from 'lodash-es'
|
||||
import chartViewManager from '../../../js/panel'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -98,7 +99,9 @@ const quotaAxis = computed(() => {
|
||||
return
|
||||
}
|
||||
const axis = props.chart[prop]
|
||||
axis?.forEach(item => result.push(item))
|
||||
axis?.forEach(item => {
|
||||
result.push({ ...item, seriesId: `${item.id}-${prop}` })
|
||||
})
|
||||
})
|
||||
return result
|
||||
})
|
||||
@ -255,6 +258,9 @@ const updateSeriesTooltipFormatter = (form: AxisEditForm) => {
|
||||
const addAxis = (form: AxisEditForm) => {
|
||||
const { axis, axisType } = form
|
||||
const axisMap = axis.reduce((pre, next) => {
|
||||
if (!next) {
|
||||
return pre
|
||||
}
|
||||
next.axisType = axisType
|
||||
next.seriesId = `${next.id}-${axisType}`
|
||||
pre[next.id] = next
|
||||
@ -272,16 +278,17 @@ const addAxis = (form: AxisEditForm) => {
|
||||
ele.chartShowName = axisMap[ele.id].chartShowName
|
||||
} else {
|
||||
// 其他轴已有的字段
|
||||
if (dupAxis.findIndex(i => i.id === ele.id) !== -1) {
|
||||
return
|
||||
}
|
||||
const tmp = cloneDeep(axisMap[ele.id])
|
||||
tmp.show = true
|
||||
dupAxis.push(tmp)
|
||||
}
|
||||
}
|
||||
})
|
||||
state.tooltipForm.seriesTooltipFormatter =
|
||||
state.tooltipForm.seriesTooltipFormatter.concat(dupAxis)
|
||||
state.tooltipForm.seriesTooltipFormatter = partition(
|
||||
state.tooltipForm.seriesTooltipFormatter,
|
||||
state.tooltipForm.seriesTooltipFormatter.concat(dupAxis),
|
||||
ele => quotaAxis.value.findIndex(item => item.id === ele.id) !== -1
|
||||
).flat()
|
||||
}
|
||||
@ -312,8 +319,8 @@ const removeAxis = (form: AxisEditForm) => {
|
||||
if (axisMap[ele.seriesId]) {
|
||||
// 数据集中的字段
|
||||
ele.show = false
|
||||
ele.summary = axisMap[ele.seriesId].summary
|
||||
ele.seriesId = ele.id
|
||||
ele.summary = 'sum'
|
||||
}
|
||||
})
|
||||
state.tooltipForm.seriesTooltipFormatter = partition(
|
||||
@ -531,7 +538,7 @@ onMounted(() => {
|
||||
</template>
|
||||
<el-option
|
||||
class="series-select-option"
|
||||
:key="item.id"
|
||||
:key="item.seriesId"
|
||||
:value="item"
|
||||
:label="`${item.name}${
|
||||
item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : ''
|
||||
|
@ -234,6 +234,20 @@ onMounted(() => {
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
v-if="showProperty('showTooltip')"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.tableCellForm.showTooltip"
|
||||
@change="changeTableCell('showTooltip')"
|
||||
>
|
||||
{{ t('chart.table_show_cell_tooltip') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
|
@ -250,6 +250,34 @@ onMounted(() => {
|
||||
{{ t('chart.table_header_sort') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
v-if="showProperty('showColTooltip')"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.tableHeaderForm.showColTooltip"
|
||||
@change="changeTableHeader('showColTooltip')"
|
||||
>
|
||||
{{ t('chart.table_show_col_tooltip') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
v-if="showProperty('showRowTooltip')"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.tableHeaderForm.showRowTooltip"
|
||||
@change="changeTableHeader('showRowTooltip')"
|
||||
>
|
||||
{{ t('chart.table_show_row_tooltip') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
|
@ -1394,7 +1394,7 @@ const drop = (ev: MouseEvent, type = 'xAxis') => {
|
||||
const obj = cloneDeep(arr[i])
|
||||
state.moveId = obj.id as unknown as number
|
||||
view.value[type].push(obj)
|
||||
const e = { newDraggableIndex: view.value.xAxis.length - 1 }
|
||||
const e = { newDraggableIndex: view.value[type].length - 1 }
|
||||
if ('drillFields' === type) {
|
||||
addDrill(e)
|
||||
} else if (type === 'customFilter') {
|
||||
|
@ -24,7 +24,9 @@ export const DEFAULT_COLOR_CASE: DeepPartial<ChartAttr> = {
|
||||
areaBorderColor: '#303133',
|
||||
gaugeStyle: 'default',
|
||||
tableBorderColor: '#E6E7E4',
|
||||
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)'
|
||||
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
|
||||
zoomButtonColor: '#aaa',
|
||||
zoomBackground: '#fff'
|
||||
},
|
||||
misc: {
|
||||
mapLineGradient: false,
|
||||
@ -65,7 +67,9 @@ export const DEFAULT_COLOR_CASE_LIGHT: DeepPartial<ChartAttr> = {
|
||||
areaBorderColor: '#303133',
|
||||
gaugeStyle: 'default',
|
||||
tableBorderColor: '#E6E7E4',
|
||||
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)'
|
||||
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
|
||||
zoomButtonColor: '#aaa',
|
||||
zoomBackground: '#fff'
|
||||
},
|
||||
misc: {
|
||||
mapLineGradient: false,
|
||||
@ -106,7 +110,9 @@ export const DEFAULT_COLOR_CASE_DARK: DeepPartial<ChartAttr> = {
|
||||
areaBorderColor: '#EBEEF5',
|
||||
gaugeStyle: 'default',
|
||||
tableBorderColor: '#CCCCCC',
|
||||
tableScrollBarColor: 'rgba(255, 255, 255, 0.5)'
|
||||
tableScrollBarColor: 'rgba(255, 255, 255, 0.5)',
|
||||
zoomButtonColor: '#fff',
|
||||
zoomBackground: '#000'
|
||||
},
|
||||
misc: {
|
||||
mapLineGradient: false,
|
||||
@ -242,10 +248,9 @@ export const DEFAULT_MISC: ChartMiscAttr = {
|
||||
mapLineAnimateDuration: 3,
|
||||
mapLineGradient: false,
|
||||
mapLineSourceColor: '#146C94',
|
||||
mapLineTargetColor: '#576CBC'
|
||||
}
|
||||
export const DEFAULT_SUSPENSION = {
|
||||
show: true
|
||||
mapLineTargetColor: '#576CBC',
|
||||
wordSizeRange: [8, 32],
|
||||
wordSpacing: 6
|
||||
}
|
||||
|
||||
export const DEFAULT_MARK = {
|
||||
@ -330,7 +335,9 @@ export const DEFAULT_TABLE_HEADER: ChartTableHeaderAttr = {
|
||||
tableHeaderFontColor: '#000000',
|
||||
tableTitleFontSize: 12,
|
||||
tableTitleHeight: 36,
|
||||
tableHeaderSort: false
|
||||
tableHeaderSort: false,
|
||||
showColTooltip: false,
|
||||
showRowTooltip: false
|
||||
}
|
||||
export const DEFAULT_TABLE_CELL: ChartTableCellAttr = {
|
||||
tableFontColor: '#000000',
|
||||
@ -339,7 +346,8 @@ export const DEFAULT_TABLE_CELL: ChartTableCellAttr = {
|
||||
tableItemFontSize: 12,
|
||||
tableItemHeight: 36,
|
||||
enableTableCrossBG: false,
|
||||
tableItemSubBgColor: '#EEEEEE'
|
||||
tableItemSubBgColor: '#EEEEEE',
|
||||
showTooltip: false
|
||||
}
|
||||
export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
|
||||
show: true,
|
||||
@ -359,35 +367,36 @@ export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
|
||||
|
||||
export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = {
|
||||
show: true,
|
||||
fontSize: '20',
|
||||
fontSize: 20,
|
||||
color: '#5470C6ff',
|
||||
hPosition: 'center',
|
||||
vPosition: 'center',
|
||||
isItalic: false,
|
||||
isBolder: true,
|
||||
fontFamily: 'Microsoft YaHei',
|
||||
letterSpace: '0',
|
||||
letterSpace: 0,
|
||||
fontShadow: false,
|
||||
|
||||
suffixEnable: true,
|
||||
suffix: '',
|
||||
suffixFontSize: '14',
|
||||
suffixFontSize: 14,
|
||||
suffixColor: '#5470C6ff',
|
||||
suffixIsItalic: false,
|
||||
suffixIsBolder: true,
|
||||
suffixFontFamily: 'Microsoft YaHei',
|
||||
suffixLetterSpace: '0',
|
||||
suffixLetterSpace: 0,
|
||||
suffixFontShadow: false
|
||||
}
|
||||
export const DEFAULT_INDICATOR_NAME_STYLE: ChartIndicatorNameStyle = {
|
||||
show: true,
|
||||
fontSize: '18',
|
||||
fontSize: 18,
|
||||
color: '#ffffffff',
|
||||
isItalic: false,
|
||||
isBolder: true,
|
||||
fontFamily: 'Microsoft YaHei',
|
||||
letterSpace: '0',
|
||||
fontShadow: false
|
||||
letterSpace: 0,
|
||||
fontShadow: false,
|
||||
nameValueSpacing: 0
|
||||
}
|
||||
|
||||
export const DEFAULT_TITLE_STYLE_BASE: ChartTextStyle = {
|
||||
@ -994,7 +1003,7 @@ export const CHART_FONT_FAMILY = [
|
||||
{ name: '楷体', value: 'KaiTi' }
|
||||
]
|
||||
|
||||
export const CHART_CONT_FAMILY_MAP = {
|
||||
export const CHART_FONT_FAMILY_MAP = {
|
||||
'Microsoft YaHei': 'Microsoft YaHei',
|
||||
SimSun: 'SimSun, "Songti SC", STSong',
|
||||
SimHei: 'SimHei, Helvetica',
|
||||
@ -1364,14 +1373,16 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
radarShape: 'polygon',
|
||||
mapStyle: 'normal',
|
||||
areaBorderColor: '#EBEEF5',
|
||||
suspension: true,
|
||||
areaBaseColor: '#ffffff',
|
||||
mapSymbolOpacity: 0.7,
|
||||
mapSymbolStrokeWidth: 2,
|
||||
mapSymbol: 'circle',
|
||||
mapSymbolSize: 20,
|
||||
radius: 80,
|
||||
innerRadius: 60
|
||||
innerRadius: 60,
|
||||
showZoom: true,
|
||||
zoomButtonColor: '#aaa',
|
||||
zoomBackground: '#fff'
|
||||
}
|
||||
|
||||
export const BASE_VIEW_CONFIG = {
|
||||
|
@ -25,7 +25,7 @@ export class Liquid extends G2PlotChartView<LiquidOptions, G2Liquid> {
|
||||
'background-overall-component': ['all'],
|
||||
'basic-style-selector': ['colors', 'alpha'],
|
||||
'label-selector': ['fontSize', 'color', 'labelFormatter'],
|
||||
'misc-selector': ['liquidShape', 'liquidMaxType', 'liquidMaxField'],
|
||||
'misc-selector': ['liquidShape', 'liquidSize', 'liquidMaxType', 'liquidMaxField'],
|
||||
'title-selector': [
|
||||
'title',
|
||||
'fontSize',
|
||||
|
@ -98,9 +98,10 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
options = this.setupOptions(chart, options, drawOption, geoJson)
|
||||
const view = new Choropleth(container, options)
|
||||
const dotLayer = this.getDotLayer(chart, geoJson, drawOption)
|
||||
this.configZoomButton(view)
|
||||
this.configZoomButton(chart, view)
|
||||
view.once('loaded', () => {
|
||||
view.addLayer(dotLayer)
|
||||
view.scene.map['keyboard'].disable()
|
||||
view.on('fillAreaLayer:click', (ev: MapMouseEvent) => {
|
||||
const data = ev.feature.properties
|
||||
action({
|
||||
@ -178,13 +179,6 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
const curAreaNameMapping = senior.areaMapping?.[areaId]
|
||||
handleGeoJson(geoJson, curAreaNameMapping)
|
||||
options.color = hexColorToRGBA(basicStyle.areaBaseColor, basicStyle.alpha)
|
||||
const suspension = basicStyle.suspension
|
||||
if (!suspension) {
|
||||
options = {
|
||||
...options,
|
||||
zoom: false
|
||||
}
|
||||
}
|
||||
if (!chart.data?.data?.length || !geoJson?.features?.length) {
|
||||
options.label && (options.label.field = 'name')
|
||||
return options
|
||||
@ -221,8 +215,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
this.configLabel,
|
||||
this.configStyle,
|
||||
this.configTooltip,
|
||||
this.configBasicStyle,
|
||||
this.configLegend
|
||||
this.configBasicStyle
|
||||
)(chart, options, extra)
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export const MAP_EDITOR_PROPERTY: EditorProperty[] = [
|
||||
|
||||
export const MAP_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
'basic-style-selector': ['colors', 'alpha', 'areaBorderColor', 'suspension'],
|
||||
'basic-style-selector': ['colors', 'alpha', 'areaBorderColor', 'zoom'],
|
||||
'title-selector': [
|
||||
'title',
|
||||
'fontSize',
|
||||
|
@ -22,8 +22,11 @@ const { t } = useI18n()
|
||||
* 地图
|
||||
*/
|
||||
export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
properties = MAP_EDITOR_PROPERTY
|
||||
propertyInner = MAP_EDITOR_PROPERTY_INNER
|
||||
properties: EditorProperty[] = [...MAP_EDITOR_PROPERTY, 'legend-selector']
|
||||
propertyInner: EditorPropertyInner = {
|
||||
...MAP_EDITOR_PROPERTY_INNER,
|
||||
'legend-selector': ['icon', 'fontSize', 'color']
|
||||
}
|
||||
axis = MAP_AXIS_TYPE
|
||||
axisConfig: AxisConfig = {
|
||||
xAxis: {
|
||||
@ -90,16 +93,14 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
active: { stroke: 'green', lineWidth: 1 }
|
||||
},
|
||||
tooltip: {},
|
||||
legend: {
|
||||
position: 'bottomleft'
|
||||
},
|
||||
// 禁用线上地图数据
|
||||
customFetchGeoData: () => null
|
||||
}
|
||||
options = this.setupOptions(chart, options, drawOption, geoJson)
|
||||
const view = new Choropleth(container, options)
|
||||
this.configZoomButton(view)
|
||||
this.configZoomButton(chart, view)
|
||||
view.once('loaded', () => {
|
||||
view.scene.map['keyboard'].disable()
|
||||
view.on('fillAreaLayer:click', (ev: MapMouseEvent) => {
|
||||
const data = ev.feature.properties
|
||||
action({
|
||||
@ -135,14 +136,6 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
|
||||
unknown: basicStyle.areaBaseColor
|
||||
}
|
||||
}
|
||||
const suspension = basicStyle.suspension
|
||||
if (!suspension) {
|
||||
options = {
|
||||
...options,
|
||||
legend: false,
|
||||
zoom: false
|
||||
}
|
||||
}
|
||||
if (!chart.data?.data?.length || !geoJson?.features?.length) {
|
||||
options.label && (options.label.field = 'name')
|
||||
return options
|
||||
|
@ -365,8 +365,8 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
|
||||
protected configAnalyse(chart: Chart, options: DualAxesOptions): DualAxesOptions {
|
||||
const list = getAnalyse(chart)
|
||||
const annotations = {
|
||||
value: filter(list, l => l.axisType === 'left'),
|
||||
valueExt: filter(list, l => l.axisType === 'right')
|
||||
value: filter(list, l => l.yAxisType === 'left'),
|
||||
valueExt: filter(list, l => l.yAxisType === 'right')
|
||||
}
|
||||
return { ...options, annotations }
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
return
|
||||
}
|
||||
const { colorFieldObj, sizeFieldObj, xFieldObj, yFieldObj } = this.getFieldObject(chart)
|
||||
if (!xFieldObj.id || !yFieldObj.id) {
|
||||
if (!xFieldObj.id || !yFieldObj.id || yFieldObj.id === xFieldObj.id) {
|
||||
return
|
||||
}
|
||||
const data: any[] = []
|
||||
@ -316,14 +316,10 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
tooltip: false
|
||||
}
|
||||
}
|
||||
xAxisTitle['show'] = true
|
||||
yAxisTitle['show'] = true
|
||||
yAxisExtTitle['show'] = true
|
||||
tooltipAttr.seriesTooltipFormatter?.push(xAxisTitle)
|
||||
const formatterMap = tooltipAttr.seriesTooltipFormatter
|
||||
?.filter(i => i.show)
|
||||
.reduce((pre, next) => {
|
||||
pre[next['originName']] = next
|
||||
pre[next['seriesId']] = next
|
||||
return pre
|
||||
}, {}) as Record<string, SeriesFormatter>
|
||||
const tooltip: ScatterOptions['tooltip'] = {
|
||||
@ -339,17 +335,21 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
originalItems
|
||||
?.filter(i => i.name !== xAxisTitle['originName'])
|
||||
.forEach(item => {
|
||||
const formatter = formatterMap[item.name]
|
||||
if (formatter) {
|
||||
const value =
|
||||
formatter.groupType === 'q'
|
||||
? valueFormatter(parseFloat(item.value as string), formatter.formatterCfg)
|
||||
: item.value
|
||||
const name = isEmpty(formatter.chartShowName)
|
||||
? formatter.name
|
||||
: formatter.chartShowName
|
||||
result.push({ color: item.color, name, value })
|
||||
}
|
||||
Object.keys(formatterMap).forEach(key => {
|
||||
if (formatterMap[key]['originName'] === item.name) {
|
||||
const formatter = formatterMap[key]
|
||||
if (formatter) {
|
||||
const value =
|
||||
formatter.groupType === 'q'
|
||||
? valueFormatter(parseFloat(item.value as string), formatter.formatterCfg)
|
||||
: item.value
|
||||
const name = isEmpty(formatter.chartShowName)
|
||||
? formatter.name
|
||||
: formatter.chartShowName
|
||||
result.push({ color: item.color, name, value })
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { getPadding } from '@/views/chart/components/js/panel/common/common_antv
|
||||
import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { DEFAULT_MISC } from '@/views/chart/components/editor/util/chart'
|
||||
|
||||
const { t } = useI18n()
|
||||
const DEFAULT_DATA = []
|
||||
@ -20,6 +21,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
'background-overall-component',
|
||||
'title-selector',
|
||||
'tooltip-selector',
|
||||
'misc-selector',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
]
|
||||
@ -38,6 +40,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
'letterSpace',
|
||||
'fontShadow'
|
||||
],
|
||||
'misc-selector': ['wordSizeRange', 'wordSpacing'],
|
||||
'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'seriesTooltipFormatter']
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'filter']
|
||||
@ -58,6 +61,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
if (chart?.data) {
|
||||
// data
|
||||
const data = chart.data.data
|
||||
const { misc } = parseJson(chart.customAttr)
|
||||
// options
|
||||
const initOptions: WordCloudOptions = {
|
||||
data: data,
|
||||
@ -66,9 +70,9 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
|
||||
colorField: 'field',
|
||||
wordStyle: {
|
||||
fontFamily: 'Verdana',
|
||||
fontSize: [8, 32],
|
||||
fontSize: (misc.wordSizeRange ?? DEFAULT_MISC.wordSizeRange) as [number, number],
|
||||
rotation: [0, 0],
|
||||
padding: 6
|
||||
padding: misc.wordSpacing ?? DEFAULT_MISC.wordSpacing
|
||||
},
|
||||
random: () => 0.5,
|
||||
appendPadding: getPadding(chart),
|
||||
|
@ -20,7 +20,8 @@ export const TABLE_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
'tableTitleHeight',
|
||||
'tableHeaderAlign',
|
||||
'showIndex',
|
||||
'indexLabel'
|
||||
'indexLabel',
|
||||
'showColTooltip'
|
||||
],
|
||||
'table-cell-selector': [
|
||||
'tableItemBgColor',
|
||||
@ -29,7 +30,8 @@ export const TABLE_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
'tableItemAlign',
|
||||
'tableItemHeight',
|
||||
'enableTableCrossBG',
|
||||
'tableItemSubBgColor'
|
||||
'tableItemSubBgColor',
|
||||
'showTooltip'
|
||||
],
|
||||
'title-selector': [
|
||||
'title',
|
||||
|
@ -169,6 +169,15 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
action(param)
|
||||
})
|
||||
|
||||
// hover
|
||||
const { showColTooltip } = customAttr.tableHeader
|
||||
if (showColTooltip) {
|
||||
newChart.on(S2Event.COL_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
}
|
||||
const { showTooltip } = customAttr.tableCell
|
||||
if (showTooltip) {
|
||||
newChart.on(S2Event.DATA_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
}
|
||||
// header resize
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev))
|
||||
// right click
|
||||
|
@ -164,6 +164,15 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
}
|
||||
action(param)
|
||||
})
|
||||
// hover
|
||||
const { showColTooltip } = customAttr.tableHeader
|
||||
if (showColTooltip) {
|
||||
newChart.on(S2Event.COL_CELL_HOVER, event => this.showTooltip(newChart, event))
|
||||
}
|
||||
const { showTooltip } = customAttr.tableCell
|
||||
if (showTooltip) {
|
||||
newChart.on(S2Event.DATA_CELL_HOVER, event => this.showTooltip(newChart, event, meta))
|
||||
}
|
||||
// header resize
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev))
|
||||
// right click
|
||||
|
@ -32,7 +32,9 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
'tableTitleFontSize',
|
||||
'tableHeaderFontColor',
|
||||
'tableTitleHeight',
|
||||
'tableHeaderAlign'
|
||||
'tableHeaderAlign',
|
||||
'showColTooltip',
|
||||
'showRowTooltip'
|
||||
],
|
||||
'table-total-selector': ['row', 'col'],
|
||||
'basic-style-selector': ['tableColumnMode', 'tableBorderColor', 'tableScrollBarColor', 'alpha']
|
||||
@ -185,7 +187,18 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
|
||||
// 开始渲染
|
||||
const s2 = new PivotSheet(containerDom, s2DataConfig, s2Options as unknown as S2Options)
|
||||
|
||||
// hover
|
||||
const { showColTooltip, showRowTooltip } = customAttr.tableHeader
|
||||
if (showColTooltip) {
|
||||
s2.on(S2Event.COL_CELL_HOVER, event => this.showTooltip(s2, event, meta))
|
||||
}
|
||||
if (showRowTooltip) {
|
||||
s2.on(S2Event.ROW_CELL_HOVER, event => this.showTooltip(s2, event, meta))
|
||||
}
|
||||
const { showTooltip } = customAttr.tableCell
|
||||
if (showTooltip) {
|
||||
s2.on(S2Event.DATA_CELL_HOVER, event => this.showTooltip(s2, event, meta))
|
||||
}
|
||||
// click
|
||||
s2.on(S2Event.DATA_CELL_CLICK, ev => this.dataCellClickAction(chart, ev, s2, action))
|
||||
s2.on(S2Event.ROW_CELL_CLICK, ev => this.headerCellClickAction(chart, ev, s2, action))
|
||||
|
@ -29,9 +29,9 @@ import { DOM } from '@antv/l7-utils'
|
||||
|
||||
export function getPadding(chart: Chart): number[] {
|
||||
if (chart.drill) {
|
||||
return [0, 10, 26, 10]
|
||||
return [0, 10, 22, 10]
|
||||
} else {
|
||||
return [0, 10, 14, 10]
|
||||
return [0, 10, 10, 10]
|
||||
}
|
||||
}
|
||||
// color,label,tooltip,axis,legend,background
|
||||
@ -273,9 +273,7 @@ export function getLegend(chart: Chart) {
|
||||
offsetY = 0
|
||||
} else if (l.vPosition === 'bottom') {
|
||||
if (chart.drill) {
|
||||
offsetY = -16
|
||||
} else {
|
||||
offsetY = -4
|
||||
offsetY = -12
|
||||
}
|
||||
} else {
|
||||
offsetY = 0
|
||||
@ -292,9 +290,9 @@ export function getLegend(chart: Chart) {
|
||||
offsetY = 0
|
||||
} else if (l.vPosition === 'bottom') {
|
||||
if (chart.drill) {
|
||||
offsetY = -22
|
||||
offsetY = -18
|
||||
} else {
|
||||
offsetY = -10
|
||||
offsetY = -6
|
||||
}
|
||||
} else {
|
||||
offsetY = 0
|
||||
@ -309,6 +307,7 @@ export function getLegend(chart: Chart) {
|
||||
marker: {
|
||||
symbol: legendSymbol
|
||||
},
|
||||
itemHeight: l.fontSize + 4,
|
||||
radio: false,
|
||||
pageNavigator: {
|
||||
marker: {
|
||||
@ -681,10 +680,10 @@ export function getAnalyse(chart: Chart) {
|
||||
const content =
|
||||
ele.name +
|
||||
' : ' +
|
||||
valueFormatter(value, ele.axisType === 'left' ? axisFormatterCfg : axisExtFormatterCfg)
|
||||
valueFormatter(value, ele.yAxisType === 'left' ? axisFormatterCfg : axisExtFormatterCfg)
|
||||
assistLine.push({
|
||||
type: 'line',
|
||||
axisType: ele.axisType,
|
||||
yAxisType: ele.yAxisType,
|
||||
start: ['start', value],
|
||||
end: ['end', value],
|
||||
style: {
|
||||
@ -694,15 +693,17 @@ export function getAnalyse(chart: Chart) {
|
||||
})
|
||||
assistLine.push({
|
||||
type: 'text',
|
||||
axisType: ele.axisType,
|
||||
yAxisType: ele.yAxisType,
|
||||
position: [
|
||||
(ele.axisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left' ? 'start' : 'end',
|
||||
(ele.yAxisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left'
|
||||
? 'start'
|
||||
: 'end',
|
||||
value
|
||||
],
|
||||
content: content,
|
||||
offsetY: -2,
|
||||
offsetX:
|
||||
(ele.axisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left'
|
||||
(ele.yAxisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left'
|
||||
? 2
|
||||
: -10 * (content.length - 2),
|
||||
style: {
|
||||
@ -898,9 +899,32 @@ export function getTooltipSeriesTotalMap(data: any[]): Record<string, number> {
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
export function configL7Legend(): LegendOptions {
|
||||
const LEGEND_SHAPE_STYLE_MAP = {
|
||||
circle: {
|
||||
borderRadius: '50%'
|
||||
},
|
||||
square: {},
|
||||
triangle: {
|
||||
borderLeft: '5px solid transparent',
|
||||
borderRight: '5px solid transparent',
|
||||
borderBottom: '10px solid var(--bgColor)',
|
||||
background: 'unset'
|
||||
},
|
||||
diamond: {
|
||||
transform: 'rotate(45deg)'
|
||||
}
|
||||
}
|
||||
export function configL7Legend(chart: Chart): LegendOptions | false {
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
|
||||
return false
|
||||
}
|
||||
const { legend } = parseJson(chart.customStyle)
|
||||
if (!legend.show) {
|
||||
return false
|
||||
}
|
||||
return {
|
||||
position: 'bottomleft',
|
||||
customContent: (_: string, items: CategoryLegendListItem[]) => {
|
||||
const showItems = items?.length > 30 ? items.slice(0, 30) : items
|
||||
if (showItems?.length) {
|
||||
@ -923,11 +947,22 @@ export function configL7Legend(): LegendOptions {
|
||||
|
||||
const domStr = substitute(ITEM_TPL, substituteObj)
|
||||
const itemDom = createDom(domStr)
|
||||
// 给 legend 形状用的
|
||||
itemDom.style.setProperty('--bgColor', item.color)
|
||||
listDom.appendChild(itemDom)
|
||||
})
|
||||
return listDom
|
||||
}
|
||||
return ''
|
||||
},
|
||||
domStyles: {
|
||||
'l7plot-legend__category-value': {
|
||||
fontSize: legend.fontSize + 'px',
|
||||
color: legend.color
|
||||
},
|
||||
'l7plot-legend__category-marker': {
|
||||
...LEGEND_SHAPE_STYLE_MAP[legend.icon]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -942,12 +977,18 @@ class CustomZoom extends Zoom {
|
||||
this.zoomIn
|
||||
)
|
||||
const resetBtnIconText = createL7Icon('l7-icon-round')
|
||||
this['createButton'](resetBtnIconText, 'Reset', 'l7-button-control', container, () => {
|
||||
this.mapsService.setZoomAndCenter(
|
||||
this.controlOption['initZoom'],
|
||||
this.controlOption['center']
|
||||
)
|
||||
})
|
||||
this['zoomResetButton'] = this['createButton'](
|
||||
resetBtnIconText,
|
||||
'Reset',
|
||||
'l7-button-control',
|
||||
container,
|
||||
() => {
|
||||
this.mapsService.setZoomAndCenter(
|
||||
this.controlOption['initZoom'],
|
||||
this.controlOption['center']
|
||||
)
|
||||
}
|
||||
)
|
||||
if (this.controlOption.showZoom) {
|
||||
this['zoomNumDiv'] = this['createButton'](
|
||||
'0',
|
||||
@ -963,19 +1004,44 @@ class CustomZoom extends Zoom {
|
||||
container,
|
||||
this.zoomOut
|
||||
)
|
||||
const { buttonColor, buttonBackground } = this.controlOption as any
|
||||
if (buttonColor) {
|
||||
const elements = [
|
||||
this.controlOption.zoomInText,
|
||||
this.controlOption.zoomOutText,
|
||||
resetBtnIconText
|
||||
] as HTMLElement[]
|
||||
setStyle(elements, 'fill', buttonColor)
|
||||
}
|
||||
const elements = [this['zoomResetButton'], this['zoomInButton'], this['zoomOutButton']]
|
||||
if (buttonBackground) {
|
||||
setStyle(elements, 'background', buttonBackground)
|
||||
}
|
||||
setStyle(elements, 'border-bottom', 'none')
|
||||
this['updateDisabled']()
|
||||
}
|
||||
}
|
||||
export function configL7Zoom(plot: L7Plot<PlotOptions>) {
|
||||
const options = plot.options
|
||||
if (options.zoom === false) {
|
||||
export function configL7Zoom(chart: Chart, plot: L7Plot<PlotOptions>) {
|
||||
const { basicStyle } = parseJson(chart.customAttr)
|
||||
if (
|
||||
(basicStyle.suspension === false && basicStyle.showZoom === undefined) ||
|
||||
basicStyle.showZoom === false
|
||||
) {
|
||||
return
|
||||
}
|
||||
plot.once('loaded', () => {
|
||||
const zoomOptions = {
|
||||
initZoom: plot.scene.getZoom(),
|
||||
center: plot.scene.getCenter()
|
||||
center: plot.scene.getCenter(),
|
||||
buttonColor: basicStyle.zoomButtonColor,
|
||||
buttonBackground: basicStyle.zoomBackground
|
||||
} as any
|
||||
plot.scene.addControl(new CustomZoom(zoomOptions))
|
||||
})
|
||||
}
|
||||
|
||||
function setStyle(elements: HTMLElement[], styleProp: string, value) {
|
||||
elements.forEach(e => {
|
||||
e.style[styleProp] = value
|
||||
})
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
ChartLibraryType
|
||||
} from '@/views/chart/components/js/panel/types'
|
||||
import { cloneDeep, defaultsDeep } from 'lodash-es'
|
||||
import { ChoroplethOptions } from '@antv/l7plot/dist/esm/plots/choropleth'
|
||||
import { parseJson } from '@/views/chart/components/js/util'
|
||||
|
||||
export interface L7PlotDrawOptions<P> extends AntVDrawOptions<P> {
|
||||
@ -47,12 +46,12 @@ export abstract class L7PlotChartView<
|
||||
defaultsDeep(options.tooltip, tooltip)
|
||||
return options
|
||||
}
|
||||
protected configLegend(_: Chart, options: ChoroplethOptions) {
|
||||
const legend = configL7Legend()
|
||||
defaultsDeep(options.legend, legend)
|
||||
protected configLegend(chart: Chart, options: O): O {
|
||||
const legend = configL7Legend(chart)
|
||||
defaultsDeep(options, { legend })
|
||||
return options
|
||||
}
|
||||
protected configEmptyDataStrategy(chart: Chart, options: ChoroplethOptions): ChoroplethOptions {
|
||||
protected configEmptyDataStrategy(chart: Chart, options: O): O {
|
||||
const { functionCfg } = parseJson(chart.senior)
|
||||
const emptyDataStrategy = functionCfg.emptyDataStrategy
|
||||
if (!emptyDataStrategy || emptyDataStrategy === 'breakLine') {
|
||||
@ -75,8 +74,8 @@ export abstract class L7PlotChartView<
|
||||
return options
|
||||
}
|
||||
|
||||
protected configZoomButton(plot: P) {
|
||||
configL7Zoom(plot)
|
||||
protected configZoomButton(chart: Chart, plot: P) {
|
||||
configL7Zoom(chart, plot)
|
||||
}
|
||||
protected constructor(name: string, defaultData?: any[]) {
|
||||
super(ChartLibraryType.L7_PLOT, name)
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
AntVDrawOptions,
|
||||
ChartLibraryType
|
||||
} from '@/views/chart/components/js/panel/types'
|
||||
import { S2Theme, SpreadSheet, Style, S2Options } from '@antv/s2'
|
||||
import { S2Theme, SpreadSheet, Style, S2Options, Meta } from '@antv/s2'
|
||||
import {
|
||||
configHeaderInteraction,
|
||||
configTooltip,
|
||||
@ -13,6 +13,7 @@ import {
|
||||
handleTableEmptyStrategy
|
||||
} from '@/views/chart/components/js/panel/common/common_table'
|
||||
import '@antv/s2/dist/style.min.css'
|
||||
import { find } from 'lodash-es'
|
||||
|
||||
declare interface PageInfo {
|
||||
currentPage: number
|
||||
@ -52,4 +53,40 @@ export abstract class S2ChartView<P extends SpreadSheet> extends AntVAbstractCha
|
||||
protected configConditions(chart: Chart) {
|
||||
return getConditions(chart)
|
||||
}
|
||||
|
||||
protected showTooltip(s2Instance: P, event, metaConfig: Meta[]) {
|
||||
const cell = s2Instance.getCell(event.target)
|
||||
const meta = cell.getMeta()
|
||||
let content = ''
|
||||
let field
|
||||
switch (cell.cellType) {
|
||||
case 'dataCell':
|
||||
field = find(metaConfig, item => item.field === meta.valueField)
|
||||
if (meta.fieldValue) {
|
||||
content = field?.formatter?.(meta.fieldValue)
|
||||
}
|
||||
break
|
||||
case 'rowCell':
|
||||
case 'colCell':
|
||||
content = meta.label
|
||||
field = find(metaConfig, item => item.field === content)
|
||||
if (field) {
|
||||
content = field.name
|
||||
}
|
||||
break
|
||||
}
|
||||
if (!content) {
|
||||
return
|
||||
}
|
||||
event.s2Instance = s2Instance
|
||||
s2Instance.showTooltip({
|
||||
position: {
|
||||
x: event.clientX,
|
||||
y: event.clientY
|
||||
},
|
||||
content,
|
||||
meta,
|
||||
event
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import ChartError from '@/views/chart/components/views/components/ChartError.vue
|
||||
import { BASE_VIEW_CONFIG } from '../../editor/util/chart'
|
||||
import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
import { trackBarStyleCheck } from '@/utils/canvasUtils'
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc } = storeToRefs(dvMainStore)
|
||||
@ -202,8 +203,13 @@ const action = param => {
|
||||
trackClick(trackMenu.value[0])
|
||||
} else {
|
||||
// 图表关联多个事件
|
||||
state.trackBarStyle.left = param.x - 50 + 'px'
|
||||
state.trackBarStyle.top = param.y + 10 + 'px'
|
||||
const barStyleTemp = {
|
||||
left: param.x - 50,
|
||||
top: param.y + 10
|
||||
}
|
||||
trackBarStyleCheck(props.element, barStyleTemp, props.scale)
|
||||
state.trackBarStyle.left = barStyleTemp.left + 'px'
|
||||
state.trackBarStyle.top = barStyleTemp.top + 'px'
|
||||
viewTrack.value.trackButtonClick()
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import { BASE_VIEW_CONFIG } from '../../editor/util/chart'
|
||||
import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { trackBarStyleCheck } from '@/utils/canvasUtils'
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc } = storeToRefs(dvMainStore)
|
||||
@ -247,8 +248,13 @@ const action = param => {
|
||||
trackClick(trackMenu.value[0])
|
||||
} else {
|
||||
// 图表关联多个事件
|
||||
state.trackBarStyle.left = param.x - 50 + 'px'
|
||||
state.trackBarStyle.top = param.y + 10 + 'px'
|
||||
const barStyleTemp = {
|
||||
left: param.x - 50,
|
||||
top: param.y + 10
|
||||
}
|
||||
trackBarStyleCheck(props.element, barStyleTemp, props.scale)
|
||||
state.trackBarStyle.left = barStyleTemp.left + 'px'
|
||||
state.trackBarStyle.top = barStyleTemp.top + 'px'
|
||||
viewTrack.value.trackButtonClick()
|
||||
}
|
||||
}
|
||||
@ -463,6 +469,7 @@ const autoHeightStyle = computed(() => {
|
||||
}
|
||||
.table-page-info {
|
||||
position: relative;
|
||||
padding-left: 4px;
|
||||
margin: 4px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { hexColorToRGBA } from '@/views/chart/components/js/util.js'
|
||||
import {
|
||||
CHART_CONT_FAMILY_MAP,
|
||||
CHART_FONT_FAMILY_MAP,
|
||||
DEFAULT_TITLE_STYLE
|
||||
} from '@/views/chart/components/editor/util/chart'
|
||||
import DrillPath from '@/views/chart/components/views/components/DrillPath.vue'
|
||||
@ -153,13 +153,13 @@ const trackMenu = computed<Array<string>>(() => {
|
||||
})
|
||||
|
||||
const hasLinkIcon = computed(() => {
|
||||
return trackMenu.value.indexOf('linkage') > -1 || trackMenu.value.indexOf('linkageAndDrill')
|
||||
return trackMenu.value.indexOf('linkage') > -1 || trackMenu.value.indexOf('linkageAndDrill') > -1
|
||||
})
|
||||
const hasJumpIcon = computed(() => {
|
||||
return trackMenu.value.indexOf('jump') > -1 && !mobileInPc.value
|
||||
})
|
||||
const hasDrillIcon = computed(() => {
|
||||
return trackMenu.value.indexOf('drill') > -1 || trackMenu.value.indexOf('linkageAndDrill')
|
||||
return trackMenu.value.indexOf('drill') > -1 || trackMenu.value.indexOf('linkageAndDrill') > -1
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
@ -250,7 +250,7 @@ const initTitle = () => {
|
||||
state.title_class.fontWeight = customStyle.text.isBolder ? 'bold' : 'normal'
|
||||
|
||||
state.title_class.fontFamily = customStyle.text.fontFamily
|
||||
? CHART_CONT_FAMILY_MAP[customStyle.text.fontFamily]
|
||||
? CHART_FONT_FAMILY_MAP[customStyle.text.fontFamily]
|
||||
: DEFAULT_TITLE_STYLE.fontFamily
|
||||
state.title_class.letterSpacing =
|
||||
(customStyle.text.letterSpace
|
||||
@ -587,9 +587,9 @@ const toolTip = computed(() => {
|
||||
|
||||
const marginBottom = computed<string | 0>(() => {
|
||||
if (titleShow.value || trackMenu.value.length > 0 || state.title_remark.show) {
|
||||
return 8 * scale.value + 'px'
|
||||
return 12 * scale.value + 'px'
|
||||
}
|
||||
return 0
|
||||
return 12
|
||||
})
|
||||
|
||||
const iconSize = computed<string>(() => {
|
||||
@ -686,6 +686,7 @@ const iconSize = computed<string>(() => {
|
||||
:view="view"
|
||||
:scale="scale"
|
||||
:show-position="showPosition"
|
||||
:element="element"
|
||||
v-else-if="showChartView(ChartLibraryType.S2)"
|
||||
ref="chartComponent"
|
||||
@onChartClick="chartClick"
|
||||
|
@ -317,10 +317,14 @@ const addOperation = (
|
||||
const baseUrl =
|
||||
curCanvasType.value === 'dataV' ? '#/dvCanvas?opt=create' : '#/dashboard?opt=create'
|
||||
let newWindow = null
|
||||
let embeddedBaseUrl = ''
|
||||
if (isDataEaseBi.value) {
|
||||
embeddedBaseUrl = embeddedStore.baseUrl
|
||||
}
|
||||
if (data?.id) {
|
||||
newWindow = window.open(baseUrl + `&pid=${data.id}`, '_blank')
|
||||
newWindow = window.open(embeddedBaseUrl + baseUrl + `&pid=${data.id}`, '_blank')
|
||||
} else {
|
||||
newWindow = window.open(baseUrl, '_blank')
|
||||
newWindow = window.open(embeddedBaseUrl + baseUrl, '_blank')
|
||||
}
|
||||
initOpenHandler(newWindow)
|
||||
} else if (cmd === 'newFromTemplate') {
|
||||
@ -463,19 +467,14 @@ defineExpose({
|
||||
<el-tooltip content="新建文件夹" placement="top" effect="dark">
|
||||
<el-icon
|
||||
class="custom-icon btn"
|
||||
:style="{ marginRight: isDataEaseBi ? 0 : '20px' }"
|
||||
style="margin-right: 20px"
|
||||
@click="addOperation('newFolder', null, 'folder')"
|
||||
>
|
||||
<Icon name="dv-new-folder" />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip
|
||||
v-if="!isDataEaseBi"
|
||||
:content="newResourceLabel"
|
||||
placement="top"
|
||||
effect="dark"
|
||||
>
|
||||
<el-tooltip :content="newResourceLabel" placement="top" effect="dark">
|
||||
<el-dropdown popper-class="menu-outer-dv_popper" trigger="hover">
|
||||
<el-icon class="custom-icon btn" @click="addOperation('newLeaf', null, 'leaf', true)">
|
||||
<Icon name="icon_file-add_outlined" />
|
||||
|
@ -9,11 +9,11 @@ const dvMainStore = dvMainStoreWithOut()
|
||||
|
||||
const checkItemPosition = component => {
|
||||
component.x = 1
|
||||
component.sizeX = 36
|
||||
component.sizeX = 72
|
||||
component.y = dvMainStore.componentData.reduce((pre, next) => {
|
||||
return Math.max(pre, next.y + next.sizeY)
|
||||
}, 1)
|
||||
component.sizeY = 10
|
||||
component.sizeY = 20
|
||||
}
|
||||
|
||||
const hanedleMessage = event => {
|
||||
|
@ -9,15 +9,15 @@
|
||||
</el-tooltip>
|
||||
<el-row v-show="state.asideActive" style="padding: 24px 12px 0">
|
||||
<el-row style="align-items: center">
|
||||
<span class="custom-breadcrumb-item" @click="closePreview()">{{
|
||||
t('visualization.template_preview')
|
||||
}}</span>
|
||||
<span class="custom-breadcrumb-item" @click="closePreview()">模版中心</span>
|
||||
<el-icon><ArrowRight /></el-icon> <span class="custom-breadcrumb-item-to">预览</span>
|
||||
|
||||
<el-tooltip class="box-item" effect="dark" content="收起" placement="right">
|
||||
<el-icon class="insert-retract" @click="asideActiveChange(false)">
|
||||
<Icon name="market-retract"></Icon>
|
||||
</el-icon>
|
||||
<div @click="asideActiveChange(false)" class="insert-retract">
|
||||
<el-icon>
|
||||
<Icon name="icon_left_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-row>
|
||||
<el-row class="margin-top16 search-area">
|
||||
@ -499,34 +499,44 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-side-tree {
|
||||
position: absolute;
|
||||
border: 1px solid #dee0e3;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
.ed-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.insert-retract {
|
||||
position: absolute;
|
||||
left: 176px;
|
||||
left: 182px;
|
||||
top: 2px;
|
||||
display: inline-block;
|
||||
font-size: 34px;
|
||||
font-weight: 400 !important;
|
||||
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
border: 1px solid #dee0e3;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
color: #646a73;
|
||||
-webkit-appearance: none;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
transition: 0.1s;
|
||||
border-radius: 3px;
|
||||
|
||||
&:active {
|
||||
color: #000;
|
||||
border-color: #3a8ee6;
|
||||
outline: 0;
|
||||
}
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0px 5px 10px 0px #1f23291a;
|
||||
|
||||
&:hover {
|
||||
color: #3a8ee6;
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
.ed-icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { reactive, computed, ref, nextTick, inject, type Ref, watch } from 'vue'
|
||||
import { reactive, computed, ref, nextTick, inject, type Ref, watch, unref } from 'vue'
|
||||
import AddSql from './AddSql.vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import zeroNodeImg from '@/assets/img/drag.png'
|
||||
@ -108,6 +108,23 @@ const dfsNodeNameList = (list, arr) => {
|
||||
})
|
||||
}
|
||||
|
||||
const dfsForDsId = (arr, datasourceId) => {
|
||||
return arr.every(ele => {
|
||||
if (ele.children?.length) {
|
||||
return dfsForDsId(ele.children, datasourceId)
|
||||
}
|
||||
return ele.datasourceId === datasourceId || !ele.datasourceId
|
||||
})
|
||||
}
|
||||
|
||||
const crossDatasources = computed(() => {
|
||||
const { datasourceId, children = [] } = state.nodeList[0] || {}
|
||||
if (datasourceId && !!children.length) {
|
||||
return !dfsForDsId(children, datasourceId)
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
let isUpdate = false
|
||||
|
||||
watch(
|
||||
@ -234,6 +251,8 @@ const changeNodeFields = val => {
|
||||
}
|
||||
|
||||
const closeEditUnion = () => {
|
||||
nodeField.value = []
|
||||
currentNode.value = null
|
||||
const [fir] = state.nodeList
|
||||
if (fir.isShadow) {
|
||||
delete fir.isShadow
|
||||
@ -831,14 +850,19 @@ const notConfirm = () => {
|
||||
confirm()
|
||||
}
|
||||
|
||||
const getNodeList = () => {
|
||||
return cloneDeep(unref(state.nodeList))
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
nodeNameList,
|
||||
nodeList: state.nodeList,
|
||||
getNodeList,
|
||||
setStateBack,
|
||||
notConfirm,
|
||||
dfsNodeFieldBack,
|
||||
initState,
|
||||
setChangeStatus
|
||||
setChangeStatus,
|
||||
crossDatasources
|
||||
})
|
||||
|
||||
const handleActiveNode = ele => {
|
||||
|
@ -120,7 +120,9 @@ const handleChange = () => {
|
||||
|
||||
<template>
|
||||
<el-popover
|
||||
popper-class="menu-more_popper_one"
|
||||
:popper-class="
|
||||
options.length === 6 ? 'menu-more_popper_one menu-more_popper_six' : 'menu-more_popper_one'
|
||||
"
|
||||
:persistent="false"
|
||||
ref="popover"
|
||||
placement="right"
|
||||
@ -173,6 +175,9 @@ const handleChange = () => {
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.menu-more_popper_six > :first-child > :first-child > :first-child {
|
||||
height: 210px;
|
||||
}
|
||||
.menu-more_popper_one {
|
||||
padding: 0 !important;
|
||||
background: transparent !important;
|
||||
|
@ -318,7 +318,7 @@ watch(searchTable, val => {
|
||||
const editeSave = () => {
|
||||
const union = []
|
||||
loading.value = true
|
||||
dfsNodeList(union, datasetDrag.value.nodeList)
|
||||
dfsNodeList(union, datasetDrag.value.getNodeList())
|
||||
saveDatasetTree({
|
||||
...nodeInfo,
|
||||
name: datasetName.value,
|
||||
@ -448,7 +448,7 @@ const deleteField = item => {
|
||||
callback: (action: Action) => {
|
||||
if (action === 'confirm') {
|
||||
delFieldById([item.id])
|
||||
datasetDrag.value.dfsNodeFieldBack(datasetDrag.value.nodeList, item)
|
||||
datasetDrag.value.dfsNodeFieldBack(datasetDrag.value.getNodeList(), item)
|
||||
ElMessage({
|
||||
message: t('chart.delete_success'),
|
||||
type: 'success'
|
||||
@ -671,7 +671,6 @@ const addComplete = () => {
|
||||
const state = reactive({
|
||||
nodeNameList: [],
|
||||
editArr: [],
|
||||
nodeList: [],
|
||||
dataSourceList: [],
|
||||
tableData: [],
|
||||
fieldCollapse: ['dimension', 'quota']
|
||||
@ -750,7 +749,7 @@ const fieldUnion = ref()
|
||||
|
||||
const setFieldAll = () => {
|
||||
const arr = []
|
||||
dfsFields(arr, datasetDrag.value.nodeList)
|
||||
dfsFields(arr, datasetDrag.value.getNodeList())
|
||||
const delIdArr = getDelIdArr(arr, allfields.value)
|
||||
allfields.value = diffArr(arr, allfields.value)
|
||||
delFieldById(delIdArr)
|
||||
@ -815,6 +814,10 @@ const mouseupDrag = () => {
|
||||
dom.removeEventListener('mousemove', calculateWidth)
|
||||
dom.removeEventListener('mousemove', calculateHeight)
|
||||
}
|
||||
|
||||
const crossDatasources = computed(() => {
|
||||
return datasetDrag.value?.crossDatasources
|
||||
})
|
||||
const calculateWidth = (e: MouseEvent) => {
|
||||
if (e.pageX < 240) {
|
||||
LeftWidth.value = 240
|
||||
@ -920,7 +923,7 @@ const resetAllfieldsId = arr => {
|
||||
|
||||
const resetAllfieldsUnionId = (arr, idMap) => {
|
||||
let strUnion = JSON.stringify(arr) as string
|
||||
let strNodeList = JSON.stringify(toRaw(datasetDrag.value.nodeList)) as string
|
||||
let strNodeList = JSON.stringify(toRaw(datasetDrag.value.getNodeList())) as string
|
||||
let strAllfields = JSON.stringify(unref(allfields.value)) as string
|
||||
Object.entries(idMap).forEach(([key, value]) => {
|
||||
strUnion = strUnion.replaceAll(key, value as string)
|
||||
@ -938,7 +941,7 @@ const datasetSave = () => {
|
||||
return
|
||||
}
|
||||
let union = []
|
||||
dfsNodeList(union, datasetDrag.value.nodeList)
|
||||
dfsNodeList(union, datasetDrag.value.getNodeList())
|
||||
const pid = route.query.pid || nodeInfo.pid
|
||||
if (!union.length) {
|
||||
ElMessage.error('数据集不能为空')
|
||||
@ -965,7 +968,7 @@ const datasetPreviewLoading = ref(false)
|
||||
const datasetPreview = () => {
|
||||
if (datasetPreviewLoading.value) return
|
||||
const arr = []
|
||||
dfsNodeList(arr, datasetDrag.value.nodeList)
|
||||
dfsNodeList(arr, datasetDrag.value.getNodeList())
|
||||
datasetPreviewLoading.value = true
|
||||
getPreviewData({ union: arr, allFields: allfields.value })
|
||||
.then(res => {
|
||||
@ -1328,6 +1331,12 @@ const getDsIconName = data => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="drag-right" :style="{ width: `calc(100vw - ${showLeft ? LeftWidth : 0}px)` }">
|
||||
<div v-if="crossDatasources" class="different-datasource">
|
||||
<el-icon>
|
||||
<Icon name="icon_warning_colorful"></Icon>
|
||||
</el-icon>
|
||||
您正在进行跨数据源的表关联,请确保使用calcite的标准语法和函数,否则会导致数据集报错
|
||||
</div>
|
||||
<dataset-union
|
||||
@join-editor="joinEditor"
|
||||
@changeUpdate="changeUpdate"
|
||||
@ -1343,7 +1352,9 @@ const getDsIconName = data => {
|
||||
<div
|
||||
class="sql-result"
|
||||
:style="{
|
||||
height: sqlResultHeight ? `${sqlResultHeight}px` : `calc(100% - ${dragHeight}px)`
|
||||
height: sqlResultHeight
|
||||
? `${crossDatasources ? sqlResultHeight - 40 : sqlResultHeight}px`
|
||||
: `calc(100% - ${crossDatasources ? dragHeight + 40 : dragHeight}px)`
|
||||
}"
|
||||
>
|
||||
<div class="sql-title">
|
||||
@ -2101,6 +2112,23 @@ const getDsIconName = data => {
|
||||
display: flex;
|
||||
.drag-right {
|
||||
height: calc(100vh - 56px);
|
||||
.different-datasource {
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
background: #ffe7cc;
|
||||
color: #1f2329;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
|
||||
.ed-icon {
|
||||
font-size: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
.sql-result {
|
||||
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
|
||||
font-size: 14px;
|
||||
|
@ -320,6 +320,34 @@ function clear_images() {
|
||||
fi
|
||||
}
|
||||
function backup() {
|
||||
need_stop=0
|
||||
if [[ -z $1 ]];then
|
||||
echo "如需备份 DataEase 数据,建议您先停止 DataEase 服务,以保证备份数据的完整性。"
|
||||
read -r -p "即将备份 DataEase 数据,是否需要停止 DataEase 服务? [Y/n] " input
|
||||
|
||||
case $input in
|
||||
[yY][eE][sS]|[yY])
|
||||
echo "Yes"
|
||||
need_stop=1
|
||||
;;
|
||||
[nN][oO]|[nN])
|
||||
echo "No"
|
||||
;;
|
||||
*)
|
||||
echo "无效输入..."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
elif [[ "$1" == "stop" ]];then
|
||||
need_stop=1
|
||||
fi
|
||||
|
||||
if [[ $need_stop == 1 ]];then
|
||||
service dataease stop
|
||||
else
|
||||
echo "不停服进行备份"
|
||||
fi
|
||||
|
||||
backup_file_name=dataease-backup-$(date +%Y%m%d)_$(date +%H%M%S).tar.gz
|
||||
tar --exclude=logs/dataease -zcf $backup_file_name -C $DE_RUNNING_BASE .
|
||||
if [ $? -ne 0 ]; then
|
||||
@ -328,6 +356,10 @@ function backup() {
|
||||
else
|
||||
echo "备份成功,备份文件 : $backup_file_name"
|
||||
fi
|
||||
|
||||
if [[ $need_stop == 1 ]];then
|
||||
service dataease start
|
||||
fi
|
||||
}
|
||||
function restore() {
|
||||
if [[ -z $target ]];then
|
||||
@ -367,7 +399,7 @@ function main() {
|
||||
upgrade
|
||||
;;
|
||||
backup)
|
||||
backup
|
||||
backup $target
|
||||
;;
|
||||
restore)
|
||||
restore $target
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.dataease.api.chart.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
@ -15,7 +16,8 @@ public class ChartSeniorAssistDTO {
|
||||
private Long fieldId;
|
||||
private String summary;
|
||||
private String axis;
|
||||
private String axisType;
|
||||
@JsonProperty("yAxisType")
|
||||
private String yAxisType;
|
||||
private String value;
|
||||
private String lineType;
|
||||
private String color;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.dataease.api.visualization;
|
||||
|
||||
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
|
||||
import io.dataease.api.visualization.dto.VisualizationComponentDTO;
|
||||
import io.dataease.api.visualization.dto.VisualizationLinkJumpDTO;
|
||||
import io.dataease.api.visualization.request.VisualizationLinkJumpBaseRequest;
|
||||
import io.dataease.api.visualization.response.VisualizationLinkJumpBaseResponse;
|
||||
@ -46,7 +47,7 @@ public interface VisualizationLinkJumpApi {
|
||||
|
||||
@GetMapping("/viewTableDetailList/{dvId}")
|
||||
@Operation(summary = "查询跳转明细")
|
||||
List<VisualizationViewTableVO> viewTableDetailList(@PathVariable Long dvId);
|
||||
VisualizationComponentDTO viewTableDetailList(@PathVariable Long dvId);
|
||||
|
||||
@PostMapping("/updateJumpSetActive")
|
||||
@Operation(summary = "更新跳转信息可用状态")
|
||||
|
@ -0,0 +1,23 @@
|
||||
package io.dataease.api.visualization.dto;
|
||||
|
||||
import io.dataease.api.visualization.vo.VisualizationViewTableVO;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author : WangJiaHao
|
||||
* @date : 2024/4/18 17:14
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class VisualizationComponentDTO {
|
||||
|
||||
private String bashComponentData;
|
||||
|
||||
List<VisualizationViewTableVO> visualizationViewTables;
|
||||
|
||||
}
|