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

This commit is contained in:
fit2cloud-chenyw 2024-04-23 15:32:46 +08:00
commit db87205e6b
87 changed files with 2003 additions and 1110 deletions

View File

@ -865,7 +865,7 @@ public class ChartDataManage {
return list; 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()) { if (null == assistLineCfg || !assistLineCfg.isEnable()) {
return list; return list;
} }

View File

@ -200,7 +200,7 @@ public class DatasetDataManage {
// build query sql // build query sql
SQLMeta sqlMeta = new SQLMeta(); SQLMeta sqlMeta = new SQLMeta();
Table2SQLObj.table2sqlobj(sqlMeta, null, "(" + sql + ")", crossDs); 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); WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, fields, crossDs, dsMap);
Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap); Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap);
String querySQL; String querySQL;
@ -459,7 +459,7 @@ public class DatasetDataManage {
rowPermissionsTree = permissionManage.getRowPermissionsTree(datasetGroupInfoDTO.getId(), user.getUserId()); 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); WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, fields, crossDs, dsMap);
Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap); Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap);
String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, true, 0, 1000); String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, true, 0, 1000);
@ -585,7 +585,7 @@ public class DatasetDataManage {
datasetGroupInfoDTO.setSortFields(Collections.singletonList(deSortField)); 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); WhereTree2Str.transFilterTrees(sqlMeta, rowPermissionsTree, fields, crossDs, dsMap);
Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap); Order2SQLObj.getOrders(sqlMeta, fields, datasetGroupInfoDTO.getSortFields(), crossDs, dsMap);
String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, 0, 1000); String querySQL = SQLProvider.createQuerySQLWithLimit(sqlMeta, false, needOrder, false, 0, 1000);

View File

@ -47,7 +47,7 @@ public class SQLConstants {
public static final String FIELD_NAME = "%s.`%s`"; 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)"; public static final String UNIX_TIMESTAMP = "DE_UNIX_TIMESTAMP(%s)";

View File

@ -45,6 +45,9 @@ public class CustomWhere2Str {
// 给计算字段处加一个占位符后续SQL方言转换后再替换 // 给计算字段处加一个占位符后续SQL方言转换后再替换
originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId());
fieldsDialect.put(originName, calcFieldExp); fieldsDialect.put(originName, calcFieldExp);
if (isCross) {
originName = calcFieldExp;
}
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) { } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) {
originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName()); originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName());
} else { } else {
@ -86,18 +89,17 @@ public class CustomWhere2Str {
res.add("(" + whereName + " IN ('" + String.join("','", request.getEnumCheckField()) + "'))"); res.add("(" + whereName + " IN ('" + String.join("','", request.getEnumCheckField()) + "'))");
} }
} else { } else {
if (field.getDeType() == 1) {
// 规定几种日期格式一一匹配匹配到就是该格式
whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName);
}
List<ChartCustomFilterItemDTO> filter = request.getFilter(); List<ChartCustomFilterItemDTO> filter = request.getFilter();
for (ChartCustomFilterItemDTO filterItemDTO : filter) { for (ChartCustomFilterItemDTO filterItemDTO : filter) {
String value = filterItemDTO.getValue(); String value = filterItemDTO.getValue();
String whereTerm = Utils.transFilterTerm(filterItemDTO.getTerm()); String whereTerm = Utils.transFilterTerm(filterItemDTO.getTerm());
String whereValue = ""; String whereValue = "";
// String whereNameReal;
if (field.getDeType() == 1) {
// 规定几种日期格式一一匹配匹配到就是该格式
whereName = String.format(SQLConstants.UNIX_TIMESTAMP, whereName);
}
if (StringUtils.equalsIgnoreCase(filterItemDTO.getTerm(), "null")) { if (StringUtils.equalsIgnoreCase(filterItemDTO.getTerm(), "null")) {
whereValue = ""; whereValue = "";
} else if (StringUtils.equalsIgnoreCase(filterItemDTO.getTerm(), "not_null")) { } else if (StringUtils.equalsIgnoreCase(filterItemDTO.getTerm(), "not_null")) {
@ -113,12 +115,12 @@ public class CustomWhere2Str {
} else { } else {
// 如果是时间字段过滤当条件是等于和不等于的时候转换成between和not between // 如果是时间字段过滤当条件是等于和不等于的时候转换成between和not between
if (field.getDeType() == 1) { if (field.getDeType() == 1) {
if (StringUtils.containsIgnoreCase(whereTerm, "=")) { if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) {
whereTerm = " BETWEEN "; whereTerm = " BETWEEN ";
// 把value类似过滤组件处理获得start time和end time // 把value类似过滤组件处理获得start time和end time
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value); Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); 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 "; whereTerm = " NOT BETWEEN ";
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value); Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime"));

View File

@ -39,6 +39,9 @@ public class Dimension2SQLObj {
// 给计算字段处加一个占位符后续SQL方言转换后再替换 // 给计算字段处加一个占位符后续SQL方言转换后再替换
originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId()); originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId());
fieldsDialect.put(originField, calcFieldExp); fieldsDialect.put(originField, calcFieldExp);
if (isCross) {
originField = calcFieldExp;
}
} else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_COPY)) { } else if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_COPY)) {
originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getDataeaseName()); originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), x.getDataeaseName());
} else { } else {

View File

@ -53,6 +53,9 @@ public class ExtWhere2Str {
// 给计算字段处加一个占位符后续SQL方言转换后再替换 // 给计算字段处加一个占位符后续SQL方言转换后再替换
originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId());
fieldsDialect.put(originName, calcFieldExp); fieldsDialect.put(originName, calcFieldExp);
if (isCross) {
originName = calcFieldExp;
}
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) { } else if (ObjectUtils.isNotEmpty(field.getExtField()) && field.getExtField() == 1) {
originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName()); originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName());
} else { } else {

View File

@ -20,7 +20,7 @@ import java.util.*;
*/ */
public class Field2SQLObj { 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(); SQLObj tableObj = meta.getTable();
if (ObjectUtils.isEmpty(tableObj)) { if (ObjectUtils.isEmpty(tableObj)) {
return; return;
@ -33,10 +33,13 @@ public class Field2SQLObj {
String originField; String originField;
if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_CALC)) { if (ObjectUtils.isNotEmpty(x.getExtField()) && Objects.equals(x.getExtField(), ExtFieldConstant.EXT_CALC)) {
// 解析origin name中有关联的字段生成sql表达式 // 解析origin name中有关联的字段生成sql表达式
String calcFieldExp = Utils.calcFieldRegex(x.getOriginName(), tableObj, fields, isCross, dsMap); String calcFieldExp = Utils.calcFieldRegex(x.getOriginName(), tableObj, originFields, isCross, dsMap);
// 给计算字段处加一个占位符后续SQL方言转换后再替换 // 给计算字段处加一个占位符后续SQL方言转换后再替换
originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId()); originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, x.getId());
fieldsDialect.put(originField, calcFieldExp); fieldsDialect.put(originField, calcFieldExp);
if (isCross) {
originField = calcFieldExp;
}
// 此处是数据集预览获取数据库原始字段枚举值等操作使用如果遇到聚合函数则将originField设置为null // 此处是数据集预览获取数据库原始字段枚举值等操作使用如果遇到聚合函数则将originField设置为null
for (String func : FunctionConstant.AGG_FUNC) { for (String func : FunctionConstant.AGG_FUNC) {
if (Utils.matchFunction(func, calcFieldExp)) { if (Utils.matchFunction(func, calcFieldExp)) {

View File

@ -11,8 +11,8 @@ import io.dataease.engine.constant.SQLConstants;
import io.dataease.engine.utils.Utils; import io.dataease.engine.utils.Utils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; 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) { public static void getOrders(SQLMeta meta, List<DatasetTableFieldDTO> fields, List<DeSortField> sortFields, boolean isCross, Map<Long, DatasourceSchemaDTO> dsMap) {
SQLObj tableObj = meta.getTable(); SQLObj tableObj = meta.getTable();
List<SQLObj> xOrders = meta.getXOrders(); List<SQLObj> xOrders = meta.getXOrders() == null ? new ArrayList<>() : meta.getXOrders();
if (ObjectUtils.isEmpty(tableObj) || CollectionUtils.isEmpty(xOrders)) { if (ObjectUtils.isEmpty(tableObj)) {
return; return;
} }
if (ObjectUtils.isNotEmpty(sortFields)) { if (ObjectUtils.isNotEmpty(sortFields)) {
@ -35,6 +35,7 @@ public class Order2SQLObj {
SQLObj order = buildSortField(deSortField, tableObj, i, fields, isCross, dsMap); SQLObj order = buildSortField(deSortField, tableObj, i, fields, isCross, dsMap);
xOrders.add(order); xOrders.add(order);
} }
meta.setXOrders(xOrders);
} }
} }

View File

@ -40,6 +40,9 @@ public class Quota2SQLObj {
// 给计算字段处加一个占位符后续SQL方言转换后再替换 // 给计算字段处加一个占位符后续SQL方言转换后再替换
originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, y.getId()); originField = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, y.getId());
fieldsDialect.put(originField, calcFieldExp); fieldsDialect.put(originField, calcFieldExp);
if (isCross) {
originField = calcFieldExp;
}
} else if (ObjectUtils.isNotEmpty(y.getExtField()) && Objects.equals(y.getExtField(), ExtFieldConstant.EXT_COPY)) { } else if (ObjectUtils.isNotEmpty(y.getExtField()) && Objects.equals(y.getExtField(), ExtFieldConstant.EXT_COPY)) {
originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getDataeaseName()); originField = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), y.getDataeaseName());
} else { } else {

View File

@ -88,6 +88,9 @@ public class WhereTree2Str {
// 给计算字段处加一个占位符后续SQL方言转换后再替换 // 给计算字段处加一个占位符后续SQL方言转换后再替换
originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId()); originName = String.format(SqlPlaceholderConstants.CALC_FIELD_PLACEHOLDER, field.getId());
fieldsDialect.put(originName, calcFieldExp); fieldsDialect.put(originName, calcFieldExp);
if (isCross) {
originName = calcFieldExp;
}
} else if (ObjectUtils.isNotEmpty(field.getExtField()) && Objects.equals(field.getExtField(), ExtFieldConstant.EXT_COPY)) { } else if (ObjectUtils.isNotEmpty(field.getExtField()) && Objects.equals(field.getExtField(), ExtFieldConstant.EXT_COPY)) {
originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName()); originName = String.format(SQLConstants.FIELD_NAME, tableObj.getTableAlias(), field.getDataeaseName());
} else { } else {
@ -149,12 +152,12 @@ public class WhereTree2Str {
} else { } else {
// 如果是时间字段过滤当条件是等于和不等于的时候转换成between和not between // 如果是时间字段过滤当条件是等于和不等于的时候转换成between和not between
if (field.getDeType() == 1) { if (field.getDeType() == 1) {
if (StringUtils.containsIgnoreCase(whereTerm, "=")) { if (StringUtils.equalsIgnoreCase(whereTerm, " = ")) {
whereTerm = " BETWEEN "; whereTerm = " BETWEEN ";
// 把value类似过滤组件处理获得start time和end time // 把value类似过滤组件处理获得start time和end time
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value); Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); 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 "; whereTerm = " NOT BETWEEN ";
Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value); Map<String, Long> stringLongMap = Utils.parseDateTimeValue(value);
whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime")); whereValue = String.format(SQLConstants.WHERE_VALUE_BETWEEN, stringLongMap.get("startTime"), stringLongMap.get("endTime"));

View File

@ -3,6 +3,7 @@ package io.dataease.visualization.server;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO; import io.dataease.api.permissions.dataset.dto.DataSetRowPermissionsTreeDTO;
import io.dataease.api.visualization.VisualizationLinkJumpApi; 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.VisualizationLinkJumpDTO;
import io.dataease.api.visualization.dto.VisualizationLinkJumpInfoDTO; import io.dataease.api.visualization.dto.VisualizationLinkJumpInfoDTO;
import io.dataease.api.visualization.request.VisualizationLinkJumpBaseRequest; import io.dataease.api.visualization.request.VisualizationLinkJumpBaseRequest;
@ -144,14 +145,18 @@ public class VisualizationLinkJumpService implements VisualizationLinkJumpApi {
} }
@Override @Override
public List<VisualizationViewTableVO> viewTableDetailList(Long dvId) { public VisualizationComponentDTO viewTableDetailList(Long dvId) {
DataVisualizationInfo dvInfo = dataVisualizationInfoMapper.selectById(dvId); DataVisualizationInfo dvInfo = dataVisualizationInfoMapper.selectById(dvId);
List<VisualizationViewTableVO> result;
String componentData;
if (dvInfo != null) { if (dvInfo != null) {
List<VisualizationViewTableVO> result = extVisualizationLinkJumpMapper.getViewTableDetails(dvId); result = extVisualizationLinkJumpMapper.getViewTableDetails(dvId).stream().filter(viewTableInfo -> dvInfo.getComponentData().indexOf(viewTableInfo.getId().toString()) > -1).collect(Collectors.toList());
return result.stream().filter(viewTableInfo -> dvInfo.getComponentData().indexOf(viewTableInfo.getId().toString()) > -1).collect(Collectors.toList()); componentData = dvInfo.getComponentData();
}else { } else {
return new ArrayList<>(); result = new ArrayList<>();
componentData = "[]";
} }
return new VisualizationComponentDTO(componentData,result);
} }

View File

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

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="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

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="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

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="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

View File

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

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="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

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="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

View File

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

View 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

View File

@ -63,33 +63,31 @@ const checkDialog = () => {
} }
const handleMouseWheel = e => { const handleMouseWheel = e => {
if (editMode.value === 'preview' || checkDialog()) { if (
editMode.value === 'preview' ||
checkDialog() ||
(Math.abs(e.deltaX) !== 0 && Math.abs(e.deltaY) !== 0)
) {
return return
} }
let dvMain = document.getElementById('dv-main-center') if (e.ctrlKey) {
let dvMainLeftSlide = document.getElementById('dv-main-left-sidebar') if (e.deltaY > 0) {
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) {
//
scaleDecrease(3) scaleDecrease(3)
}
if (delta >= 240 || delta <= -240) {
e.stopPropagation() e.stopPropagation()
e.preventDefault() e.preventDefault()
} }
lastWheelNum = delta if (e.deltaY < 0) {
//
scaleIncrease(3)
e.stopPropagation()
e.preventDefault()
}
} }
} }
onMounted(() => { onMounted(() => {
window.addEventListener('mousewheel', handleMouseWheel, { passive: false }) window.addEventListener('wheel', handleMouseWheel, { passive: false })
setTimeout(() => { setTimeout(() => {
scale.value = canvasStyleData.value.scale scale.value = canvasStyleData.value.scale
nextTick(() => { nextTick(() => {
@ -99,7 +97,7 @@ onMounted(() => {
}) })
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('mousewheel', handleMouseWheel) window.removeEventListener('wheel', handleMouseWheel)
}) })
</script> </script>
<template> <template>

View File

@ -216,11 +216,10 @@ watch(
) )
watch( watch(
() => areaData.value.components, () => areaData.value.components.length,
() => { (val, oldVal) => {
groupAreaClickChange() groupAreaClickChange()
}, }
{ deep: true }
) )
const initWatermark = (waterDomId = 'editor-canvas-main') => { const initWatermark = (waterDomId = 'editor-canvas-main') => {
@ -1062,8 +1061,8 @@ const clearInfoBox = e => {
const cellInit = () => { const cellInit = () => {
// 1,why: x,y 使 style.left/cellWidth style.top/cellWidth // 1,why: x,y 使 style.left/cellWidth style.top/cellWidth
// () xy , // () xy ,
cellWidth.value = Math.floor((baseWidth.value + baseMarginLeft.value) * 10) / 10 cellWidth.value = Math.floor((baseWidth.value + baseMarginLeft.value) * 1000) / 1000
cellHeight.value = Math.floor((baseHeight.value + baseMarginTop.value) * 10) / 10 cellHeight.value = Math.floor((baseHeight.value + baseMarginTop.value) * 1000) / 1000
} }
const canvasSizeInit = () => { const canvasSizeInit = () => {
@ -1359,9 +1358,9 @@ const contextMenuShow = computed(() => {
const markLineShow = computed(() => isMainCanvas(canvasId.value)) const markLineShow = computed(() => isMainCanvas(canvasId.value))
// //
const groupAreaClickChange = () => { const groupAreaClickChange = async () => {
let groupAreaCom 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) { if (groupAreaHis && groupAreaHis.length > 0) {
groupAreaCom = groupAreaHis[0] groupAreaCom = groupAreaHis[0]
} }
@ -1369,7 +1368,8 @@ const groupAreaClickChange = () => {
if (areaData.value.components.length > 1) { if (areaData.value.components.length > 1) {
// //
composeStore.calcComposeArea() composeStore.calcComposeArea()
if (!groupAreaCom) { const hist2 = dvMainStore.componentData.filter(ele => ele.component === 'GroupArea')
if (groupAreaHis.length === 0) {
// //
groupAreaCom = findNewComponent('GroupArea', 'GroupArea') groupAreaCom = findNewComponent('GroupArea', 'GroupArea')
dvMainStore.addComponent({ component: groupAreaCom, index: undefined }) dvMainStore.addComponent({ component: groupAreaCom, index: undefined })
@ -1379,7 +1379,9 @@ const groupAreaClickChange = () => {
groupAreaCom.style.width = areaData.value.style.width groupAreaCom.style.width = areaData.value.style.width
groupAreaCom.style.height = areaData.value.style.height groupAreaCom.style.height = areaData.value.style.height
} else if (groupAreaCom) { } else if (groupAreaCom) {
dvMainStore.deleteComponentById(100000001) groupAreaHis.forEach(ele => {
dvMainStore.deleteComponentById(ele.id)
})
} }
} }

View File

@ -231,7 +231,8 @@
> >
<span class="custom-option"> <span class="custom-option">
<Icon <Icon
:icon-class="item.type" :name="item.type"
class-name="view-type-icon"
style="width: 14px; height: 14px" style="width: 14px; height: 14px"
/> />
<span style="float: left; margin-left: 4px; font-size: 14px">{{ <span style="float: left; margin-left: 4px; font-size: 14px">{{
@ -245,7 +246,7 @@
<el-select <el-select
v-model="targetViewInfo.targetFieldId" v-model="targetViewInfo.targetFieldId"
:placeholder="'请选择字段'" :placeholder="'请选择字段'"
:disabled="!targetViewInfo.sourceFieldActiveId" :disabled="fieldIdDisabledCheck(targetViewInfo)"
style="width: 100%" style="width: 100%"
> >
<el-option <el-option
@ -405,7 +406,7 @@ import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapsho
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue' import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
import { filterEmptyFolderTree } from '@/utils/canvasUtils' import { filterEmptyFolderTree } from '@/utils/canvasUtils'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { dvInfo, canvasViewInfo } = storeToRefs(dvMainStore) const { dvInfo, canvasViewInfo, componentData } = storeToRefs(dvMainStore)
const linkJumpInfoTree = ref(null) const linkJumpInfoTree = ref(null)
const { t } = useI18n() const { t } = useI18n()
const dialogShow = ref(false) const dialogShow = ref(false)
@ -643,12 +644,28 @@ const codeMirrorContentSet = content => {
const getPanelViewList = dvId => { const getPanelViewList = dvId => {
viewTableDetailList(dvId).then(rsp => { viewTableDetailList(dvId).then(rsp => {
state.viewIdFieldArrayMap = {} state.viewIdFieldArrayMap = {}
state.currentLinkPanelViewArray = rsp.data state.currentLinkPanelViewArray = rsp.data.visualizationViewTables
if (state.currentLinkPanelViewArray) { if (state.currentLinkPanelViewArray) {
state.currentLinkPanelViewArray.forEach(view => { state.currentLinkPanelViewArray.forEach(view => {
state.viewIdFieldArrayMap[view.id] = view.tableFields 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 => { const dvNodeClick = data => {
@ -667,8 +684,26 @@ const addLinkJumpField = () => {
const deleteLinkJumpField = index => { const deleteLinkJumpField = index => {
state.linkJumpInfo.targetViewInfoList.splice(index, 1) 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 => { 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 => { const sourceFieldCheckedChange = data => {
nextTick(() => { nextTick(() => {

View File

@ -19,10 +19,13 @@
:title="t('chart.text_color')" :title="t('chart.text_color')"
v-model="styleForm[styleColorKey.value]" v-model="styleForm[styleColorKey.value]"
class="color-picker-style" class="color-picker-style"
:prefix-icon="expandIcon(styleColorKey.icon)"
:triggerWidth="styleColorKey.width"
is-custom is-custom
:predefine="state.predefineColors" :predefine="state.predefineColors"
@change="changeStyle" @change="changeStyle"
/> >
</el-color-picker>
</el-form-item> </el-form-item>
</el-tooltip> </el-tooltip>
</template> </template>
@ -41,12 +44,17 @@
:class="'form-item-' + themes" :class="'form-item-' + themes"
> >
<el-select <el-select
style="width: 50px" :style="{ width: styleOptionMountedKey.width }"
:effect="themes" :effect="themes"
v-model="styleMounted[styleOptionMountedKey.value]" v-model="styleMounted[styleOptionMountedKey.value]"
size="small" size="small"
@change="sizeChange(styleOptionMountedKey.value)" @change="sizeChange(styleOptionMountedKey.value)"
> >
<template #prefix>
<el-icon :class="{ 'dark-icon': themes === 'dark' }">
<Icon :name="styleOptionMountedKey.icon" />
</el-icon>
</template>
<el-option <el-option
class="custom-style-option" class="custom-style-option"
v-for="option in styleOptionMountedKey.customOption" v-for="option in styleOptionMountedKey.customOption"
@ -72,10 +80,14 @@
:style="{ width: styleOptionKey.width }" :style="{ width: styleOptionKey.width }"
:effect="themes" :effect="themes"
v-model="styleForm[styleOptionKey.value]" v-model="styleForm[styleOptionKey.value]"
placeholder="透明度"
size="small" size="small"
@change="changeStyle" @change="changeStyle"
> >
<template #prefix>
<el-icon>
<Icon :name="styleOptionKey.icon" />
</el-icon>
</template>
<el-option <el-option
class="custom-style-option" class="custom-style-option"
v-for="option in styleOptionKey.customOption" v-for="option in styleOptionKey.customOption"
@ -118,48 +130,50 @@
</el-tooltip> </el-tooltip>
<template v-if="styleForm.textAlign"> <template v-if="styleForm.textAlign">
<div class="m-divider" :class="'custom-divider-' + themes"></div> <div class="m-divider" :class="'custom-divider-' + themes"></div>
<el-tooltip effect="dark" placement="bottom"> <div style="display: flex">
<template #content> <el-tooltip effect="dark" placement="bottom">
{{ t('chart.text_pos_left') }} <template #content>
</template> {{ t('chart.text_pos_left') }}
<div </template>
class="icon-btn" <div
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'left' }" class="icon-btn"
@click="setPosition('textAlign', 'left')" :class="{ dark: themes === 'dark', active: styleForm.textAlign === 'left' }"
> @click="setPosition('textAlign', 'left')"
<el-icon> >
<Icon name="icon_left-alignment_outlined" /> <el-icon>
</el-icon> <Icon name="icon_left-alignment_outlined" />
</div> </el-icon>
</el-tooltip> </div>
<el-tooltip effect="dark" placement="bottom"> </el-tooltip>
<template #content> <el-tooltip effect="dark" placement="bottom">
{{ t('chart.text_pos_center') }} <template #content>
</template> {{ t('chart.text_pos_center') }}
<div </template>
class="icon-btn" <div
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'center' }" class="icon-btn"
@click="setPosition('textAlign', 'center')" :class="{ dark: themes === 'dark', active: styleForm.textAlign === 'center' }"
> @click="setPosition('textAlign', 'center')"
<el-icon> >
<Icon name="icon_center-alignment_outlined" /> <el-icon>
</el-icon> <Icon name="icon_center-alignment_outlined" />
</div> </el-icon>
</el-tooltip> </div>
<el-tooltip effect="dark" placement="bottom"> </el-tooltip>
<template #content> <el-tooltip effect="dark" placement="bottom">
{{ t('chart.text_pos_right') }} <template #content>
</template> {{ t('chart.text_pos_right') }}
<div </template>
class="icon-btn" <div
:class="{ dark: themes === 'dark', active: styleForm.textAlign === 'right' }" class="icon-btn"
@click="setPosition('textAlign', 'right')" :class="{ dark: themes === 'dark', active: styleForm.textAlign === 'right' }"
> @click="setPosition('textAlign', 'right')"
<el-icon> >
<Icon name="icon_right-alignment_outlined" /> <el-icon>
</el-icon> <Icon name="icon_right-alignment_outlined" />
</div> </el-icon>
</el-tooltip> </div>
</el-tooltip>
</div>
</template> </template>
<template v-if="styleForm.headHorizontalPosition"> <template v-if="styleForm.headHorizontalPosition">
<div class="m-divider"></div> <div class="m-divider"></div>
@ -220,8 +234,8 @@
</el-row> </el-row>
</template> </template>
<script lang="ts" setup> <script lang="tsx" setup>
import { computed, reactive, ref, toRefs, watch } from 'vue' import { computed, h, reactive, ref, toRefs, watch } from 'vue'
import { COLOR_PANEL } from '@/views/chart/components/editor/util/chart' import { COLOR_PANEL } from '@/views/chart/components/editor/util/chart'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
@ -243,7 +257,9 @@ const props = withDefaults(
themes: 'dark' themes: 'dark'
} }
) )
const expandIcon = (name: string) => {
return h(Icon, { className: '', name })
}
const { themes, element } = toRefs(props) const { themes, element } = toRefs(props)
const emits = defineEmits(['onTextChange']) const emits = defineEmits(['onTextChange'])
const styleMounted = ref({ const styleMounted = ref({
@ -277,11 +293,21 @@ const state = reactive({
}) })
const styleColorKeyArray = [ const styleColorKeyArray = [
{ value: 'color', label: '颜色' }, { value: 'color', label: '颜色', width: 90, icon: 'dv-style-color' },
{ value: 'borderColor', label: '边框颜色' }, { value: 'borderColor', label: '边框颜色', width: 90, icon: 'dv-style-borderColor' },
{ value: 'headFontColor', label: '头部字体颜色' }, {
{ value: 'headFontActiveColor', label: '激活字体颜色' }, value: 'headFontColor',
{ value: 'backgroundColor', label: '背景色' } 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(() => { const fontSizeList = computed(() => {
@ -325,16 +351,52 @@ const borderStyleList = [
// //
const styleOptionMountedKeyArray = [ 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 = [ const styleOptionKeyArray = [
{ value: 'opacity', label: '透明度', customOption: opacitySizeList, width: '50px' }, {
{ value: 'borderWidth', label: '边框宽度', customOption: borderWidthList.value, width: '50px' }, value: 'opacity',
{ value: 'borderRadius', label: '圆角', customOption: borderRadiusList.value, width: '50px' }, label: '透明度',
{ value: 'borderStyle', label: '边框样式', customOption: borderStyleList, width: '60px' } 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 = () => { const styleInit = () => {
@ -514,4 +576,8 @@ watch(
.custom-row-inner { .custom-row-inner {
margin: 8px 0px 24px; margin: 8px 0px 24px;
} }
.dark-icon {
color: #ffffff;
}
</style> </style>

View File

@ -264,16 +264,18 @@ const componentMoveIn = component => {
dvMainStore.setCurComponent({ component: null, index: null }) dvMainStore.setCurComponent({ component: null, index: null })
component.canvasId = element.value.id + '--' + tabItem.name component.canvasId = element.value.id + '--' + tabItem.name
const refInstance = currentInstance.refs['tabCanvas_' + index][0] const refInstance = currentInstance.refs['tabCanvas_' + index][0]
const matrixBase = refInstance.getBaseMatrixSize() // if (refInstance) {
canvasChangeAdaptor(component, matrixBase) const matrixBase = refInstance.getBaseMatrixSize() //
tabItem.componentData.push(component) canvasChangeAdaptor(component, matrixBase)
nextTick(() => { tabItem.componentData.push(component)
component.x = 1 nextTick(() => {
component.y = 1 component.x = 1
component.style.left = 0 component.y = 1
component.style.top = 0 component.style.left = 0
refInstance.addItemBox(component) // component.style.top = 0
}) refInstance.addItemBox(component) //
})
}
} }
}) })
} }

View File

@ -7,7 +7,7 @@ import { deepCopy } from '@/utils/utils'
import { cloneDeep, defaultsDeep, defaultTo } from 'lodash-es' import { cloneDeep, defaultsDeep, defaultTo } from 'lodash-es'
import { import {
BASE_VIEW_CONFIG, BASE_VIEW_CONFIG,
CHART_CONT_FAMILY_MAP, CHART_FONT_FAMILY_MAP,
DEFAULT_INDICATOR_NAME_STYLE, DEFAULT_INDICATOR_NAME_STYLE,
DEFAULT_INDICATOR_STYLE DEFAULT_INDICATOR_STYLE
} from '@/views/chart/components/editor/util/chart' } from '@/views/chart/components/editor/util/chart'
@ -170,7 +170,7 @@ const formattedResult = computed(() => {
const emit = defineEmits(['onChartClick', 'onDrillFilters', 'onJumpClick']) const emit = defineEmits(['onChartClick', 'onDrillFilters', 'onJumpClick'])
const contentStyle = ref({ const contentStyle = ref<CSSProperties>({
display: 'flex', display: 'flex',
'flex-direction': 'column', 'flex-direction': 'column',
'align-items': 'center', 'align-items': 'center',
@ -182,7 +182,7 @@ const indicatorClass = ref<CSSProperties>({
color: thresholdColor.value, color: thresholdColor.value,
'font-size': DEFAULT_INDICATOR_STYLE.fontSize + 'px', 'font-size': DEFAULT_INDICATOR_STYLE.fontSize + 'px',
'font-family': defaultTo( 'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.fontFamily], CHART_FONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.fontFamily],
DEFAULT_INDICATOR_STYLE.fontFamily DEFAULT_INDICATOR_STYLE.fontFamily
), ),
'font-weight': DEFAULT_INDICATOR_STYLE.isBolder ? 'bold' : 'normal', 'font-weight': DEFAULT_INDICATOR_STYLE.isBolder ? 'bold' : 'normal',
@ -196,7 +196,7 @@ const indicatorSuffixClass = ref<CSSProperties>({
color: DEFAULT_INDICATOR_STYLE.suffixColor, color: DEFAULT_INDICATOR_STYLE.suffixColor,
'font-size': DEFAULT_INDICATOR_STYLE.suffixFontSize + 'px', 'font-size': DEFAULT_INDICATOR_STYLE.suffixFontSize + 'px',
'font-family': defaultTo( 'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.suffixFontFamily], CHART_FONT_FAMILY_MAP[DEFAULT_INDICATOR_STYLE.suffixFontFamily],
DEFAULT_INDICATOR_STYLE.suffixFontFamily DEFAULT_INDICATOR_STYLE.suffixFontFamily
), ),
'font-weight': DEFAULT_INDICATOR_STYLE.suffixIsBolder ? 'bold' : 'normal', 'font-weight': DEFAULT_INDICATOR_STYLE.suffixIsBolder ? 'bold' : 'normal',
@ -212,11 +212,15 @@ const suffixContent = ref('')
const indicatorNameShow = ref(false) const indicatorNameShow = ref(false)
const indicatorNameWrapperStyle = reactive<CSSProperties>({
'margin-top': DEFAULT_INDICATOR_NAME_STYLE.nameValueSpacing + 'px'
})
const indicatorNameClass = ref<CSSProperties>({ const indicatorNameClass = ref<CSSProperties>({
color: DEFAULT_INDICATOR_NAME_STYLE.color, color: DEFAULT_INDICATOR_NAME_STYLE.color,
'font-size': DEFAULT_INDICATOR_NAME_STYLE.fontSize + 'px', 'font-size': DEFAULT_INDICATOR_NAME_STYLE.fontSize + 'px',
'font-family': defaultTo( '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 DEFAULT_INDICATOR_NAME_STYLE.fontFamily
), ),
'font-weight': DEFAULT_INDICATOR_NAME_STYLE.isBolder ? 'bold' : 'normal', 'font-weight': DEFAULT_INDICATOR_NAME_STYLE.isBolder ? 'bold' : 'normal',
@ -237,16 +241,16 @@ const renderChart = async view => {
const chart = deepCopy({ const chart = deepCopy({
...defaultsDeep(view, TEMP_DEFAULT_CHART), ...defaultsDeep(view, TEMP_DEFAULT_CHART),
data: chartData.value data: chartData.value
}) }) as ChartObj
recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value) recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value)
recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value) recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value)
if (chart.customAttr) { if (chart.customAttr) {
const customAttr = chart.customAttr const { indicator, indicatorName, basicStyle } = chart.customAttr
if (customAttr.indicator) { if (indicator) {
switch (customAttr.indicator.hPosition) { switch (indicator.hPosition) {
case 'left': case 'left':
contentStyle.value['align-items'] = 'flex-start' contentStyle.value['align-items'] = 'flex-start'
break break
@ -256,7 +260,7 @@ const renderChart = async view => {
default: default:
contentStyle.value['align-items'] = 'center' contentStyle.value['align-items'] = 'center'
} }
switch (customAttr.indicator.vPosition) { switch (indicator.vPosition) {
case 'top': case 'top':
contentStyle.value['justify-content'] = 'flex-start' contentStyle.value['justify-content'] = 'flex-start'
break break
@ -267,73 +271,68 @@ const renderChart = async view => {
contentStyle.value['justify-content'] = 'center' contentStyle.value['justify-content'] = 'center'
} }
indicatorColor.value = customAttr.indicator.color indicatorColor.value = indicator.color
let suffixColor = customAttr.indicator.suffixColor let suffixColor = indicator.suffixColor
if ( if (basicStyle?.alpha !== undefined && !batchOptStatus.value) {
customAttr.basicStyle && indicatorColor.value = hexColorToRGBA(basicStyle.colors[0], basicStyle.alpha)
customAttr.basicStyle.alpha !== undefined && suffixColor = hexColorToRGBA(basicStyle.colors[1], basicStyle.alpha)
!batchOptStatus.value
) {
indicatorColor.value = hexColorToRGBA(
customAttr.basicStyle.colors[0],
customAttr.basicStyle.alpha
)
suffixColor = hexColorToRGBA(customAttr.basicStyle.colors[1], customAttr.basicStyle.alpha)
} }
indicatorClass.value = { indicatorClass.value = {
color: thresholdColor.value, color: thresholdColor.value,
'font-size': customAttr.indicator.fontSize + 'px', 'font-size': indicator.fontSize + 'px',
'font-family': defaultTo( 'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicator.fontFamily], CHART_FONT_FAMILY_MAP[indicator.fontFamily],
DEFAULT_INDICATOR_STYLE.fontFamily DEFAULT_INDICATOR_STYLE.fontFamily
), ),
'font-weight': customAttr.indicator.isBolder ? 'bold' : 'normal', 'font-weight': indicator.isBolder ? 'bold' : 'normal',
'font-style': customAttr.indicator.isItalic ? 'italic' : 'normal', 'font-style': indicator.isItalic ? 'italic' : 'normal',
'letter-spacing': customAttr.indicator.letterSpace + 'px', 'letter-spacing': indicator.letterSpace + 'px',
'text-shadow': customAttr.indicator.fontShadow ? '2px 2px 4px' : 'none', 'text-shadow': indicator.fontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style' 'font-synthesis': 'weight style'
} }
indicatorSuffixClass.value = { indicatorSuffixClass.value = {
color: suffixColor, color: suffixColor,
'font-size': customAttr.indicator.suffixFontSize + 'px', 'font-size': indicator.suffixFontSize + 'px',
'font-family': defaultTo( 'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicator.suffixFontFamily], CHART_FONT_FAMILY_MAP[indicator.suffixFontFamily],
DEFAULT_INDICATOR_STYLE.suffixFontFamily DEFAULT_INDICATOR_STYLE.suffixFontFamily
), ),
'font-weight': customAttr.indicator.suffixIsBolder ? 'bold' : 'normal', 'font-weight': indicator.suffixIsBolder ? 'bold' : 'normal',
'font-style': customAttr.indicator.suffixIsItalic ? 'italic' : 'normal', 'font-style': indicator.suffixIsItalic ? 'italic' : 'normal',
'letter-spacing': customAttr.indicator.suffixLetterSpace + 'px', 'letter-spacing': indicator.suffixLetterSpace + 'px',
'text-shadow': customAttr.indicator.suffixFontShadow ? '2px 2px 4px' : 'none', 'text-shadow': indicator.suffixFontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style' 'font-synthesis': 'weight style'
} }
showSuffix.value = customAttr.indicator.suffixEnable showSuffix.value = indicator.suffixEnable
suffixContent.value = defaultTo(customAttr.indicator.suffix, '') suffixContent.value = defaultTo(indicator.suffix, '')
} }
if (customAttr.indicatorName && customAttr.indicatorName.show) { if (indicatorName?.show) {
let nameColor = customAttr.indicatorName.color let nameColor = indicatorName.color
if (customAttr.basicStyle && customAttr.basicStyle.alpha !== undefined) { if (basicStyle?.alpha !== undefined) {
nameColor = hexColorToRGBA(customAttr.basicStyle.colors[2], customAttr.basicStyle.alpha) nameColor = hexColorToRGBA(basicStyle.colors[2], basicStyle.alpha)
} }
indicatorNameShow.value = true indicatorNameShow.value = true
indicatorNameClass.value = { indicatorNameClass.value = {
color: nameColor, color: nameColor,
'font-size': customAttr.indicatorName.fontSize + 'px', 'font-size': indicatorName.fontSize + 'px',
'font-family': defaultTo( 'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicatorName.fontFamily], CHART_FONT_FAMILY_MAP[indicatorName.fontFamily],
DEFAULT_INDICATOR_NAME_STYLE.fontFamily DEFAULT_INDICATOR_NAME_STYLE.fontFamily
), ),
'font-weight': customAttr.indicatorName.isBolder ? 'bold' : 'normal', 'font-weight': indicatorName.isBolder ? 'bold' : 'normal',
'font-style': customAttr.indicatorName.isItalic ? 'italic' : 'normal', 'font-style': indicatorName.isItalic ? 'italic' : 'normal',
'letter-spacing': customAttr.indicatorName.letterSpace + 'px', 'letter-spacing': indicatorName.letterSpace + 'px',
'text-shadow': customAttr.indicatorName.fontShadow ? '2px 2px 4px' : 'none', 'text-shadow': indicatorName.fontShadow ? '2px 2px 4px' : 'none',
'font-synthesis': 'weight style' 'font-synthesis': 'weight style'
} }
indicatorNameWrapperStyle['margin-top'] =
(indicatorName.nameValueSpacing ?? DEFAULT_INDICATOR_NAME_STYLE.nameValueSpacing) + 'px'
} else { } else {
indicatorNameShow.value = false indicatorNameShow.value = false
} }
@ -363,9 +362,6 @@ const calcData = (view, callback) => {
callback?.() callback?.()
}) })
} else { } else {
if (view.type === 'map') {
renderChart(view)
}
callback?.() callback?.()
} }
} }
@ -382,7 +378,7 @@ defineExpose({
<span :style="indicatorClass">{{ formattedResult }}</span> <span :style="indicatorClass">{{ formattedResult }}</span>
<span :style="indicatorSuffixClass" v-if="showSuffix">{{ suffixContent }}</span> <span :style="indicatorSuffixClass" v-if="showSuffix">{{ suffixContent }}</span>
</div> </div>
<div v-if="indicatorNameShow"> <div :style="indicatorNameWrapperStyle" v-if="indicatorNameShow">
<span :style="indicatorNameClass">{{ resultName }}</span> <span :style="indicatorNameClass">{{ resultName }}</span>
</div> </div>
</div> </div>

View File

@ -10,9 +10,10 @@
<chart-error v-if="isError" :err-msg="errMsg" /> <chart-error v-if="isError" :err-msg="errMsg" />
<Editor <Editor
v-if="editShow && !isError" v-if="editShow && !isError"
:id="tinymceId"
v-model="myValue" v-model="myValue"
class="custom-text-content" class="custom-text-content"
:style="wrapperStyle"
:id="tinymceId"
:init="init" :init="init"
:disabled="!canEdit || disabled" :disabled="!canEdit || disabled"
/> />
@ -46,6 +47,7 @@ import 'tinymce/plugins/contextmenu' // contextmenu
import 'tinymce/plugins/directionality' import 'tinymce/plugins/directionality'
import 'tinymce/plugins/nonbreaking' import 'tinymce/plugins/nonbreaking'
import 'tinymce/plugins/pagebreak' import 'tinymce/plugins/pagebreak'
import './plugins' //
import { computed, nextTick, reactive, ref, toRefs, watch, onMounted, PropType } from 'vue' import { computed, nextTick, reactive, ref, toRefs, watch, onMounted, PropType } from 'vue'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot' import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import eventBus from '@/utils/eventBus' import eventBus from '@/utils/eventBus'
@ -119,11 +121,11 @@ const init = ref({
skin_url: formatDataEaseBi('./tinymce-dataease-private/skins/ui/oxide'), // skin_url: formatDataEaseBi('./tinymce-dataease-private/skins/ui/oxide'), //
content_css: formatDataEaseBi('./tinymce-dataease-private/skins/content/default/content.css'), content_css: formatDataEaseBi('./tinymce-dataease-private/skins/content/default/content.css'),
plugins: 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: toolbar:
'undo redo |fontselect fontsizeselect |forecolor backcolor bold italic |underline strikethrough link| formatselect |' + '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 ' + ' blockquote subscript superscript removeformat | table image | fullscreen ' +
'| bdmap indent2em lineheight formatpainter axupimgs', '| bdmap indent2em lineheight formatpainter axupimgs',
toolbar_location: '/', toolbar_location: '/',
@ -134,7 +136,9 @@ const init = ref({
placeholder: '', placeholder: '',
outer_placeholder: '双击输入文字', outer_placeholder: '双击输入文字',
inline: true, // inline: true, //
branding: false branding: false,
icons: 'vertical-content',
vertical_align: element.value.propValue.verticalAlign
}) })
const editStatus = computed(() => { 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 = () => { const viewInit = () => {
useEmitt({ useEmitt({
@ -496,6 +530,14 @@ defineExpose({
</style> </style>
<style lang="less"> <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 { .tox-collection__item-label {
p { p {
color: #1a1a1a !important; color: #1a1a1a !important;

View File

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

View File

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

View File

@ -13,7 +13,10 @@ import {
watch, watch,
computed, computed,
onMounted, onMounted,
CSSProperties onBeforeMount,
CSSProperties,
shallowRef,
provide
} from 'vue' } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
@ -156,7 +159,52 @@ const onComponentClick = () => {
} }
const { emitter } = useEmitt() 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(() => { onBeforeUnmount(() => {
emitter.off(`addQueryCriteria${element.value.id}`) emitter.off(`addQueryCriteria${element.value.id}`)
emitter.off(`editQueryCriteria${element.value.id}`) emitter.off(`editQueryCriteria${element.value.id}`)
@ -245,10 +293,20 @@ const delQueryConfig = index => {
const resetData = () => { const resetData = () => {
;(list.value || []).reduce((pre, next) => { ;(list.value || []).reduce((pre, next) => {
next.conditionValueF = next.defaultConditionValueF
next.conditionValueOperatorF = next.defaultConditionValueOperatorF
next.conditionValueS = next.defaultConditionValueS
next.conditionValueOperatorS = next.defaultConditionValueOperatorS
if (!next.defaultValueCheck) { if (!next.defaultValueCheck) {
next.defaultValue = next.multiple || +next.displayType === 7 ? [] : undefined next.defaultValue = next.multiple || +next.displayType === 7 ? [] : undefined
} }
next.selectValue = Array.isArray(next.defaultValue) ? [...next.defaultValue] : next.defaultValue 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) const keyList = Object.entries(next.checkedFieldsMap)
.filter(ele => next.checkedFields.includes(ele[0])) .filter(ele => next.checkedFields.includes(ele[0]))
.filter(ele => !!ele[1]) .filter(ele => !!ele[1])
@ -261,6 +319,11 @@ const resetData = () => {
const clearData = () => { const clearData = () => {
;(list.value || []).reduce((pre, next) => { ;(list.value || []).reduce((pre, next) => {
next.selectValue = next.multiple || +next.displayType === 7 ? [] : undefined 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) const keyList = Object.entries(next.checkedFieldsMap)
.filter(ele => next.checkedFields.includes(ele[0])) .filter(ele => next.checkedFields.includes(ele[0]))
.filter(ele => !!ele[1]) .filter(ele => !!ele[1])
@ -557,7 +620,7 @@ const autoStyle = computed(() => {
} }
.query-button { .query-button {
align-self: flex-end; align-self: flex-end;
line-height: 28px; line-height: 40px;
margin: auto 0 5px auto; margin: auto 0 5px auto;
z-index: 0; z-index: 0;
} }

View File

@ -248,6 +248,9 @@ const handleDatasetChange = () => {
const handleFieldChange = () => { const handleFieldChange = () => {
if (!curComponent.value.defaultValueCheck) return if (!curComponent.value.defaultValueCheck) return
curComponent.value.defaultValue = curComponent.value.multiple ? [] : undefined curComponent.value.defaultValue = curComponent.value.multiple ? [] : undefined
if (!curComponent.value.displayId) {
curComponent.value.displayId = curComponent.value.field.id
}
} }
const handleValueSourceChange = () => { const handleValueSourceChange = () => {
@ -545,6 +548,7 @@ const validate = () => {
const handleBeforeClose = () => { const handleBeforeClose = () => {
inputCom.value?.mult?.handleClickOutside?.() inputCom.value?.mult?.handleClickOutside?.()
inputCom.value?.single?.handleClickOutside?.()
handleDialogClick() handleDialogClick()
dialogVisible.value = false dialogVisible.value = false
visiblePopover.value = false visiblePopover.value = false
@ -553,6 +557,8 @@ const handleBeforeClose = () => {
const confirmClick = () => { const confirmClick = () => {
if (validate()) return if (validate()) return
inputCom.value?.mult?.handleClickOutside?.() inputCom.value?.mult?.handleClickOutside?.()
inputCom.value?.single?.handleClickOutside?.()
handleDialogClick()
visiblePopover.value = false visiblePopover.value = false
dialogVisible.value = false dialogVisible.value = false
conditions.value.forEach(ele => { conditions.value.forEach(ele => {
@ -675,6 +681,7 @@ const parameterCompletion = () => {
timeType: 'fixed', timeType: 'fixed',
required: false, required: false,
defaultMapValue: [], defaultMapValue: [],
mapValue: [],
parametersStart: null, parametersStart: null,
conditionType: 0, conditionType: 0,
conditionValueOperatorF: 'eq', conditionValueOperatorF: 'eq',
@ -781,7 +788,7 @@ const handleDialogClick = () => {
const operators = [ const operators = [
{ {
label: '精匹配', label: '精匹配',
value: 'eq' value: 'eq'
}, },
{ {
@ -1569,7 +1576,6 @@ defineExpose({
</el-select> </el-select>
<el-input <el-input
class="condition-value-input" class="condition-value-input"
size="small"
v-model="curComponent.defaultConditionValueF" v-model="curComponent.defaultConditionValueF"
/> />
<div class="bottom-line"></div> <div class="bottom-line"></div>
@ -1593,7 +1599,6 @@ defineExpose({
</el-select> </el-select>
<el-input <el-input
class="condition-value-input" class="condition-value-input"
size="small"
v-model="curComponent.defaultConditionValueS" v-model="curComponent.defaultConditionValueS"
/> />
<div class="bottom-line next-line"></div> <div class="bottom-line next-line"></div>
@ -1654,7 +1659,10 @@ defineExpose({
> >
</div> </div>
</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"> <div class="label">
<el-tooltip <el-tooltip
effect="dark" effect="dark"
@ -2219,7 +2227,7 @@ defineExpose({
.value { .value {
width: 321px; width: 321px;
.condition-type { .condition-type {
margin-top: 8px; margin-top: 3px !important;
display: flex; display: flex;
position: relative; position: relative;
.ed-input__wrapper { .ed-input__wrapper {
@ -2271,7 +2279,7 @@ defineExpose({
opacity: 0.3; opacity: 0.3;
position: absolute; position: absolute;
right: 5px; right: 5px;
bottom: 5px; bottom: 3px;
width: 220px; width: 220px;
z-index: 10; z-index: 10;

View File

@ -1,11 +1,23 @@
<script lang="ts" setup> <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 { enumValueObj, type EnumValue, getEnumValue } from '@/api/dataset'
import { cloneDeep, debounce } from 'lodash-es' import { cloneDeep, debounce } from 'lodash-es'
interface SelectConfig { interface SelectConfig {
selectValue: any selectValue: any
defaultMapValue: any defaultMapValue: any
mapValue: any
defaultValue: any defaultValue: any
checkedFieldsMap: object checkedFieldsMap: object
displayType: string displayType: string
@ -53,7 +65,9 @@ const selectValue = ref()
const loading = ref(false) const loading = ref(false)
const multiple = ref(false) const multiple = ref(false)
const options = shallowRef([]) 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 setDefaultMapValue = arr => {
const { displayId, field } = config.value const { displayId, field } = config.value
if (!displayId || displayId === field?.id) { if (!displayId || displayId === field?.id) {
@ -81,13 +95,16 @@ const handleValueChange = () => {
config.value.selectValue = Array.isArray(selectValue.value) config.value.selectValue = Array.isArray(selectValue.value)
? [...selectValue.value] ? [...selectValue.value]
: selectValue.value : selectValue.value
config.value.defaultMapValue = setDefaultMapValue( config.value.mapValue = setDefaultMapValue(
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value] Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
) )
return return
} }
config.value.defaultValue = value config.value.defaultValue = value
config.value.mapValue = setDefaultMapValue(
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
)
config.value.defaultMapValue = setDefaultMapValue( config.value.defaultMapValue = setDefaultMapValue(
Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value] Array.isArray(selectValue.value) ? [...selectValue.value] : [selectValue.value]
) )
@ -152,12 +169,29 @@ const handleFieldIdChange = (val: EnumValue) => {
selectValue.value = Array.isArray(config.value.defaultValue) selectValue.value = Array.isArray(config.value.defaultValue)
? [...config.value.defaultValue] ? [...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 { } else {
selectValue.value = Array.isArray(selectValue.value) selectValue.value = Array.isArray(selectValue.value)
? [...selectValue.value] ? [...selectValue.value]
: selectValue.value : selectValue.value
} }
setEmptyData()
}) })
} }
@ -176,8 +210,8 @@ watch(
) )
const setEmptyData = () => { const setEmptyData = () => {
const { showEmpty, displayType } = config.value const { showEmpty, displayType, optionValueSource } = config.value
if (+displayType !== 0) return if (+displayType !== 0 || optionValueSource === 1) return
const [s] = options.value const [s] = options.value
if (showEmpty) { if (showEmpty) {
if (s?.value !== '_empty_$') { if (s?.value !== '_empty_$') {
@ -268,6 +302,7 @@ watch(
watch( watch(
[() => config.value.checkedFields, () => config.value.checkedFieldsMap], [() => config.value.checkedFields, () => config.value.checkedFieldsMap],
() => { () => {
if (!props.isConfig) return
debounceOptions(config.value.optionValueSource) debounceOptions(config.value.optionValueSource)
}, },
{ {
@ -350,6 +385,7 @@ const selectStyle = computed(() => {
}) })
const mult = ref() const mult = ref()
const single = ref()
onBeforeMount(() => { onBeforeMount(() => {
init() init()
@ -357,7 +393,8 @@ onBeforeMount(() => {
defineExpose({ defineExpose({
displayTypeChange, displayTypeChange,
mult mult,
single
}) })
</script> </script>
@ -390,6 +427,7 @@ defineExpose({
v-loading="loading" v-loading="loading"
@change="handleValueChange" @change="handleValueChange"
clearable clearable
ref="single"
:style="selectStyle" :style="selectStyle"
filterable filterable
radio radio

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { toRefs, onBeforeMount, type PropType } from 'vue' import { toRefs, onBeforeMount, type PropType, inject, type CSSProperties } from 'vue'
interface SelectConfig { interface SelectConfig {
conditionValueOperatorF: string conditionValueOperatorF: string
conditionValueF: string conditionValueF: string
@ -14,7 +14,7 @@ interface SelectConfig {
const operators = [ const operators = [
{ {
label: '精匹配', label: '精匹配',
value: 'eq' value: 'eq'
}, },
{ {
@ -57,10 +57,11 @@ const setParams = () => {
onBeforeMount(() => { onBeforeMount(() => {
setParams() setParams()
}) })
const customStyle = inject<{ background: string }>('$custom-style-filter')
</script> </script>
<template> <template>
<div class="text-search-select"> <div class="text-search-select" :style="{ background: customStyle.background }">
<div class="condition-type"> <div class="condition-type">
<el-select <el-select
class="condition-value-select" class="condition-value-select"
@ -143,7 +144,7 @@ onBeforeMount(() => {
opacity: 0.3; opacity: 0.3;
position: absolute; position: absolute;
right: 5px; right: 5px;
bottom: 5px; bottom: 3px;
width: 195px; width: 195px;
z-index: 10; z-index: 10;

View File

@ -15,10 +15,11 @@ const infoFormat = (obj: ComponentInfo) => {
name, name,
deType deType
}, },
displayId: '', displayId: id,
sortId: '', sortId: '',
sort: 'asc', sort: 'asc',
defaultMapValue: [], defaultMapValue: [],
mapValue: [],
conditionType: 0, conditionType: 0,
conditionValueOperatorF: 'eq', conditionValueOperatorF: 'eq',
conditionValueF: '', conditionValueF: '',

View File

@ -83,13 +83,15 @@ const getValueByDefaultValueCheckOrFirstLoad = (
firstLoad: boolean, firstLoad: boolean,
multiple: boolean, multiple: boolean,
defaultMapValue: any, defaultMapValue: any,
optionValueSource: number optionValueSource: number,
mapValue: any,
displayType: string
) => { ) => {
if (optionValueSource === 1) { if (optionValueSource === 1 && defaultMapValue?.length && ![1, 7].includes(+displayType)) {
if (firstLoad && !selectValue?.length) { if (firstLoad) {
return defaultValueCheck ? defaultMapValue : multiple ? [] : '' return defaultValueCheck ? defaultMapValue : multiple ? [] : ''
} }
return (selectValue?.length ? defaultMapValue : selectValue) || '' return (selectValue?.length ? mapValue : selectValue) || ''
} }
if (firstLoad && !selectValue?.length) { if (firstLoad && !selectValue?.length) {
@ -152,7 +154,7 @@ const getOperator = (
const operatorS = firstLoad ? defaultConditionValueOperatorS : conditionValueOperatorS const operatorS = firstLoad ? defaultConditionValueOperatorS : conditionValueOperatorS
if (displayType === '8') { if (displayType === '8') {
if (conditionType === 0) { if (conditionType === 0) {
return defaultConditionValueOperatorF return operatorF
} }
const operatorArr = [valueF === '' ? '' : operatorF, valueS === '' ? '' : operatorS].filter( const operatorArr = [valueF === '' ? '' : operatorF, valueS === '' ? '' : operatorS].filter(
ele => ele !== '' ele => ele !== ''
@ -180,7 +182,7 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
item.checkedFields.includes(curComponentId) && item.checkedFields.includes(curComponentId) &&
item.checkedFieldsMap[curComponentId] item.checkedFieldsMap[curComponentId]
) { ) {
let selectValue = '' let selectValue
const { const {
selectValue: value, selectValue: value,
timeGranularityMultiple, timeGranularityMultiple,
@ -200,6 +202,7 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
defaultValue, defaultValue,
optionValueSource, optionValueSource,
defaultMapValue, defaultMapValue,
mapValue,
parameters = [], parameters = [],
parametersCheck = false, parametersCheck = false,
isTree = false, isTree = false,
@ -247,6 +250,7 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
) )
item.defaultValue = [startTime, endTime] item.defaultValue = [startTime, endTime]
item.selectValue = [startTime, endTime] item.selectValue = [startTime, endTime]
selectValue = [startTime, endTime]
} }
} else if (displayType === '8') { } else if (displayType === '8') {
selectValue = getResult( selectValue = getResult(
@ -265,7 +269,9 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
firstLoad, firstLoad,
multiple, multiple,
defaultMapValue, defaultMapValue,
optionValueSource optionValueSource,
mapValue,
displayType
) )
} }
if ( if (
@ -294,23 +300,25 @@ export const searchQuery = (queryComponentList, filter, curComponentId, firstLoa
firstLoad, firstLoad,
optionValueSource optionValueSource
) )
filter.push({ if (result?.length) {
componentId: ele.id, filter.push({
fieldId: item.checkedFieldsMap[curComponentId], componentId: ele.id,
operator, fieldId: item.checkedFieldsMap[curComponentId],
value: result, operator,
parameters: parametersCheck value: result,
? +displayType === 7 parameters: parametersCheck
? [ ? +displayType === 7
parametersStart, ? [
parametersEnd?.id parametersStart,
? { ...parametersEnd, id: `${parametersEnd.id}_START_END_SPLIT` } parametersEnd?.id
: parametersEnd ? { ...parametersEnd, id: `${parametersEnd.id}_START_END_SPLIT` }
] : parametersEnd
: parameters ]
: [], : parameters
isTree : [],
}) isTree
})
}
} }
} }
}) })

View File

@ -80,7 +80,7 @@ onMounted(() => {
} }
} }
.ai-main-active { .ai-main-active {
border: 1px solid #d9d9d9; border: 1px solid rgba(239, 240, 241, 1);
box-shadow: 0px 6px 24px 0px #1f232914; box-shadow: 0px 6px 24px 0px #1f232914;
} }
.ai-main-active-min { .ai-main-active-min {

View 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 />&nbsp;
</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>

View File

@ -17,6 +17,7 @@ import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
import AiComponent from '@/layout/components/AiComponent.vue' import AiComponent from '@/layout/components/AiComponent.vue'
import { useEmitt } from '@/hooks/web/useEmitt' import { useEmitt } from '@/hooks/web/useEmitt'
import { findBaseParams } from '@/api/aiComponent' import { findBaseParams } from '@/api/aiComponent'
import AiTips from '@/layout/components/AiTips.vue'
const appearanceStore = useAppearanceStoreWithOut() const appearanceStore = useAppearanceStoreWithOut()
const { push } = useRouter() const { push } = useRouter()
const route = useRoute() const route = useRoute()
@ -43,6 +44,7 @@ const permissionStore = usePermissionStore()
const routers: any[] = formatRoute(permissionStore.getRoutersNotHidden as AppCustomRouteRecordRaw[]) const routers: any[] = formatRoute(permissionStore.getRoutersNotHidden as AppCustomRouteRecordRaw[])
const showSystem = ref(false) const showSystem = ref(false)
const showToolbox = ref(false) const showToolbox = ref(false)
const showOverlay = ref(true)
const handleSelect = (index: string) => { const handleSelect = (index: string) => {
// //
if (isExternal(index)) { if (isExternal(index)) {
@ -61,6 +63,12 @@ const navigateBg = computed(() => appearanceStore.getNavigateBg)
const navigate = computed(() => appearanceStore.getNavigate) const navigate = computed(() => appearanceStore.getNavigate)
const initAiBase = async () => { 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 => { await findBaseParams().then(rsp => {
const params = rsp.data const params = rsp.data
if (params && params['ai.baseUrl']) { 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(() => { onMounted(() => {
initShowSystem() initShowSystem()
initShowToolbox() initShowToolbox()
@ -96,19 +109,30 @@ onMounted(() => {
</el-menu> </el-menu>
<div class="operate-setting" v-if="!desktop"> <div class="operate-setting" v-if="!desktop">
<XpackComponent jsname="c3dpdGNoZXI=" /> <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" /> <Icon name="dv-ai" @click="handleAiClick" />
</el-icon> </el-icon>
<ai-tips @confirm="aiTipsConfirm" v-if="showOverlay" class="ai-icon-tips"></ai-tips>
<ToolboxCfg v-if="showToolbox" /> <ToolboxCfg v-if="showToolbox" />
<TopDoc /> <TopDoc />
<SystemCfg v-if="showSystem" /> <SystemCfg v-if="showSystem" />
<AccountOperator /> <AccountOperator />
<ai-component v-if="aiBaseUrl" :base-url="aiBaseUrl"></ai-component> <ai-component v-if="aiBaseUrl" :base-url="aiBaseUrl"></ai-component>
<div v-if="showOverlay" class="overlay"></div>
</div> </div>
</el-header> </el-header>
</template> </template>
<style lang="less" scoped> <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 { .header-light {
background-color: #ffffff !important; background-color: #ffffff !important;
box-shadow: 0px 0.5px 0px 0px #1f232926 !important; box-shadow: 0px 0.5px 0px 0px #1f232926 !important;
@ -208,4 +232,9 @@ onMounted(() => {
.ai-icon { .ai-icon {
font-size: 24px !important; font-size: 24px !important;
} }
.ai-icon-tips {
font-size: 24px !important;
z-index: 10001;
}
</style> </style>

View File

@ -449,7 +449,9 @@ export default {
latitude: '纬度', latitude: '纬度',
gradient: '渐变', gradient: '渐变',
layer_controller: '指标切换', layer_controller: '指标切换',
suspension: '悬浮', show_zoom: '显示缩放按钮',
button_color: '按钮颜色',
button_background_color: '按钮背景色',
chart_background: '组件背景', chart_background: '组件背景',
date_format: '请选择日期解析格式', date_format: '请选择日期解析格式',
solid_color: '纯色', solid_color: '纯色',
@ -646,6 +648,9 @@ export default {
table_item_font_color: '表格字体', table_item_font_color: '表格字体',
table_show_index: '显示序号', table_show_index: '显示序号',
table_header_sort: '开启表头排序', table_header_sort: '开启表头排序',
table_show_row_tooltip: '开启行头提示',
table_show_col_tooltip: '开启列头提示',
table_show_cell_tooltip: '开启单元格提示',
stripe: '斑马纹', stripe: '斑马纹',
start_angle: '起始角度', start_angle: '起始角度',
end_angle: '结束角度', end_angle: '结束角度',
@ -977,6 +982,7 @@ export default {
dimension_font_family: '名称字体', dimension_font_family: '名称字体',
dimension_text_style: '名称样式', dimension_text_style: '名称样式',
dimension_letter_space: '名称字间距', dimension_letter_space: '名称字间距',
name_value_spacing: '名称/值间距',
font_family: '字体', font_family: '字体',
letter_space: '字间距', letter_space: '字间距',
font_shadow: '字体阴影', font_shadow: '字体阴影',
@ -1102,7 +1108,9 @@ export default {
add_condition: '添加条件', add_condition: '添加条件',
chart_quadrant: '象限图', chart_quadrant: '象限图',
quadrant: '象限', quadrant: '象限',
font_size: '字号' font_size: '字号',
word_size_range: '字号区间',
word_spacing: '文字间隔'
}, },
dataset: { dataset: {
scope_edit: '仅编辑时生效', scope_edit: '仅编辑时生效',

View File

@ -38,6 +38,14 @@ declare interface ChartAttr {
* 象限设置 * 象限设置
*/ */
quadrant: QuadrantAttr quadrant: QuadrantAttr
/**
* 指标值
*/
indicator: ChartIndicatorStyle
/**
* 指标名称
*/
indicatorName: ChartIndicatorNameStyle
} }
/** /**
* 基础样式设置 * 基础样式设置
@ -161,9 +169,10 @@ declare interface ChartBasicStyle {
*/ */
areaBorderColor: string areaBorderColor: string
/** /**
* @deprecated
* 悬浮工具栏 * 悬浮工具栏
*/ */
suspension: boolean suspension?: boolean
/** /**
* 地图底色 * 地图底色
*/ */
@ -192,6 +201,18 @@ declare interface ChartBasicStyle {
* 环形图/玫瑰图外径占比 * 环形图/玫瑰图外径占比
*/ */
radius: number radius: number
/**
* 是否显示地图缩放按钮
*/
showZoom: boolean
/**
* 地图缩放按钮颜色
*/
zoomButtonColor: string
/**
* 地图缩放按钮背景颜色
*/
zoomBackground: string
} }
/** /**
* 表头属性 * 表头属性
@ -229,6 +250,14 @@ declare interface ChartTableHeaderAttr {
* 表头排序开关 * 表头排序开关
*/ */
tableHeaderSort: boolean tableHeaderSort: boolean
/**
* 行头鼠标悬浮提示开关
*/
showRowTooltip: boolean
/**
* 列头鼠标悬浮提示开关
*/
showColTooltip: boolean
} }
/** /**
* 单元格属性 * 单元格属性
@ -262,6 +291,10 @@ declare interface ChartTableCellAttr {
* 斑马纹单数行颜色 * 斑马纹单数行颜色
*/ */
tableItemSubBgColor: string tableItemSubBgColor: string
/**
* 鼠标悬浮提示
*/
showTooltip: boolean
} }
/** /**
@ -517,6 +550,14 @@ declare interface ChartMiscAttr {
* 指标/文本卡垂直位置 * 指标/文本卡垂直位置
*/ */
vPosition: 'top' | 'center' | 'bottom' vPosition: 'top' | 'center' | 'bottom'
/**
* 词云图字体大小区间
*/
wordSizeRange: [number, number]
/**
* 词云图文字间距
*/
wordSpacing: number
} }
/** /**
* 动态极值配置 * 动态极值配置
@ -702,3 +743,127 @@ declare interface QuadrantLineStyle {
*/ */
opacity: number 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
}

View File

@ -108,7 +108,7 @@ declare interface AssistLine {
*/ */
summary: string summary: string
axisType: 'left' | 'right' yAxisType: 'left' | 'right'
} }
/** /**

View File

@ -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
}
/** /**
* 标题样式设置 * 标题样式设置
*/ */

View File

@ -2,7 +2,22 @@ import { createRouter, createWebHashHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router' import type { RouteRecordRaw } from 'vue-router'
import type { App } from 'vue' 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({ const router = createRouter({
history: createWebHashHistory(), history: createWebHashHistory(),

View File

@ -812,7 +812,7 @@ export const dvMainStore = defineStore('dataVisualization', {
const checkQDList = [...data.dimensionList, ...data.quotaList] const checkQDList = [...data.dimensionList, ...data.quotaList]
for (let indexOuter = 0; indexOuter < this.componentData.length; indexOuter++) { for (let indexOuter = 0; indexOuter < this.componentData.length; indexOuter++) {
const element = this.componentData[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.trackFilterCursor(element, checkQDList, trackInfo, preActiveComponentIds, viewId)
this.componentData[indexOuter] = element this.componentData[indexOuter] = element
} else if (element.component === 'Group') { } else if (element.component === 'Group') {
@ -900,18 +900,36 @@ export const dvMainStore = defineStore('dataVisualization', {
if (element.component === 'VQuery') { if (element.component === 'VQuery') {
element.propValue.forEach(filterItem => { element.propValue.forEach(filterItem => {
if (filterItem.id === targetViewId) { if (filterItem.id === targetViewId) {
let queryParams = paramValue
if (!['1', '7'].includes(filterItem.displayType)) {
// 查询组件除了时间组件 其他入参只支持文本 这里全部转为文本
queryParams = paramValue.map(number => String(number))
}
filterItem.defaultValueCheck = true filterItem.defaultValueCheck = true
if (filterItem.displayType === '0' && filterItem.multiple) { filterItem.timeType = 'fixed'
filterItem.selectValue = paramValue if (['0', '2'].includes(filterItem.displayType)) {
filterItem.defaultValue = paramValue // 0 文本类型 1 数字类型
} else if (filterItem.displayType === '0' && !filterItem.multiple) { if (filterItem.multiple) {
filterItem.selectValue = paramValue[0] // multiple === true 多选
filterItem.defaultValue = paramValue[0] 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') { } else if (filterItem.displayType === '8') {
filterItem.conditionValueF = parmaValueSource // 8 文本搜索
} else { filterItem.conditionValueF = parmaValueSource + ''
filterItem.selectValue = paramValue[0] filterItem.defaultConditionValueF = parmaValueSource + ''
filterItem.defaultValue = paramValue[0]
} }
} }
}) })
@ -933,10 +951,11 @@ export const dvMainStore = defineStore('dataVisualization', {
const sourceInfo = viewId + '#' + QDItem.id const sourceInfo = viewId + '#' + QDItem.id
// 获取所有目标联动信息 // 获取所有目标联动信息
const targetInfoList = trackInfo[sourceInfo] || [] const targetInfoList = trackInfo[sourceInfo] || []
const paramValue = [QDItem.value]
targetInfoList.forEach(targetInfo => { targetInfoList.forEach(targetInfo => {
const targetInfoArray = targetInfo.split('#') const targetInfoArray = targetInfo.split('#')
const targetViewId = targetInfoArray[0] // 目标图表 const targetViewId = targetInfoArray[0] // 目标图表
if (element.id === targetViewId) { if (element.component === 'UserView' && element.id === targetViewId) {
// 如果目标图表 当前循环组件id相等 则进行条件增减 // 如果目标图表 当前循环组件id相等 则进行条件增减
const targetFieldId = targetInfoArray[1] // 目标图表列ID const targetFieldId = targetInfoArray[1] // 目标图表列ID
const condition = { const condition = {
@ -959,6 +978,43 @@ export const dvMainStore = defineStore('dataVisualization', {
currentFilters.push(condition) currentFilters.push(condition)
preActiveComponentIds.includes(element.id) || preActiveComponentIds.push(element.id) 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 element.linkageFilters = currentFilters

View File

@ -121,12 +121,14 @@ export const customAttrTrans = {
'valueFontSize', 'valueFontSize',
'spaceSplit', // 间隔 'spaceSplit', // 间隔
'scatterSymbolSize', // 气泡大小散点图 'scatterSymbolSize', // 气泡大小散点图
'radarSize' // 雷达占比 'radarSize', // 雷达占比
'wordSizeRange',
'wordSpacing'
], ],
label: ['fontSize'], label: ['fontSize'],
tooltip: ['fontSize'], tooltip: ['fontSize'],
indicator: ['fontSize', 'suffixFontSize'], indicator: ['fontSize', 'suffixFontSize'],
indicatorName: ['fontSize'] indicatorName: ['fontSize', 'nameValueSpacing']
} }
export const customStyleTrans = { export const customStyleTrans = {
text: ['fontSize'], text: ['fontSize'],
@ -278,6 +280,13 @@ export const mobileSpecialProps = {
} }
export function getScaleValue(propValue, scale) { 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) const propValueTemp = Math.round(propValue * scale)
return propValueTemp > 1 ? propValueTemp : 1 return propValueTemp > 1 ? propValueTemp : 1
} }

View File

@ -420,3 +420,20 @@ export async function decompressionPre(params, callBack) {
}) })
callBack(deTemplateData) 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
}
}

View File

@ -355,7 +355,7 @@ onMounted(() => {
<span class="el-dropdown-link inner-dropdown-menu menu-item-padding"> <span class="el-dropdown-link inner-dropdown-menu menu-item-padding">
<span class="menu-item-content"> <span class="menu-item-content">
<el-icon> <el-icon>
<Icon name="icon_functions_outlined" /> <Icon name="icon_dashboard_outlined" />
</el-icon> </el-icon>
<span>{{ t('chart.chart_type') }}</span> <span>{{ t('chart.chart_type') }}</span>
</span> </span>

View File

@ -54,11 +54,6 @@ const state = reactive({
quotaFields: [] quotaFields: []
}) })
const axisType = [
{ type: 'left', name: t('chart.drag_block_value_axis_left') },
{ type: 'right', name: t('chart.drag_block_value_axis_right') }
]
watch( watch(
() => props.chart.senior.assistLineCfg, () => props.chart.senior.assistLineCfg,
() => { () => {

View File

@ -1,6 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, nextTick, onMounted, PropType, reactive, ref, watch } from 'vue' import { computed, nextTick, onMounted, PropType, reactive, ref, watch } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { getGeoJsonFile, parseJson } from '../../../js/util' import { getGeoJsonFile, parseJson } from '../../../js/util'
import { forEach, debounce } from 'lodash-es' import { forEach, debounce } from 'lodash-es'
import { EmptyBackground } from '@/components/empty-background' import { EmptyBackground } from '@/components/empty-background'
@ -118,14 +117,6 @@ const updateAreaData = debounce(() => {
const onMapMappingChange = () => { const onMapMappingChange = () => {
emit('onMapMappingChange', state.mappingForm) emit('onMapMappingChange', state.mappingForm)
} }
const mergeCellMethod = ({ columnIndex }) => {
if (columnIndex === 1) {
return [1, 2]
}
if (columnIndex === 2) {
return [0, 0]
}
}
onMounted(() => { onMounted(() => {
init() init()
}) })
@ -141,7 +132,6 @@ onMounted(() => {
:cell-class-name="'area-map-table-cell-' + themes" :cell-class-name="'area-map-table-cell-' + themes"
:row-class-name="'area-map-table-row-' + themes" :row-class-name="'area-map-table-row-' + themes"
:data="areaData" :data="areaData"
:span-method="mergeCellMethod"
> >
<el-table-column label="图形" prop="originName" width="80" show-overflow-tooltip /> <el-table-column label="图形" prop="originName" width="80" show-overflow-tooltip />
<el-table-column width="144"> <el-table-column width="144">

View File

@ -26,7 +26,7 @@ const props = defineProps({
} }
}) })
const axisTypes = [ const yAxisTypes = [
{ type: 'left', name: t('chart.drag_block_value_axis_left') }, { type: 'left', name: t('chart.drag_block_value_axis_left') },
{ type: 'right', name: t('chart.drag_block_value_axis_right') } { type: 'right', name: t('chart.drag_block_value_axis_right') }
] ]
@ -39,7 +39,7 @@ const state = reactive({
fieldId: '', fieldId: '',
summary: 'avg', summary: 'avg',
axis: 'y', // axis: 'y', //
axisType: 'left', yAxisType: 'left',
value: '0', value: '0',
lineType: 'solid', lineType: 'solid',
color: '#ff0000', color: '#ff0000',
@ -76,8 +76,23 @@ const init = () => {
state.lineArr = JSON.parse(JSON.stringify(props.line)) state.lineArr = JSON.parse(JSON.stringify(props.line))
state.lineArr.forEach(line => { state.lineArr.forEach(line => {
if (find(props.quotaFields, d => d.id === line.fieldId) == undefined) { if (props.useQuotaExt) {
line.fieldId = undefined 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() changeAssistLine()
} }
const changeAxisType = item => { const changeYAxisType = item => {
if (props.useQuotaExt && item.axisType === 'right') { if (props.useQuotaExt && item.yAxisType === 'right') {
item.fieldId = props.quotaExtFields ? props.quotaExtFields[0]?.id : null item.fieldId = props.quotaExtFields ? props.quotaExtFields[0]?.id : null
item.curField = getQuotaExtField(item.fieldId) item.curField = getQuotaExtField(item.fieldId)
} else { } else {
@ -113,7 +128,7 @@ const changeAssistLine = () => {
emit('onAssistLineChange', state.lineArr) emit('onAssistLineChange', state.lineArr)
} }
const changeAssistLineField = item => { const changeAssistLineField = item => {
if (props.useQuotaExt && item.axisType === 'right') { if (props.useQuotaExt && item.yAxisType === 'right') {
item.curField = getQuotaExtField(item.fieldId) item.curField = getQuotaExtField(item.fieldId)
} else { } else {
item.curField = getQuotaField(item.fieldId) item.curField = getQuotaField(item.fieldId)
@ -169,9 +184,9 @@ onMounted(() => {
/> />
</el-col> </el-col>
<el-col v-if="useQuotaExt" :span="3"> <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 <el-option
v-for="opt in axisTypes" v-for="opt in yAxisTypes"
:key="opt.type" :key="opt.type"
:label="opt.name" :label="opt.name"
:value="opt.type" :value="opt.type"
@ -206,7 +221,7 @@ onMounted(() => {
@change="changeAssistLineField(item)" @change="changeAssistLineField(item)"
> >
<el-option <el-option
v-for="quota in useQuotaExt && item.axisType === 'right' v-for="quota in useQuotaExt && item.yAxisType === 'right'
? quotaExtFields ? quotaExtFields
: quotaFields" : quotaFields"
:key="quota.id" :key="quota.id"

View File

@ -116,11 +116,14 @@ const onChangeXAxisForm = (val, prop) => {
} }
const onChangeYAxisForm = (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) state.initReady && emit('onChangeYAxisForm', val, prop)
} }
const onChangeYAxisExtForm = (val, prop) => { const onChangeYAxisExtForm = (val, prop) => {
console.log(val, prop)
state.initReady && emit('onChangeYAxisExtForm', val, prop) state.initReady && emit('onChangeYAxisExtForm', val, prop)
} }

View File

@ -49,6 +49,7 @@ const changeBasicStyle = (prop?: string, requestData = false) => {
} }
const init = () => { const init = () => {
const basicStyle = cloneDeep(props.chart.customAttr.basicStyle) const basicStyle = cloneDeep(props.chart.customAttr.basicStyle)
configCompat(basicStyle)
state.basicStyleForm = defaultsDeep(basicStyle, cloneDeep(DEFAULT_BASIC_STYLE)) as ChartBasicStyle state.basicStyleForm = defaultsDeep(basicStyle, cloneDeep(DEFAULT_BASIC_STYLE)) as ChartBasicStyle
if (!state.customColor) { if (!state.customColor) {
state.customColor = state.basicStyleForm.colors[0] state.customColor = state.basicStyleForm.colors[0]
@ -56,6 +57,12 @@ const init = () => {
} }
initTableColumnWidth() initTableColumnWidth()
} }
const configCompat = (basicStyle: ChartBasicStyle) => {
//
if (basicStyle.suspension === false && basicStyle.showZoom === undefined) {
basicStyle.showZoom = false
}
}
const COLUMN_WIDTH_TYPE = ['table-info', 'table-normal'] const COLUMN_WIDTH_TYPE = ['table-info', 'table-normal']
const initTableColumnWidth = () => { const initTableColumnWidth = () => {
if (!COLUMN_WIDTH_TYPE.includes(props.chart.type)) { if (!COLUMN_WIDTH_TYPE.includes(props.chart.type)) {
@ -191,6 +198,39 @@ onMounted(() => {
</el-checkbox> </el-checkbox>
</el-form-item> </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--> <!--map start-->
<el-row :gutter="8"> <el-row :gutter="8">
<el-col :span="12" v-if="showProperty('areaBorderColor')"> <el-col :span="12" v-if="showProperty('areaBorderColor')">
@ -230,21 +270,51 @@ onMounted(() => {
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-form-item <el-form-item class="form-item" :class="'form-item-' + themes" v-if="showProperty('zoom')">
class="form-item"
:class="'form-item-' + themes"
v-if="showProperty('suspension')"
>
<el-checkbox <el-checkbox
size="small" size="small"
:effect="themes" :effect="themes"
v-model="state.basicStyleForm.suspension" v-model="state.basicStyleForm.showZoom"
:predefine="predefineColors" :predefine="predefineColors"
@change="changeBasicStyle('suspension')" @change="changeBasicStyle('zoomShow')"
> >
{{ t('chart.suspension') }} {{ t('chart.show_zoom') }}
</el-checkbox> </el-checkbox>
</el-form-item> </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--> <!--map end-->
@ -335,39 +405,6 @@ onMounted(() => {
</el-row> </el-row>
<!--table end--> <!--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--> <!--table2 start-->
<el-form-item <el-form-item
:label="t('chart.table_column_width_config')" :label="t('chart.table_column_width_config')"

View File

@ -49,7 +49,6 @@ const changeAxisStyle = (val, prop) => {
} }
const changeSubAxisStyle = (val, prop) => { const changeSubAxisStyle = (val, prop) => {
console.log(val, prop)
emit('onChangeYAxisExtForm', val, prop) emit('onChangeYAxisExtForm', val, prop)
} }

View File

@ -9,7 +9,6 @@ import {
DEFAULT_BASIC_STYLE DEFAULT_BASIC_STYLE
} from '@/views/chart/components/editor/util/chart' } from '@/views/chart/components/editor/util/chart'
import { cloneDeep, defaultsDeep } from 'lodash-es' import { cloneDeep, defaultsDeep } from 'lodash-es'
import { ElIcon } from 'element-plus-secondary'
import Icon from '@/components/icon-custom/src/Icon.vue' import Icon from '@/components/icon-custom/src/Icon.vue'
import { hexColorToRGBA } from '@/views/chart/components/js/util' import { hexColorToRGBA } from '@/views/chart/components/js/util'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
@ -251,6 +250,24 @@ defineExpose({ getFormData })
{{ t('chart.font_shadow') }} {{ t('chart.font_shadow') }}
</el-checkbox> </el-checkbox>
</el-form-item> </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> </el-form>
</div> </div>
</template> </template>
@ -366,4 +383,14 @@ defineExpose({ getFormData })
color: var(--N600-Dark, #a6a6a6); 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> </style>

View File

@ -7,11 +7,12 @@ import cloneDeep from 'lodash-es/cloneDeep'
import defaultsDeep from 'lodash-es/defaultsDeep' import defaultsDeep from 'lodash-es/defaultsDeep'
import { formatterType, unitType } from '../../../js/formatter' import { formatterType, unitType } from '../../../js/formatter'
import { fieldType } from '@/utils/attr' import { fieldType } from '@/utils/attr'
import { partition } from 'lodash-es' import { partition, uniqWith, isEqual } from 'lodash-es'
import chartViewManager from '../../../js/panel' import chartViewManager from '../../../js/panel'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useEmitt } from '@/hooks/web/useEmitt' import { useEmitt } from '@/hooks/web/useEmitt'
import { deepCopy } from '@/utils/utils'
const { t } = useI18n() const { t } = useI18n()
@ -98,7 +99,9 @@ const quotaAxis = computed(() => {
return return
} }
const axis = props.chart[prop] const axis = props.chart[prop]
axis?.forEach(item => result.push(item)) axis?.forEach(item => {
result.push({ ...item, seriesId: `${item.id}-${prop}` })
})
}) })
return result return result
}) })
@ -255,6 +258,9 @@ const updateSeriesTooltipFormatter = (form: AxisEditForm) => {
const addAxis = (form: AxisEditForm) => { const addAxis = (form: AxisEditForm) => {
const { axis, axisType } = form const { axis, axisType } = form
const axisMap = axis.reduce((pre, next) => { const axisMap = axis.reduce((pre, next) => {
if (!next) {
return pre
}
next.axisType = axisType next.axisType = axisType
next.seriesId = `${next.id}-${axisType}` next.seriesId = `${next.id}-${axisType}`
pre[next.id] = next pre[next.id] = next
@ -272,16 +278,17 @@ const addAxis = (form: AxisEditForm) => {
ele.chartShowName = axisMap[ele.id].chartShowName ele.chartShowName = axisMap[ele.id].chartShowName
} else { } else {
// //
if (dupAxis.findIndex(i => i.id === ele.id) !== -1) {
return
}
const tmp = cloneDeep(axisMap[ele.id]) const tmp = cloneDeep(axisMap[ele.id])
tmp.show = true tmp.show = true
dupAxis.push(tmp) dupAxis.push(tmp)
} }
} }
}) })
state.tooltipForm.seriesTooltipFormatter =
state.tooltipForm.seriesTooltipFormatter.concat(dupAxis)
state.tooltipForm.seriesTooltipFormatter = partition( state.tooltipForm.seriesTooltipFormatter = partition(
state.tooltipForm.seriesTooltipFormatter, state.tooltipForm.seriesTooltipFormatter.concat(dupAxis),
ele => quotaAxis.value.findIndex(item => item.id === ele.id) !== -1 ele => quotaAxis.value.findIndex(item => item.id === ele.id) !== -1
).flat() ).flat()
} }
@ -312,8 +319,8 @@ const removeAxis = (form: AxisEditForm) => {
if (axisMap[ele.seriesId]) { if (axisMap[ele.seriesId]) {
// //
ele.show = false ele.show = false
ele.summary = axisMap[ele.seriesId].summary
ele.seriesId = ele.id ele.seriesId = ele.id
ele.summary = 'sum'
} }
}) })
state.tooltipForm.seriesTooltipFormatter = partition( state.tooltipForm.seriesTooltipFormatter = partition(
@ -531,7 +538,7 @@ onMounted(() => {
</template> </template>
<el-option <el-option
class="series-select-option" class="series-select-option"
:key="item.id" :key="item.seriesId"
:value="item" :value="item"
:label="`${item.name}${ :label="`${item.name}${
item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : '' item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : ''

View File

@ -234,6 +234,20 @@ onMounted(() => {
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </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> </el-form>
</template> </template>

View File

@ -250,6 +250,34 @@ onMounted(() => {
{{ t('chart.table_header_sort') }} {{ t('chart.table_header_sort') }}
</el-checkbox> </el-checkbox>
</el-form-item> </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> </el-form>
</template> </template>

View File

@ -1394,7 +1394,7 @@ const drop = (ev: MouseEvent, type = 'xAxis') => {
const obj = cloneDeep(arr[i]) const obj = cloneDeep(arr[i])
state.moveId = obj.id as unknown as number state.moveId = obj.id as unknown as number
view.value[type].push(obj) view.value[type].push(obj)
const e = { newDraggableIndex: view.value.xAxis.length - 1 } const e = { newDraggableIndex: view.value[type].length - 1 }
if ('drillFields' === type) { if ('drillFields' === type) {
addDrill(e) addDrill(e)
} else if (type === 'customFilter') { } else if (type === 'customFilter') {

View File

@ -24,7 +24,9 @@ export const DEFAULT_COLOR_CASE: DeepPartial<ChartAttr> = {
areaBorderColor: '#303133', areaBorderColor: '#303133',
gaugeStyle: 'default', gaugeStyle: 'default',
tableBorderColor: '#E6E7E4', tableBorderColor: '#E6E7E4',
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)' tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
}, },
misc: { misc: {
mapLineGradient: false, mapLineGradient: false,
@ -65,7 +67,9 @@ export const DEFAULT_COLOR_CASE_LIGHT: DeepPartial<ChartAttr> = {
areaBorderColor: '#303133', areaBorderColor: '#303133',
gaugeStyle: 'default', gaugeStyle: 'default',
tableBorderColor: '#E6E7E4', tableBorderColor: '#E6E7E4',
tableScrollBarColor: 'rgba(0, 0, 0, 0.15)' tableScrollBarColor: 'rgba(0, 0, 0, 0.15)',
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
}, },
misc: { misc: {
mapLineGradient: false, mapLineGradient: false,
@ -106,7 +110,9 @@ export const DEFAULT_COLOR_CASE_DARK: DeepPartial<ChartAttr> = {
areaBorderColor: '#EBEEF5', areaBorderColor: '#EBEEF5',
gaugeStyle: 'default', gaugeStyle: 'default',
tableBorderColor: '#CCCCCC', tableBorderColor: '#CCCCCC',
tableScrollBarColor: 'rgba(255, 255, 255, 0.5)' tableScrollBarColor: 'rgba(255, 255, 255, 0.5)',
zoomButtonColor: '#fff',
zoomBackground: '#000'
}, },
misc: { misc: {
mapLineGradient: false, mapLineGradient: false,
@ -242,10 +248,9 @@ export const DEFAULT_MISC: ChartMiscAttr = {
mapLineAnimateDuration: 3, mapLineAnimateDuration: 3,
mapLineGradient: false, mapLineGradient: false,
mapLineSourceColor: '#146C94', mapLineSourceColor: '#146C94',
mapLineTargetColor: '#576CBC' mapLineTargetColor: '#576CBC',
} wordSizeRange: [8, 32],
export const DEFAULT_SUSPENSION = { wordSpacing: 6
show: true
} }
export const DEFAULT_MARK = { export const DEFAULT_MARK = {
@ -330,7 +335,9 @@ export const DEFAULT_TABLE_HEADER: ChartTableHeaderAttr = {
tableHeaderFontColor: '#000000', tableHeaderFontColor: '#000000',
tableTitleFontSize: 12, tableTitleFontSize: 12,
tableTitleHeight: 36, tableTitleHeight: 36,
tableHeaderSort: false tableHeaderSort: false,
showColTooltip: false,
showRowTooltip: false
} }
export const DEFAULT_TABLE_CELL: ChartTableCellAttr = { export const DEFAULT_TABLE_CELL: ChartTableCellAttr = {
tableFontColor: '#000000', tableFontColor: '#000000',
@ -339,7 +346,8 @@ export const DEFAULT_TABLE_CELL: ChartTableCellAttr = {
tableItemFontSize: 12, tableItemFontSize: 12,
tableItemHeight: 36, tableItemHeight: 36,
enableTableCrossBG: false, enableTableCrossBG: false,
tableItemSubBgColor: '#EEEEEE' tableItemSubBgColor: '#EEEEEE',
showTooltip: false
} }
export const DEFAULT_TITLE_STYLE: ChartTextStyle = { export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
show: true, show: true,
@ -359,35 +367,36 @@ export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = { export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = {
show: true, show: true,
fontSize: '20', fontSize: 20,
color: '#5470C6ff', color: '#5470C6ff',
hPosition: 'center', hPosition: 'center',
vPosition: 'center', vPosition: 'center',
isItalic: false, isItalic: false,
isBolder: true, isBolder: true,
fontFamily: 'Microsoft YaHei', fontFamily: 'Microsoft YaHei',
letterSpace: '0', letterSpace: 0,
fontShadow: false, fontShadow: false,
suffixEnable: true, suffixEnable: true,
suffix: '', suffix: '',
suffixFontSize: '14', suffixFontSize: 14,
suffixColor: '#5470C6ff', suffixColor: '#5470C6ff',
suffixIsItalic: false, suffixIsItalic: false,
suffixIsBolder: true, suffixIsBolder: true,
suffixFontFamily: 'Microsoft YaHei', suffixFontFamily: 'Microsoft YaHei',
suffixLetterSpace: '0', suffixLetterSpace: 0,
suffixFontShadow: false suffixFontShadow: false
} }
export const DEFAULT_INDICATOR_NAME_STYLE: ChartIndicatorNameStyle = { export const DEFAULT_INDICATOR_NAME_STYLE: ChartIndicatorNameStyle = {
show: true, show: true,
fontSize: '18', fontSize: 18,
color: '#ffffffff', color: '#ffffffff',
isItalic: false, isItalic: false,
isBolder: true, isBolder: true,
fontFamily: 'Microsoft YaHei', fontFamily: 'Microsoft YaHei',
letterSpace: '0', letterSpace: 0,
fontShadow: false fontShadow: false,
nameValueSpacing: 0
} }
export const DEFAULT_TITLE_STYLE_BASE: ChartTextStyle = { export const DEFAULT_TITLE_STYLE_BASE: ChartTextStyle = {
@ -994,7 +1003,7 @@ export const CHART_FONT_FAMILY = [
{ name: '楷体', value: 'KaiTi' } { name: '楷体', value: 'KaiTi' }
] ]
export const CHART_CONT_FAMILY_MAP = { export const CHART_FONT_FAMILY_MAP = {
'Microsoft YaHei': 'Microsoft YaHei', 'Microsoft YaHei': 'Microsoft YaHei',
SimSun: 'SimSun, "Songti SC", STSong', SimSun: 'SimSun, "Songti SC", STSong',
SimHei: 'SimHei, Helvetica', SimHei: 'SimHei, Helvetica',
@ -1364,14 +1373,16 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
radarShape: 'polygon', radarShape: 'polygon',
mapStyle: 'normal', mapStyle: 'normal',
areaBorderColor: '#EBEEF5', areaBorderColor: '#EBEEF5',
suspension: true,
areaBaseColor: '#ffffff', areaBaseColor: '#ffffff',
mapSymbolOpacity: 0.7, mapSymbolOpacity: 0.7,
mapSymbolStrokeWidth: 2, mapSymbolStrokeWidth: 2,
mapSymbol: 'circle', mapSymbol: 'circle',
mapSymbolSize: 20, mapSymbolSize: 20,
radius: 80, radius: 80,
innerRadius: 60 innerRadius: 60,
showZoom: true,
zoomButtonColor: '#aaa',
zoomBackground: '#fff'
} }
export const BASE_VIEW_CONFIG = { export const BASE_VIEW_CONFIG = {

View File

@ -25,7 +25,7 @@ export class Liquid extends G2PlotChartView<LiquidOptions, G2Liquid> {
'background-overall-component': ['all'], 'background-overall-component': ['all'],
'basic-style-selector': ['colors', 'alpha'], 'basic-style-selector': ['colors', 'alpha'],
'label-selector': ['fontSize', 'color', 'labelFormatter'], 'label-selector': ['fontSize', 'color', 'labelFormatter'],
'misc-selector': ['liquidShape', 'liquidMaxType', 'liquidMaxField'], 'misc-selector': ['liquidShape', 'liquidSize', 'liquidMaxType', 'liquidMaxField'],
'title-selector': [ 'title-selector': [
'title', 'title',
'fontSize', 'fontSize',

View File

@ -98,9 +98,10 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
options = this.setupOptions(chart, options, drawOption, geoJson) options = this.setupOptions(chart, options, drawOption, geoJson)
const view = new Choropleth(container, options) const view = new Choropleth(container, options)
const dotLayer = this.getDotLayer(chart, geoJson, drawOption) const dotLayer = this.getDotLayer(chart, geoJson, drawOption)
this.configZoomButton(view) this.configZoomButton(chart, view)
view.once('loaded', () => { view.once('loaded', () => {
view.addLayer(dotLayer) view.addLayer(dotLayer)
view.scene.map['keyboard'].disable()
view.on('fillAreaLayer:click', (ev: MapMouseEvent) => { view.on('fillAreaLayer:click', (ev: MapMouseEvent) => {
const data = ev.feature.properties const data = ev.feature.properties
action({ action({
@ -178,13 +179,6 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
const curAreaNameMapping = senior.areaMapping?.[areaId] const curAreaNameMapping = senior.areaMapping?.[areaId]
handleGeoJson(geoJson, curAreaNameMapping) handleGeoJson(geoJson, curAreaNameMapping)
options.color = hexColorToRGBA(basicStyle.areaBaseColor, basicStyle.alpha) 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) { if (!chart.data?.data?.length || !geoJson?.features?.length) {
options.label && (options.label.field = 'name') options.label && (options.label.field = 'name')
return options return options
@ -221,8 +215,7 @@ export class BubbleMap extends L7PlotChartView<ChoroplethOptions, Choropleth> {
this.configLabel, this.configLabel,
this.configStyle, this.configStyle,
this.configTooltip, this.configTooltip,
this.configBasicStyle, this.configBasicStyle
this.configLegend
)(chart, options, extra) )(chart, options, extra)
} }
} }

View File

@ -12,7 +12,7 @@ export const MAP_EDITOR_PROPERTY: EditorProperty[] = [
export const MAP_EDITOR_PROPERTY_INNER: EditorPropertyInner = { export const MAP_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
'background-overall-component': ['all'], 'background-overall-component': ['all'],
'basic-style-selector': ['colors', 'alpha', 'areaBorderColor', 'suspension'], 'basic-style-selector': ['colors', 'alpha', 'areaBorderColor', 'zoom'],
'title-selector': [ 'title-selector': [
'title', 'title',
'fontSize', 'fontSize',

View File

@ -22,8 +22,11 @@ const { t } = useI18n()
* 地图 * 地图
*/ */
export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> { export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
properties = MAP_EDITOR_PROPERTY properties: EditorProperty[] = [...MAP_EDITOR_PROPERTY, 'legend-selector']
propertyInner = MAP_EDITOR_PROPERTY_INNER propertyInner: EditorPropertyInner = {
...MAP_EDITOR_PROPERTY_INNER,
'legend-selector': ['icon', 'fontSize', 'color']
}
axis = MAP_AXIS_TYPE axis = MAP_AXIS_TYPE
axisConfig: AxisConfig = { axisConfig: AxisConfig = {
xAxis: { xAxis: {
@ -90,16 +93,14 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
active: { stroke: 'green', lineWidth: 1 } active: { stroke: 'green', lineWidth: 1 }
}, },
tooltip: {}, tooltip: {},
legend: {
position: 'bottomleft'
},
// 禁用线上地图数据 // 禁用线上地图数据
customFetchGeoData: () => null customFetchGeoData: () => null
} }
options = this.setupOptions(chart, options, drawOption, geoJson) options = this.setupOptions(chart, options, drawOption, geoJson)
const view = new Choropleth(container, options) const view = new Choropleth(container, options)
this.configZoomButton(view) this.configZoomButton(chart, view)
view.once('loaded', () => { view.once('loaded', () => {
view.scene.map['keyboard'].disable()
view.on('fillAreaLayer:click', (ev: MapMouseEvent) => { view.on('fillAreaLayer:click', (ev: MapMouseEvent) => {
const data = ev.feature.properties const data = ev.feature.properties
action({ action({
@ -135,14 +136,6 @@ export class Map extends L7PlotChartView<ChoroplethOptions, Choropleth> {
unknown: basicStyle.areaBaseColor unknown: basicStyle.areaBaseColor
} }
} }
const suspension = basicStyle.suspension
if (!suspension) {
options = {
...options,
legend: false,
zoom: false
}
}
if (!chart.data?.data?.length || !geoJson?.features?.length) { if (!chart.data?.data?.length || !geoJson?.features?.length) {
options.label && (options.label.field = 'name') options.label && (options.label.field = 'name')
return options return options

View File

@ -365,8 +365,8 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
protected configAnalyse(chart: Chart, options: DualAxesOptions): DualAxesOptions { protected configAnalyse(chart: Chart, options: DualAxesOptions): DualAxesOptions {
const list = getAnalyse(chart) const list = getAnalyse(chart)
const annotations = { const annotations = {
value: filter(list, l => l.axisType === 'left'), value: filter(list, l => l.yAxisType === 'left'),
valueExt: filter(list, l => l.axisType === 'right') valueExt: filter(list, l => l.yAxisType === 'right')
} }
return { ...options, annotations } return { ...options, annotations }
} }

View File

@ -123,7 +123,7 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
return return
} }
const { colorFieldObj, sizeFieldObj, xFieldObj, yFieldObj } = this.getFieldObject(chart) const { colorFieldObj, sizeFieldObj, xFieldObj, yFieldObj } = this.getFieldObject(chart)
if (!xFieldObj.id || !yFieldObj.id) { if (!xFieldObj.id || !yFieldObj.id || yFieldObj.id === xFieldObj.id) {
return return
} }
const data: any[] = [] const data: any[] = []
@ -316,14 +316,10 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
tooltip: false tooltip: false
} }
} }
xAxisTitle['show'] = true
yAxisTitle['show'] = true
yAxisExtTitle['show'] = true
tooltipAttr.seriesTooltipFormatter?.push(xAxisTitle)
const formatterMap = tooltipAttr.seriesTooltipFormatter const formatterMap = tooltipAttr.seriesTooltipFormatter
?.filter(i => i.show) ?.filter(i => i.show)
.reduce((pre, next) => { .reduce((pre, next) => {
pre[next['originName']] = next pre[next['seriesId']] = next
return pre return pre
}, {}) as Record<string, SeriesFormatter> }, {}) as Record<string, SeriesFormatter>
const tooltip: ScatterOptions['tooltip'] = { const tooltip: ScatterOptions['tooltip'] = {
@ -339,17 +335,21 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
originalItems originalItems
?.filter(i => i.name !== xAxisTitle['originName']) ?.filter(i => i.name !== xAxisTitle['originName'])
.forEach(item => { .forEach(item => {
const formatter = formatterMap[item.name] Object.keys(formatterMap).forEach(key => {
if (formatter) { if (formatterMap[key]['originName'] === item.name) {
const value = const formatter = formatterMap[key]
formatter.groupType === 'q' if (formatter) {
? valueFormatter(parseFloat(item.value as string), formatter.formatterCfg) const value =
: item.value formatter.groupType === 'q'
const name = isEmpty(formatter.chartShowName) ? valueFormatter(parseFloat(item.value as string), formatter.formatterCfg)
? formatter.name : item.value
: formatter.chartShowName const name = isEmpty(formatter.chartShowName)
result.push({ color: item.color, name, value }) ? formatter.name
} : formatter.chartShowName
result.push({ color: item.color, name, value })
}
}
})
}) })
return result return result
} }

View File

@ -8,6 +8,7 @@ import { getPadding } from '@/views/chart/components/js/panel/common/common_antv
import { valueFormatter } from '@/views/chart/components/js/formatter' import { valueFormatter } from '@/views/chart/components/js/formatter'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { isEmpty } from 'lodash-es' import { isEmpty } from 'lodash-es'
import { DEFAULT_MISC } from '@/views/chart/components/editor/util/chart'
const { t } = useI18n() const { t } = useI18n()
const DEFAULT_DATA = [] const DEFAULT_DATA = []
@ -20,6 +21,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
'background-overall-component', 'background-overall-component',
'title-selector', 'title-selector',
'tooltip-selector', 'tooltip-selector',
'misc-selector',
'jump-set', 'jump-set',
'linkage' 'linkage'
] ]
@ -38,6 +40,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
'letterSpace', 'letterSpace',
'fontShadow' 'fontShadow'
], ],
'misc-selector': ['wordSizeRange', 'wordSpacing'],
'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'seriesTooltipFormatter'] 'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'seriesTooltipFormatter']
} }
axis: AxisType[] = ['xAxis', 'yAxis', 'filter'] axis: AxisType[] = ['xAxis', 'yAxis', 'filter']
@ -58,6 +61,7 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
if (chart?.data) { if (chart?.data) {
// data // data
const data = chart.data.data const data = chart.data.data
const { misc } = parseJson(chart.customAttr)
// options // options
const initOptions: WordCloudOptions = { const initOptions: WordCloudOptions = {
data: data, data: data,
@ -66,9 +70,9 @@ export class WordCloud extends G2PlotChartView<WordCloudOptions, G2WordCloud> {
colorField: 'field', colorField: 'field',
wordStyle: { wordStyle: {
fontFamily: 'Verdana', fontFamily: 'Verdana',
fontSize: [8, 32], fontSize: (misc.wordSizeRange ?? DEFAULT_MISC.wordSizeRange) as [number, number],
rotation: [0, 0], rotation: [0, 0],
padding: 6 padding: misc.wordSpacing ?? DEFAULT_MISC.wordSpacing
}, },
random: () => 0.5, random: () => 0.5,
appendPadding: getPadding(chart), appendPadding: getPadding(chart),

View File

@ -20,7 +20,8 @@ export const TABLE_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
'tableTitleHeight', 'tableTitleHeight',
'tableHeaderAlign', 'tableHeaderAlign',
'showIndex', 'showIndex',
'indexLabel' 'indexLabel',
'showColTooltip'
], ],
'table-cell-selector': [ 'table-cell-selector': [
'tableItemBgColor', 'tableItemBgColor',
@ -29,7 +30,8 @@ export const TABLE_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
'tableItemAlign', 'tableItemAlign',
'tableItemHeight', 'tableItemHeight',
'enableTableCrossBG', 'enableTableCrossBG',
'tableItemSubBgColor' 'tableItemSubBgColor',
'showTooltip'
], ],
'title-selector': [ 'title-selector': [
'title', 'title',

View File

@ -169,6 +169,15 @@ export class TableInfo extends S2ChartView<TableSheet> {
action(param) 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 // header resize
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev)) newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev))
// right click // right click

View File

@ -164,6 +164,15 @@ export class TableNormal extends S2ChartView<TableSheet> {
} }
action(param) 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 // header resize
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev)) newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, ev => resizeAction(ev))
// right click // right click

View File

@ -32,7 +32,9 @@ export class TablePivot extends S2ChartView<PivotSheet> {
'tableTitleFontSize', 'tableTitleFontSize',
'tableHeaderFontColor', 'tableHeaderFontColor',
'tableTitleHeight', 'tableTitleHeight',
'tableHeaderAlign' 'tableHeaderAlign',
'showColTooltip',
'showRowTooltip'
], ],
'table-total-selector': ['row', 'col'], 'table-total-selector': ['row', 'col'],
'basic-style-selector': ['tableColumnMode', 'tableBorderColor', 'tableScrollBarColor', 'alpha'] '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) 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 // click
s2.on(S2Event.DATA_CELL_CLICK, ev => this.dataCellClickAction(chart, ev, s2, action)) 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)) s2.on(S2Event.ROW_CELL_CLICK, ev => this.headerCellClickAction(chart, ev, s2, action))

View File

@ -29,9 +29,9 @@ import { DOM } from '@antv/l7-utils'
export function getPadding(chart: Chart): number[] { export function getPadding(chart: Chart): number[] {
if (chart.drill) { if (chart.drill) {
return [0, 10, 26, 10] return [0, 10, 22, 10]
} else { } else {
return [0, 10, 14, 10] return [0, 10, 10, 10]
} }
} }
// color,label,tooltip,axis,legend,background // color,label,tooltip,axis,legend,background
@ -273,9 +273,7 @@ export function getLegend(chart: Chart) {
offsetY = 0 offsetY = 0
} else if (l.vPosition === 'bottom') { } else if (l.vPosition === 'bottom') {
if (chart.drill) { if (chart.drill) {
offsetY = -16 offsetY = -12
} else {
offsetY = -4
} }
} else { } else {
offsetY = 0 offsetY = 0
@ -292,9 +290,9 @@ export function getLegend(chart: Chart) {
offsetY = 0 offsetY = 0
} else if (l.vPosition === 'bottom') { } else if (l.vPosition === 'bottom') {
if (chart.drill) { if (chart.drill) {
offsetY = -22 offsetY = -18
} else { } else {
offsetY = -10 offsetY = -6
} }
} else { } else {
offsetY = 0 offsetY = 0
@ -309,6 +307,7 @@ export function getLegend(chart: Chart) {
marker: { marker: {
symbol: legendSymbol symbol: legendSymbol
}, },
itemHeight: l.fontSize + 4,
radio: false, radio: false,
pageNavigator: { pageNavigator: {
marker: { marker: {
@ -681,10 +680,10 @@ export function getAnalyse(chart: Chart) {
const content = const content =
ele.name + ele.name +
' : ' + ' : ' +
valueFormatter(value, ele.axisType === 'left' ? axisFormatterCfg : axisExtFormatterCfg) valueFormatter(value, ele.yAxisType === 'left' ? axisFormatterCfg : axisExtFormatterCfg)
assistLine.push({ assistLine.push({
type: 'line', type: 'line',
axisType: ele.axisType, yAxisType: ele.yAxisType,
start: ['start', value], start: ['start', value],
end: ['end', value], end: ['end', value],
style: { style: {
@ -694,15 +693,17 @@ export function getAnalyse(chart: Chart) {
}) })
assistLine.push({ assistLine.push({
type: 'text', type: 'text',
axisType: ele.axisType, yAxisType: ele.yAxisType,
position: [ position: [
(ele.axisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left' ? 'start' : 'end', (ele.yAxisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left'
? 'start'
: 'end',
value value
], ],
content: content, content: content,
offsetY: -2, offsetY: -2,
offsetX: offsetX:
(ele.axisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left' (ele.yAxisType === 'left' ? yAxisPosition : yAxisExtPosition) === 'left'
? 2 ? 2
: -10 * (content.length - 2), : -10 * (content.length - 2),
style: { style: {
@ -898,9 +899,32 @@ export function getTooltipSeriesTotalMap(data: any[]): Record<string, number> {
}) })
return result return result
} }
const LEGEND_SHAPE_STYLE_MAP = {
export function configL7Legend(): LegendOptions { 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 { return {
position: 'bottomleft',
customContent: (_: string, items: CategoryLegendListItem[]) => { customContent: (_: string, items: CategoryLegendListItem[]) => {
const showItems = items?.length > 30 ? items.slice(0, 30) : items const showItems = items?.length > 30 ? items.slice(0, 30) : items
if (showItems?.length) { if (showItems?.length) {
@ -923,11 +947,22 @@ export function configL7Legend(): LegendOptions {
const domStr = substitute(ITEM_TPL, substituteObj) const domStr = substitute(ITEM_TPL, substituteObj)
const itemDom = createDom(domStr) const itemDom = createDom(domStr)
// legend 形状用的
itemDom.style.setProperty('--bgColor', item.color)
listDom.appendChild(itemDom) listDom.appendChild(itemDom)
}) })
return listDom return listDom
} }
return '' 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 this.zoomIn
) )
const resetBtnIconText = createL7Icon('l7-icon-round') const resetBtnIconText = createL7Icon('l7-icon-round')
this['createButton'](resetBtnIconText, 'Reset', 'l7-button-control', container, () => { this['zoomResetButton'] = this['createButton'](
this.mapsService.setZoomAndCenter( resetBtnIconText,
this.controlOption['initZoom'], 'Reset',
this.controlOption['center'] 'l7-button-control',
) container,
}) () => {
this.mapsService.setZoomAndCenter(
this.controlOption['initZoom'],
this.controlOption['center']
)
}
)
if (this.controlOption.showZoom) { if (this.controlOption.showZoom) {
this['zoomNumDiv'] = this['createButton']( this['zoomNumDiv'] = this['createButton'](
'0', '0',
@ -963,19 +1004,44 @@ class CustomZoom extends Zoom {
container, container,
this.zoomOut 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']() this['updateDisabled']()
} }
} }
export function configL7Zoom(plot: L7Plot<PlotOptions>) { export function configL7Zoom(chart: Chart, plot: L7Plot<PlotOptions>) {
const options = plot.options const { basicStyle } = parseJson(chart.customAttr)
if (options.zoom === false) { if (
(basicStyle.suspension === false && basicStyle.showZoom === undefined) ||
basicStyle.showZoom === false
) {
return return
} }
plot.once('loaded', () => { plot.once('loaded', () => {
const zoomOptions = { const zoomOptions = {
initZoom: plot.scene.getZoom(), initZoom: plot.scene.getZoom(),
center: plot.scene.getCenter() center: plot.scene.getCenter(),
buttonColor: basicStyle.zoomButtonColor,
buttonBackground: basicStyle.zoomBackground
} as any } as any
plot.scene.addControl(new CustomZoom(zoomOptions)) plot.scene.addControl(new CustomZoom(zoomOptions))
}) })
} }
function setStyle(elements: HTMLElement[], styleProp: string, value) {
elements.forEach(e => {
e.style[styleProp] = value
})
}

View File

@ -15,7 +15,6 @@ import {
ChartLibraryType ChartLibraryType
} from '@/views/chart/components/js/panel/types' } from '@/views/chart/components/js/panel/types'
import { cloneDeep, defaultsDeep } from 'lodash-es' import { cloneDeep, defaultsDeep } from 'lodash-es'
import { ChoroplethOptions } from '@antv/l7plot/dist/esm/plots/choropleth'
import { parseJson } from '@/views/chart/components/js/util' import { parseJson } from '@/views/chart/components/js/util'
export interface L7PlotDrawOptions<P> extends AntVDrawOptions<P> { export interface L7PlotDrawOptions<P> extends AntVDrawOptions<P> {
@ -47,12 +46,12 @@ export abstract class L7PlotChartView<
defaultsDeep(options.tooltip, tooltip) defaultsDeep(options.tooltip, tooltip)
return options return options
} }
protected configLegend(_: Chart, options: ChoroplethOptions) { protected configLegend(chart: Chart, options: O): O {
const legend = configL7Legend() const legend = configL7Legend(chart)
defaultsDeep(options.legend, legend) defaultsDeep(options, { legend })
return options return options
} }
protected configEmptyDataStrategy(chart: Chart, options: ChoroplethOptions): ChoroplethOptions { protected configEmptyDataStrategy(chart: Chart, options: O): O {
const { functionCfg } = parseJson(chart.senior) const { functionCfg } = parseJson(chart.senior)
const emptyDataStrategy = functionCfg.emptyDataStrategy const emptyDataStrategy = functionCfg.emptyDataStrategy
if (!emptyDataStrategy || emptyDataStrategy === 'breakLine') { if (!emptyDataStrategy || emptyDataStrategy === 'breakLine') {
@ -75,8 +74,8 @@ export abstract class L7PlotChartView<
return options return options
} }
protected configZoomButton(plot: P) { protected configZoomButton(chart: Chart, plot: P) {
configL7Zoom(plot) configL7Zoom(chart, plot)
} }
protected constructor(name: string, defaultData?: any[]) { protected constructor(name: string, defaultData?: any[]) {
super(ChartLibraryType.L7_PLOT, name) super(ChartLibraryType.L7_PLOT, name)

View File

@ -3,7 +3,7 @@ import {
AntVDrawOptions, AntVDrawOptions,
ChartLibraryType ChartLibraryType
} from '@/views/chart/components/js/panel/types' } 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 { import {
configHeaderInteraction, configHeaderInteraction,
configTooltip, configTooltip,
@ -13,6 +13,7 @@ import {
handleTableEmptyStrategy handleTableEmptyStrategy
} from '@/views/chart/components/js/panel/common/common_table' } from '@/views/chart/components/js/panel/common/common_table'
import '@antv/s2/dist/style.min.css' import '@antv/s2/dist/style.min.css'
import { find } from 'lodash-es'
declare interface PageInfo { declare interface PageInfo {
currentPage: number currentPage: number
@ -52,4 +53,40 @@ export abstract class S2ChartView<P extends SpreadSheet> extends AntVAbstractCha
protected configConditions(chart: Chart) { protected configConditions(chart: Chart) {
return getConditions(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
})
}
} }

View File

@ -15,6 +15,7 @@ import ChartError from '@/views/chart/components/views/components/ChartError.vue
import { BASE_VIEW_CONFIG } from '../../editor/util/chart' import { BASE_VIEW_CONFIG } from '../../editor/util/chart'
import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle' import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle'
import { deepCopy } from '@/utils/utils' import { deepCopy } from '@/utils/utils'
import { trackBarStyleCheck } from '@/utils/canvasUtils'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc } = storeToRefs(dvMainStore) const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc } = storeToRefs(dvMainStore)
@ -202,8 +203,13 @@ const action = param => {
trackClick(trackMenu.value[0]) trackClick(trackMenu.value[0])
} else { } else {
// //
state.trackBarStyle.left = param.x - 50 + 'px' const barStyleTemp = {
state.trackBarStyle.top = param.y + 10 + 'px' 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() viewTrack.value.trackButtonClick()
} }
} }

View File

@ -26,6 +26,7 @@ import { BASE_VIEW_CONFIG } from '../../editor/util/chart'
import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle' import { customAttrTrans, customStyleTrans, recursionTransObj } from '@/utils/canvasStyle'
import { deepCopy } from '@/utils/utils' import { deepCopy } from '@/utils/utils'
import { useEmitt } from '@/hooks/web/useEmitt' import { useEmitt } from '@/hooks/web/useEmitt'
import { trackBarStyleCheck } from '@/utils/canvasUtils'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc } = storeToRefs(dvMainStore) const { nowPanelTrackInfo, nowPanelJumpInfo, mobileInPc } = storeToRefs(dvMainStore)
@ -247,8 +248,13 @@ const action = param => {
trackClick(trackMenu.value[0]) trackClick(trackMenu.value[0])
} else { } else {
// //
state.trackBarStyle.left = param.x - 50 + 'px' const barStyleTemp = {
state.trackBarStyle.top = param.y + 10 + 'px' 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() viewTrack.value.trackButtonClick()
} }
} }
@ -463,6 +469,7 @@ const autoHeightStyle = computed(() => {
} }
.table-page-info { .table-page-info {
position: relative; position: relative;
padding-left: 4px;
margin: 4px; margin: 4px;
height: 20px; height: 20px;
display: flex; display: flex;

View File

@ -19,7 +19,7 @@ import {
import { useEmitt } from '@/hooks/web/useEmitt' import { useEmitt } from '@/hooks/web/useEmitt'
import { hexColorToRGBA } from '@/views/chart/components/js/util.js' import { hexColorToRGBA } from '@/views/chart/components/js/util.js'
import { import {
CHART_CONT_FAMILY_MAP, CHART_FONT_FAMILY_MAP,
DEFAULT_TITLE_STYLE DEFAULT_TITLE_STYLE
} from '@/views/chart/components/editor/util/chart' } from '@/views/chart/components/editor/util/chart'
import DrillPath from '@/views/chart/components/views/components/DrillPath.vue' import DrillPath from '@/views/chart/components/views/components/DrillPath.vue'
@ -153,13 +153,13 @@ const trackMenu = computed<Array<string>>(() => {
}) })
const hasLinkIcon = computed(() => { 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(() => { const hasJumpIcon = computed(() => {
return trackMenu.value.indexOf('jump') > -1 && !mobileInPc.value return trackMenu.value.indexOf('jump') > -1 && !mobileInPc.value
}) })
const hasDrillIcon = computed(() => { 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) const loading = ref(false)
@ -250,7 +250,7 @@ const initTitle = () => {
state.title_class.fontWeight = customStyle.text.isBolder ? 'bold' : 'normal' state.title_class.fontWeight = customStyle.text.isBolder ? 'bold' : 'normal'
state.title_class.fontFamily = customStyle.text.fontFamily 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 : DEFAULT_TITLE_STYLE.fontFamily
state.title_class.letterSpacing = state.title_class.letterSpacing =
(customStyle.text.letterSpace (customStyle.text.letterSpace
@ -587,9 +587,9 @@ const toolTip = computed(() => {
const marginBottom = computed<string | 0>(() => { const marginBottom = computed<string | 0>(() => {
if (titleShow.value || trackMenu.value.length > 0 || state.title_remark.show) { 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>(() => { const iconSize = computed<string>(() => {
@ -686,6 +686,7 @@ const iconSize = computed<string>(() => {
:view="view" :view="view"
:scale="scale" :scale="scale"
:show-position="showPosition" :show-position="showPosition"
:element="element"
v-else-if="showChartView(ChartLibraryType.S2)" v-else-if="showChartView(ChartLibraryType.S2)"
ref="chartComponent" ref="chartComponent"
@onChartClick="chartClick" @onChartClick="chartClick"

View File

@ -317,10 +317,14 @@ const addOperation = (
const baseUrl = const baseUrl =
curCanvasType.value === 'dataV' ? '#/dvCanvas?opt=create' : '#/dashboard?opt=create' curCanvasType.value === 'dataV' ? '#/dvCanvas?opt=create' : '#/dashboard?opt=create'
let newWindow = null let newWindow = null
let embeddedBaseUrl = ''
if (isDataEaseBi.value) {
embeddedBaseUrl = embeddedStore.baseUrl
}
if (data?.id) { if (data?.id) {
newWindow = window.open(baseUrl + `&pid=${data.id}`, '_blank') newWindow = window.open(embeddedBaseUrl + baseUrl + `&pid=${data.id}`, '_blank')
} else { } else {
newWindow = window.open(baseUrl, '_blank') newWindow = window.open(embeddedBaseUrl + baseUrl, '_blank')
} }
initOpenHandler(newWindow) initOpenHandler(newWindow)
} else if (cmd === 'newFromTemplate') { } else if (cmd === 'newFromTemplate') {
@ -463,19 +467,14 @@ defineExpose({
<el-tooltip content="新建文件夹" placement="top" effect="dark"> <el-tooltip content="新建文件夹" placement="top" effect="dark">
<el-icon <el-icon
class="custom-icon btn" class="custom-icon btn"
:style="{ marginRight: isDataEaseBi ? 0 : '20px' }" style="margin-right: 20px"
@click="addOperation('newFolder', null, 'folder')" @click="addOperation('newFolder', null, 'folder')"
> >
<Icon name="dv-new-folder" /> <Icon name="dv-new-folder" />
</el-icon> </el-icon>
</el-tooltip> </el-tooltip>
<el-tooltip <el-tooltip :content="newResourceLabel" placement="top" effect="dark">
v-if="!isDataEaseBi"
:content="newResourceLabel"
placement="top"
effect="dark"
>
<el-dropdown popper-class="menu-outer-dv_popper" trigger="hover"> <el-dropdown popper-class="menu-outer-dv_popper" trigger="hover">
<el-icon class="custom-icon btn" @click="addOperation('newLeaf', null, 'leaf', true)"> <el-icon class="custom-icon btn" @click="addOperation('newLeaf', null, 'leaf', true)">
<Icon name="icon_file-add_outlined" /> <Icon name="icon_file-add_outlined" />

View File

@ -9,11 +9,11 @@ const dvMainStore = dvMainStoreWithOut()
const checkItemPosition = component => { const checkItemPosition = component => {
component.x = 1 component.x = 1
component.sizeX = 36 component.sizeX = 72
component.y = dvMainStore.componentData.reduce((pre, next) => { component.y = dvMainStore.componentData.reduce((pre, next) => {
return Math.max(pre, next.y + next.sizeY) return Math.max(pre, next.y + next.sizeY)
}, 1) }, 1)
component.sizeY = 10 component.sizeY = 20
} }
const hanedleMessage = event => { const hanedleMessage = event => {

View File

@ -9,15 +9,15 @@
</el-tooltip> </el-tooltip>
<el-row v-show="state.asideActive" style="padding: 24px 12px 0"> <el-row v-show="state.asideActive" style="padding: 24px 12px 0">
<el-row style="align-items: center"> <el-row style="align-items: center">
<span class="custom-breadcrumb-item" @click="closePreview()">{{ <span class="custom-breadcrumb-item" @click="closePreview()">模版中心</span>
t('visualization.template_preview')
}}</span>
<el-icon><ArrowRight /></el-icon> <span class="custom-breadcrumb-item-to"></span> <el-icon><ArrowRight /></el-icon> <span class="custom-breadcrumb-item-to"></span>
<el-tooltip class="box-item" effect="dark" content="收起" placement="right"> <el-tooltip class="box-item" effect="dark" content="收起" placement="right">
<el-icon class="insert-retract" @click="asideActiveChange(false)"> <div @click="asideActiveChange(false)" class="insert-retract">
<Icon name="market-retract"></Icon> <el-icon>
</el-icon> <Icon name="icon_left_outlined" />
</el-icon>
</div>
</el-tooltip> </el-tooltip>
</el-row> </el-row>
<el-row class="margin-top16 search-area"> <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 { .insert-retract {
position: absolute; position: absolute;
left: 176px; left: 182px;
top: 2px; top: 2px;
display: inline-block; border: 1px solid #dee0e3;
font-size: 34px; background: #fff;
font-weight: 400 !important;
font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
line-height: 1;
white-space: nowrap;
cursor: pointer; cursor: pointer;
color: #646a73; height: 24px;
-webkit-appearance: none; width: 24px;
text-align: center; border-radius: 50%;
box-sizing: border-box; display: flex;
outline: 0; align-items: center;
margin: 0; justify-content: center;
transition: 0.1s; box-shadow: 0px 5px 10px 0px #1f23291a;
border-radius: 3px;
&:active {
color: #000;
border-color: #3a8ee6;
outline: 0;
}
&:hover { &:hover {
color: #3a8ee6; .ed-icon {
color: var(--ed-color-primary);
}
}
.ed-icon {
font-size: 12px;
} }
} }

View File

@ -1,5 +1,5 @@
<script lang="ts" setup> <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 AddSql from './AddSql.vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import zeroNodeImg from '@/assets/img/drag.png' 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 let isUpdate = false
watch( watch(
@ -234,6 +251,8 @@ const changeNodeFields = val => {
} }
const closeEditUnion = () => { const closeEditUnion = () => {
nodeField.value = []
currentNode.value = null
const [fir] = state.nodeList const [fir] = state.nodeList
if (fir.isShadow) { if (fir.isShadow) {
delete fir.isShadow delete fir.isShadow
@ -831,14 +850,19 @@ const notConfirm = () => {
confirm() confirm()
} }
const getNodeList = () => {
return cloneDeep(unref(state.nodeList))
}
defineExpose({ defineExpose({
nodeNameList, nodeNameList,
nodeList: state.nodeList, getNodeList,
setStateBack, setStateBack,
notConfirm, notConfirm,
dfsNodeFieldBack, dfsNodeFieldBack,
initState, initState,
setChangeStatus setChangeStatus,
crossDatasources
}) })
const handleActiveNode = ele => { const handleActiveNode = ele => {

View File

@ -120,7 +120,9 @@ const handleChange = () => {
<template> <template>
<el-popover <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" :persistent="false"
ref="popover" ref="popover"
placement="right" placement="right"
@ -173,6 +175,9 @@ const handleChange = () => {
</style> </style>
<style lang="less"> <style lang="less">
.menu-more_popper_six > :first-child > :first-child > :first-child {
height: 210px;
}
.menu-more_popper_one { .menu-more_popper_one {
padding: 0 !important; padding: 0 !important;
background: transparent !important; background: transparent !important;

View File

@ -318,7 +318,7 @@ watch(searchTable, val => {
const editeSave = () => { const editeSave = () => {
const union = [] const union = []
loading.value = true loading.value = true
dfsNodeList(union, datasetDrag.value.nodeList) dfsNodeList(union, datasetDrag.value.getNodeList())
saveDatasetTree({ saveDatasetTree({
...nodeInfo, ...nodeInfo,
name: datasetName.value, name: datasetName.value,
@ -448,7 +448,7 @@ const deleteField = item => {
callback: (action: Action) => { callback: (action: Action) => {
if (action === 'confirm') { if (action === 'confirm') {
delFieldById([item.id]) delFieldById([item.id])
datasetDrag.value.dfsNodeFieldBack(datasetDrag.value.nodeList, item) datasetDrag.value.dfsNodeFieldBack(datasetDrag.value.getNodeList(), item)
ElMessage({ ElMessage({
message: t('chart.delete_success'), message: t('chart.delete_success'),
type: 'success' type: 'success'
@ -671,7 +671,6 @@ const addComplete = () => {
const state = reactive({ const state = reactive({
nodeNameList: [], nodeNameList: [],
editArr: [], editArr: [],
nodeList: [],
dataSourceList: [], dataSourceList: [],
tableData: [], tableData: [],
fieldCollapse: ['dimension', 'quota'] fieldCollapse: ['dimension', 'quota']
@ -750,7 +749,7 @@ const fieldUnion = ref()
const setFieldAll = () => { const setFieldAll = () => {
const arr = [] const arr = []
dfsFields(arr, datasetDrag.value.nodeList) dfsFields(arr, datasetDrag.value.getNodeList())
const delIdArr = getDelIdArr(arr, allfields.value) const delIdArr = getDelIdArr(arr, allfields.value)
allfields.value = diffArr(arr, allfields.value) allfields.value = diffArr(arr, allfields.value)
delFieldById(delIdArr) delFieldById(delIdArr)
@ -815,6 +814,10 @@ const mouseupDrag = () => {
dom.removeEventListener('mousemove', calculateWidth) dom.removeEventListener('mousemove', calculateWidth)
dom.removeEventListener('mousemove', calculateHeight) dom.removeEventListener('mousemove', calculateHeight)
} }
const crossDatasources = computed(() => {
return datasetDrag.value?.crossDatasources
})
const calculateWidth = (e: MouseEvent) => { const calculateWidth = (e: MouseEvent) => {
if (e.pageX < 240) { if (e.pageX < 240) {
LeftWidth.value = 240 LeftWidth.value = 240
@ -920,7 +923,7 @@ const resetAllfieldsId = arr => {
const resetAllfieldsUnionId = (arr, idMap) => { const resetAllfieldsUnionId = (arr, idMap) => {
let strUnion = JSON.stringify(arr) as string 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 let strAllfields = JSON.stringify(unref(allfields.value)) as string
Object.entries(idMap).forEach(([key, value]) => { Object.entries(idMap).forEach(([key, value]) => {
strUnion = strUnion.replaceAll(key, value as string) strUnion = strUnion.replaceAll(key, value as string)
@ -938,7 +941,7 @@ const datasetSave = () => {
return return
} }
let union = [] let union = []
dfsNodeList(union, datasetDrag.value.nodeList) dfsNodeList(union, datasetDrag.value.getNodeList())
const pid = route.query.pid || nodeInfo.pid const pid = route.query.pid || nodeInfo.pid
if (!union.length) { if (!union.length) {
ElMessage.error('数据集不能为空') ElMessage.error('数据集不能为空')
@ -965,7 +968,7 @@ const datasetPreviewLoading = ref(false)
const datasetPreview = () => { const datasetPreview = () => {
if (datasetPreviewLoading.value) return if (datasetPreviewLoading.value) return
const arr = [] const arr = []
dfsNodeList(arr, datasetDrag.value.nodeList) dfsNodeList(arr, datasetDrag.value.getNodeList())
datasetPreviewLoading.value = true datasetPreviewLoading.value = true
getPreviewData({ union: arr, allFields: allfields.value }) getPreviewData({ union: arr, allFields: allfields.value })
.then(res => { .then(res => {
@ -1328,6 +1331,12 @@ const getDsIconName = data => {
</div> </div>
</div> </div>
<div class="drag-right" :style="{ width: `calc(100vw - ${showLeft ? LeftWidth : 0}px)` }"> <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 <dataset-union
@join-editor="joinEditor" @join-editor="joinEditor"
@changeUpdate="changeUpdate" @changeUpdate="changeUpdate"
@ -1343,7 +1352,9 @@ const getDsIconName = data => {
<div <div
class="sql-result" class="sql-result"
:style="{ :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"> <div class="sql-title">
@ -2101,6 +2112,23 @@ const getDsIconName = data => {
display: flex; display: flex;
.drag-right { .drag-right {
height: calc(100vh - 56px); 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 { .sql-result {
font-family: '阿里巴巴普惠体 3.0 55 Regular L3'; font-family: '阿里巴巴普惠体 3.0 55 Regular L3';
font-size: 14px; font-size: 14px;

View File

@ -320,6 +320,34 @@ function clear_images() {
fi fi
} }
function backup() { 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 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 . tar --exclude=logs/dataease -zcf $backup_file_name -C $DE_RUNNING_BASE .
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
@ -328,6 +356,10 @@ function backup() {
else else
echo "备份成功,备份文件 : $backup_file_name" echo "备份成功,备份文件 : $backup_file_name"
fi fi
if [[ $need_stop == 1 ]];then
service dataease start
fi
} }
function restore() { function restore() {
if [[ -z $target ]];then if [[ -z $target ]];then
@ -367,7 +399,7 @@ function main() {
upgrade upgrade
;; ;;
backup) backup)
backup backup $target
;; ;;
restore) restore)
restore $target restore $target

View File

@ -1,5 +1,6 @@
package io.dataease.api.chart.dto; package io.dataease.api.chart.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data; import lombok.Data;
@ -15,7 +16,8 @@ public class ChartSeniorAssistDTO {
private Long fieldId; private Long fieldId;
private String summary; private String summary;
private String axis; private String axis;
private String axisType; @JsonProperty("yAxisType")
private String yAxisType;
private String value; private String value;
private String lineType; private String lineType;
private String color; private String color;

View File

@ -1,6 +1,7 @@
package io.dataease.api.visualization; package io.dataease.api.visualization;
import com.github.xiaoymin.knife4j.annotations.ApiSupport; 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.dto.VisualizationLinkJumpDTO;
import io.dataease.api.visualization.request.VisualizationLinkJumpBaseRequest; import io.dataease.api.visualization.request.VisualizationLinkJumpBaseRequest;
import io.dataease.api.visualization.response.VisualizationLinkJumpBaseResponse; import io.dataease.api.visualization.response.VisualizationLinkJumpBaseResponse;
@ -46,7 +47,7 @@ public interface VisualizationLinkJumpApi {
@GetMapping("/viewTableDetailList/{dvId}") @GetMapping("/viewTableDetailList/{dvId}")
@Operation(summary = "查询跳转明细") @Operation(summary = "查询跳转明细")
List<VisualizationViewTableVO> viewTableDetailList(@PathVariable Long dvId); VisualizationComponentDTO viewTableDetailList(@PathVariable Long dvId);
@PostMapping("/updateJumpSetActive") @PostMapping("/updateJumpSetActive")
@Operation(summary = "更新跳转信息可用状态") @Operation(summary = "更新跳转信息可用状态")

View File

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