Merge branch 'dev-v2' into pr@dev2@fixds
@ -250,6 +250,120 @@ public class DefaultChartHandler extends AbstractChartPlugin {
|
||||
return res;
|
||||
}
|
||||
|
||||
protected List<ChartViewFieldDTO> getAssistFields(List<ChartSeniorAssistDTO> list, List<ChartViewFieldDTO> yAxis, List<ChartViewFieldDTO> xAxis) {
|
||||
List<ChartViewFieldDTO> res = new ArrayList<>();
|
||||
for (ChartSeniorAssistDTO dto : list) {
|
||||
DatasetTableFieldDTO curField = dto.getCurField();
|
||||
ChartViewFieldDTO field = null;
|
||||
String alias = "";
|
||||
for (int i = 0; i < yAxis.size(); i++) {
|
||||
ChartViewFieldDTO yField = yAxis.get(i);
|
||||
if (Objects.equals(yField.getId(), curField.getId())) {
|
||||
field = yField;
|
||||
alias = String.format(SQLConstants.FIELD_ALIAS_Y_PREFIX, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ObjectUtils.isEmpty(field) && CollectionUtils.isNotEmpty(xAxis)) {
|
||||
for (int i = 0; i < xAxis.size(); i++) {
|
||||
ChartViewFieldDTO xField = xAxis.get(i);
|
||||
if (StringUtils.equalsIgnoreCase(String.valueOf(xField.getId()), String.valueOf(curField.getId()))) {
|
||||
field = xField;
|
||||
alias = String.format(SQLConstants.FIELD_ALIAS_X_PREFIX, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ObjectUtils.isEmpty(field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ChartViewFieldDTO chartViewFieldDTO = new ChartViewFieldDTO();
|
||||
BeanUtils.copyBean(chartViewFieldDTO, curField);
|
||||
chartViewFieldDTO.setSummary(dto.getSummary());
|
||||
chartViewFieldDTO.setOriginName(alias);// yAxis的字段别名,就是查找的字段名
|
||||
res.add(chartViewFieldDTO);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public List<ChartSeniorAssistDTO> getDynamicThresholdFields(ChartViewDTO view) {
|
||||
List<ChartSeniorAssistDTO> list = new ArrayList<>();
|
||||
Map<String, Object> senior = view.getSenior();
|
||||
if (ObjectUtils.isEmpty(senior)) {
|
||||
return list;
|
||||
}
|
||||
ChartSeniorThresholdCfgDTO thresholdCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("threshold")), ChartSeniorThresholdCfgDTO.class);
|
||||
|
||||
if (null == thresholdCfg || !thresholdCfg.isEnable()) {
|
||||
return list;
|
||||
}
|
||||
List<TableThresholdDTO> tableThreshold = thresholdCfg.getTableThreshold();
|
||||
|
||||
if (ObjectUtils.isEmpty(tableThreshold)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
List<ChartSeniorThresholdDTO> conditionsList = tableThreshold.stream()
|
||||
.filter(item -> !ObjectUtils.isEmpty(item))
|
||||
.map(TableThresholdDTO::getConditions)
|
||||
.flatMap(List::stream)
|
||||
.filter(condition -> StringUtils.equalsAnyIgnoreCase(condition.getType(), "dynamic"))
|
||||
.toList();
|
||||
|
||||
List<ChartSeniorAssistDTO> assistDTOs = conditionsList.stream()
|
||||
.flatMap(condition -> getConditionFields(condition).stream())
|
||||
.filter(this::solveThresholdCondition)
|
||||
.toList();
|
||||
|
||||
list.addAll(assistDTOs);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private boolean solveThresholdCondition(ChartSeniorAssistDTO fieldDTO) {
|
||||
Long fieldId = fieldDTO.getFieldId();
|
||||
String summary = fieldDTO.getValue();
|
||||
if (ObjectUtils.isEmpty(fieldId) || StringUtils.isEmpty(summary)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DatasetTableFieldDTO datasetTableFieldDTO = datasetTableFieldManage.selectById(fieldId);
|
||||
if (ObjectUtils.isEmpty(datasetTableFieldDTO)) {
|
||||
return false;
|
||||
}
|
||||
ChartViewFieldDTO datasetTableField = new ChartViewFieldDTO();
|
||||
BeanUtils.copyBean(datasetTableField, datasetTableFieldDTO);
|
||||
fieldDTO.setCurField(datasetTableField);
|
||||
fieldDTO.setSummary(summary);
|
||||
return true;
|
||||
}
|
||||
|
||||
private List<ChartSeniorAssistDTO> getConditionFields(ChartSeniorThresholdDTO condition) {
|
||||
List<ChartSeniorAssistDTO> list = new ArrayList<>();
|
||||
if ("between".equals(condition.getTerm())) {
|
||||
if (!StringUtils.equalsIgnoreCase(condition.getDynamicMaxField().getSummary(), "value")) {
|
||||
list.add(of(condition.getDynamicMaxField()));
|
||||
}
|
||||
if (!StringUtils.equalsIgnoreCase(condition.getDynamicMinField().getSummary(), "value")) {
|
||||
list.add(of(condition.getDynamicMinField()));
|
||||
}
|
||||
} else {
|
||||
if (!StringUtils.equalsIgnoreCase(condition.getDynamicField().getSummary(), "value")) {
|
||||
list.add(of(condition.getDynamicField()));
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private ChartSeniorAssistDTO of(ThresholdDynamicFieldDTO dynamicField) {
|
||||
ChartSeniorAssistDTO conditionField = new ChartSeniorAssistDTO();
|
||||
conditionField.setFieldId(Long.parseLong(dynamicField.getFieldId()));
|
||||
conditionField.setValue(dynamicField.getSummary());
|
||||
return conditionField;
|
||||
}
|
||||
|
||||
protected String assistSQL(String sql, List<ChartViewFieldDTO> assistFields) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (int i = 0; i < assistFields.size(); i++) {
|
||||
@ -464,7 +578,8 @@ public class DefaultChartHandler extends AbstractChartPlugin {
|
||||
if (StringUtils.isNotEmpty(compareCalc.getType())
|
||||
&& !StringUtils.equalsIgnoreCase(compareCalc.getType(), "none")) {
|
||||
if (Arrays.asList(ChartConstants.M_Y).contains(compareCalc.getType())) {
|
||||
if (StringUtils.equalsIgnoreCase(compareCalc.getField() + "", filterDTO.getFieldId()) && filterDTO.getFilterType() == 0) {
|
||||
if (StringUtils.equalsIgnoreCase(compareCalc.getField() + "", filterDTO.getFieldId())
|
||||
&& (filterDTO.getFilterType() == 0 || filterDTO.getFilterType() == 2)) {
|
||||
// -1 year
|
||||
try {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
|
@ -120,11 +120,11 @@ public class YoyChartHandler extends DefaultChartHandler {
|
||||
expandedResult.setQuerySql(originSql);
|
||||
}
|
||||
// 同环比数据排序
|
||||
expandedResult.setOriginData(sortData(view, expandedResult.getOriginData()));
|
||||
expandedResult.setOriginData(sortData(view, expandedResult.getOriginData(),formatResult));
|
||||
return expandedResult;
|
||||
}
|
||||
|
||||
public static List<String[]> sortData(ChartViewDTO view, List<String[]> data) {
|
||||
public static List<String[]> sortData(ChartViewDTO view, List<String[]> data, AxisFormatResult formatResult) {
|
||||
// 维度排序
|
||||
List<ChartViewFieldDTO> xAxisSortList = view.getXAxis().stream().filter(x -> !StringUtils.equalsIgnoreCase("none", x.getSort())).toList();
|
||||
// 指标排序
|
||||
@ -135,11 +135,9 @@ public class YoyChartHandler extends DefaultChartHandler {
|
||||
ChartViewFieldDTO firstYAxis = yAxisSortList.getFirst();
|
||||
boolean asc = firstYAxis.getSort().equalsIgnoreCase("asc");
|
||||
// 维度指标
|
||||
List<ChartViewFieldDTO> allAxisList = Stream.of(
|
||||
view.getXAxis(),
|
||||
view.getXAxisExt(),
|
||||
view.getYAxis()
|
||||
).flatMap(List::stream).toList();
|
||||
List<ChartViewFieldDTO> allAxisList = new ArrayList<>();
|
||||
allAxisList.addAll(formatResult.getAxisMap().get(ChartAxis.xAxis));
|
||||
allAxisList.addAll(formatResult.getAxisMap().get(ChartAxis.yAxis));
|
||||
int index = findIndex(allAxisList, firstYAxis.getId());
|
||||
return sortData(data, asc, index);
|
||||
}
|
||||
|
@ -12,8 +12,9 @@ import io.dataease.extensions.datasource.provider.Provider;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import io.dataease.extensions.view.util.ChartDataUtil;
|
||||
import io.dataease.extensions.view.util.FieldUtil;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import io.dataease.utils.BeanUtils;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -21,6 +22,8 @@ import org.springframework.stereotype.Component;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class TableInfoHandler extends DefaultChartHandler {
|
||||
@ -135,6 +138,32 @@ public class TableInfoHandler extends DefaultChartHandler {
|
||||
calcResult.setContext(filterResult.getContext());
|
||||
calcResult.setQuerySql(querySql);
|
||||
calcResult.setOriginData(data);
|
||||
try {
|
||||
var dynamicAssistFields = getDynamicThresholdFields(view);
|
||||
Set<Long> fieldIds = xAxis.stream().map(ChartViewFieldDTO::getId).collect(Collectors.toSet());
|
||||
List<ChartViewFieldDTO> finalXAxis = xAxis;
|
||||
dynamicAssistFields.forEach(i -> {
|
||||
if (!fieldIds.contains(i.getFieldId())) {
|
||||
ChartViewFieldDTO fieldDTO = new ChartViewFieldDTO();
|
||||
BeanUtils.copyBean(fieldDTO, i.getCurField());
|
||||
finalXAxis.add(fieldDTO);
|
||||
}
|
||||
});
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var assistFields = getAssistFields(dynamicAssistFields, yAxis, xAxis);
|
||||
if (CollectionUtils.isNotEmpty(assistFields)) {
|
||||
var req = new DatasourceRequest();
|
||||
req.setDsList(dsMap);
|
||||
var assistSql = assistSQL(querySql, assistFields);
|
||||
req.setQuery(assistSql);
|
||||
logger.debug("calcite assistSql sql: " + assistSql);
|
||||
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
|
||||
calcResult.setAssistData(assistData);
|
||||
calcResult.setDynamicAssistFields(dynamicAssistFields);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return calcResult;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,18 @@
|
||||
package io.dataease.chart.charts.impl.table;
|
||||
|
||||
import io.dataease.chart.charts.impl.YoyChartHandler;
|
||||
import io.dataease.extensions.datasource.dto.DatasourceRequest;
|
||||
import io.dataease.extensions.datasource.dto.DatasourceSchemaDTO;
|
||||
import io.dataease.extensions.datasource.model.SQLMeta;
|
||||
import io.dataease.extensions.datasource.provider.Provider;
|
||||
import io.dataease.extensions.view.dto.*;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author jianneng
|
||||
* @date 2024/9/11 11:37
|
||||
@ -12,4 +21,29 @@ import org.springframework.stereotype.Component;
|
||||
public class TableNormalHandler extends YoyChartHandler {
|
||||
@Getter
|
||||
private String type = "table-normal";
|
||||
|
||||
@Override
|
||||
public <T extends ChartCalcDataResult> T calcChartResult(ChartViewDTO view, AxisFormatResult formatResult, CustomFilterResult filterResult, Map<String, Object> sqlMap, SQLMeta sqlMeta, Provider provider) {
|
||||
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
|
||||
var result = (T) super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
|
||||
try {
|
||||
var originSql = result.getQuerySql();
|
||||
var dynamicAssistFields = getDynamicThresholdFields(view);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var assistFields = getAssistFields(dynamicAssistFields, yAxis);
|
||||
if (CollectionUtils.isNotEmpty(assistFields)) {
|
||||
var req = new DatasourceRequest();
|
||||
req.setDsList(dsMap);
|
||||
var assistSql = assistSQL(originSql, assistFields);
|
||||
req.setQuery(assistSql);
|
||||
logger.debug("calcite assistSql sql: " + assistSql);
|
||||
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
|
||||
result.setAssistData(assistData);
|
||||
result.setDynamicAssistFields(dynamicAssistFields);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import io.dataease.utils.BeanUtils;
|
||||
import io.dataease.utils.IDUtils;
|
||||
import io.dataease.utils.JsonUtil;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.util.function.Tuple2;
|
||||
@ -35,6 +36,25 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
T result = super.calcChartResult(view, formatResult, filterResult, sqlMap, sqlMeta, provider);
|
||||
Map<String, Object> customCalc = calcCustomExpr(view, filterResult, sqlMap, sqlMeta, provider);
|
||||
result.getData().put("customCalc", customCalc);
|
||||
try {
|
||||
var dsMap = (Map<Long, DatasourceSchemaDTO>) sqlMap.get("dsMap");
|
||||
var originSql = result.getQuerySql();
|
||||
var dynamicAssistFields = getDynamicThresholdFields(view);
|
||||
var yAxis = formatResult.getAxisMap().get(ChartAxis.yAxis);
|
||||
var assistFields = getAssistFields(dynamicAssistFields, yAxis);
|
||||
if (CollectionUtils.isNotEmpty(assistFields)) {
|
||||
var req = new DatasourceRequest();
|
||||
req.setDsList(dsMap);
|
||||
var assistSql = assistSQL(originSql, assistFields);
|
||||
req.setQuery(assistSql);
|
||||
logger.debug("calcite assistSql sql: " + assistSql);
|
||||
var assistData = (List<String[]>) provider.fetchResultField(req).get("data");
|
||||
result.setAssistData(assistData);
|
||||
result.setDynamicAssistFields(dynamicAssistFields);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -54,7 +74,9 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
var rowAxis = view.getXAxis();
|
||||
var colAxis = view.getXAxisExt();
|
||||
var dataMap = new HashMap<String, Object>();
|
||||
var quotaIds = view.getYAxis().stream().map(ChartViewFieldDTO::getDataeaseName).collect(Collectors.toSet());
|
||||
if (CollectionUtils.isEmpty(rowAxis)) {
|
||||
return dataMap;
|
||||
}
|
||||
// 行总计,列维度聚合加上自定义字段
|
||||
var row = tableTotal.getRow();
|
||||
if (row.isShowGrandTotals()) {
|
||||
@ -96,7 +118,7 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
}
|
||||
// 列总计,行维度聚合加上自定义字段
|
||||
var col = tableTotal.getCol();
|
||||
if (col.isShowGrandTotals()) {
|
||||
if (col.isShowGrandTotals() && CollectionUtils.isNotEmpty(colAxis)) {
|
||||
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
|
||||
if (!yAxis.isEmpty()) {
|
||||
var result = getData(sqlMeta, rowAxis, yAxis, allFields, crossDs, dsMap, view, provider, needOrder);
|
||||
@ -109,7 +131,7 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
}
|
||||
}
|
||||
// 列小计,行维度聚合,自定义指标数 * (列维度的数量 - 1)
|
||||
if (col.isShowSubTotals()) {
|
||||
if (col.isShowSubTotals() && colAxis.size() >= 2) {
|
||||
var yAxis = getCustomFields(view, col.getCalcSubTotals().getCfg());
|
||||
if (!yAxis.isEmpty()) {
|
||||
var tmpData = new ArrayList<Map<String, Object>>();
|
||||
@ -153,7 +175,7 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
}
|
||||
}
|
||||
// 行总计里面的列小计
|
||||
if (row.isShowGrandTotals() && col.isShowSubTotals()) {
|
||||
if (row.isShowGrandTotals() && col.isShowSubTotals() && colAxis.size() >= 2) {
|
||||
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
|
||||
if (!yAxis.isEmpty()) {
|
||||
var tmpData = new ArrayList<Map<String, Object>>();
|
||||
@ -174,7 +196,7 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
}
|
||||
}
|
||||
// 列总计里面的行小计
|
||||
if (col.isShowGrandTotals() && row.isShowGrandTotals()) {
|
||||
if (col.isShowGrandTotals() && row.isShowGrandTotals() && rowAxis.size() >= 2) {
|
||||
var yAxis = getCustomFields(view, row.getCalcTotals().getCfg());
|
||||
if (!yAxis.isEmpty()) {
|
||||
var tmpData = new ArrayList<Map<String, Object>>();
|
||||
@ -195,7 +217,7 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
}
|
||||
}
|
||||
// 行小计和列小计相交部分
|
||||
if (row.isShowSubTotals() && col.isShowSubTotals()) {
|
||||
if (row.isShowSubTotals() && col.isShowSubTotals() && colAxis.size() >= 2 && rowAxis.size() >= 2) {
|
||||
var yAxis = getCustomFields(view, col.getCalcTotals().getCfg());
|
||||
if (!yAxis.isEmpty()) {
|
||||
var tmpData = new ArrayList<List<Map<String, Object>>>();
|
||||
@ -230,6 +252,14 @@ public class TablePivotHandler extends GroupChartHandler {
|
||||
|
||||
private Map<String, Object> buildCustomCalcResult(List<String[]> data, List<ChartViewFieldDTO> dimAxis, List<ChartViewFieldDTO> quotaAxis) {
|
||||
var rootResult = new HashMap<String, Object>();
|
||||
if (CollectionUtils.isEmpty(dimAxis)) {
|
||||
var rowData = data.getFirst();
|
||||
for (int i = 0; i < rowData.length; i++) {
|
||||
var qAxis = quotaAxis.get(i);
|
||||
rootResult.put(qAxis.getDataeaseName(), rowData[i]);
|
||||
}
|
||||
return rootResult;
|
||||
}
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
var rowData = data.get(i);
|
||||
Map<String, Object> curSubMap = rootResult;
|
||||
|
@ -1,9 +1,9 @@
|
||||
package io.dataease.home;
|
||||
|
||||
import io.dataease.license.utils.LicenseUtil;
|
||||
import io.dataease.home.manage.DeIndexManage;
|
||||
import io.dataease.utils.ModelUtils;
|
||||
import io.dataease.utils.RsaUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@ -13,8 +13,9 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequestMapping
|
||||
public class RestIndexController {
|
||||
|
||||
@Value("${dataease.xpack-front-distributed:false}")
|
||||
private boolean xpackFrontDistributed;
|
||||
|
||||
@Resource
|
||||
private DeIndexManage deIndexManage;
|
||||
|
||||
@GetMapping("/dekey")
|
||||
@ResponseBody
|
||||
@ -31,8 +32,8 @@ public class RestIndexController {
|
||||
|
||||
@GetMapping("/xpackModel")
|
||||
@ResponseBody
|
||||
public boolean xpackModel() {
|
||||
return xpackFrontDistributed && LicenseUtil.licenseValid();
|
||||
public Boolean xpackModel() {
|
||||
return deIndexManage.xpackModel();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package io.dataease.home.manage;
|
||||
|
||||
import io.dataease.license.config.XpackInteract;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DeIndexManage {
|
||||
|
||||
@XpackInteract(value = "deIndexManage", replace = true)
|
||||
public Boolean xpackModel() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -5,14 +5,17 @@ import com.auth0.jwt.JWTCreator;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import io.dataease.api.permissions.login.dto.PwdLoginDTO;
|
||||
import io.dataease.auth.bo.TokenUserBO;
|
||||
import io.dataease.auth.config.SubstituleLoginConfig;
|
||||
import io.dataease.auth.vo.TokenVO;
|
||||
import io.dataease.exception.DEException;
|
||||
import io.dataease.i18n.Translator;
|
||||
import io.dataease.utils.LogUtil;
|
||||
import io.dataease.utils.Md5Utils;
|
||||
import io.dataease.utils.RsaUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@Component
|
||||
@ConditionalOnMissingBean(name = "loginServer")
|
||||
@ -21,11 +24,26 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class SubstituleLoginServer {
|
||||
|
||||
@PostMapping("/login/localLogin")
|
||||
public TokenVO localLogin(PwdLoginDTO dto) {
|
||||
public TokenVO localLogin(@RequestBody PwdLoginDTO dto) {
|
||||
|
||||
String name = dto.getName();
|
||||
name = RsaUtils.decryptStr(name);
|
||||
String pwd = dto.getPwd();
|
||||
pwd = RsaUtils.decryptStr(pwd);
|
||||
|
||||
dto.setName(name);
|
||||
dto.setPwd(pwd);
|
||||
|
||||
if (!StringUtils.equals("admin", name)) {
|
||||
DEException.throwException("仅admin账号可用");
|
||||
}
|
||||
if (!StringUtils.equals(pwd, SubstituleLoginConfig.getPwd())) {
|
||||
DEException.throwException(Translator.get("i18n_login_name_pwd_err"));
|
||||
}
|
||||
TokenUserBO tokenUserBO = new TokenUserBO();
|
||||
tokenUserBO.setUserId(1L);
|
||||
tokenUserBO.setDefaultOid(1L);
|
||||
String md5Pwd = "83d923c9f1d8fcaa46cae0ed2aaa81b5";
|
||||
String md5Pwd = Md5Utils.md5(pwd);
|
||||
return generate(tokenUserBO, md5Pwd);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,10 @@
|
||||
ALTER TABLE `visualization_outer_params_info`
|
||||
ADD COLUMN `required` tinyint(1) DEFAULT 0 COMMENT '是否必填',
|
||||
ADD COLUMN `required` tinyint(1) DEFAULT 0 COMMENT '是否必填',
|
||||
ADD COLUMN `default_value` varchar(255) DEFAULT NULL COMMENT '默认值 JSON格式',
|
||||
ADD COLUMN `enabled_default` tinyint(1) NULL DEFAULT 0 COMMENT '是否启用默认值';
|
||||
update visualization_outer_params_info
|
||||
set required =0;
|
||||
|
||||
ALTER TABLE `xpack_report_info`
|
||||
ADD COLUMN `show_watermark` tinyint(1) NOT NULL DEFAULT 0 COMMENT '显示水印' AFTER `rid`;
|
||||
|
||||
ALTER TABLE `visualization_link_jump_info`
|
||||
ADD COLUMN `window_size` varchar(255) NULL DEFAULT 'middle' COMMENT '窗口大小large middle small';
|
||||
|
@ -0,0 +1 @@
|
||||
INSERT INTO area (id, level, name, pid) VALUES ('156440315', 'district', '大鹏新区', '156440300');
|
@ -1,13 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/dataease.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/pages/index/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/pages/index/main.ts"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -3,10 +3,8 @@
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
|
||||
<title>DataEase</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -14,4 +12,4 @@
|
||||
<script type="module" src="/src/pages/mobile/main.ts"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
Before Width: | Height: | Size: 742 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 742 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 741 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 742 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 744 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 744 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 147 KiB |
@ -1,3 +1,3 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0893 1.91058C17.933 1.7543 17.721 1.6665 17.5 1.6665H2.50002C2.27901 1.6665 2.06705 1.7543 1.91076 1.91058C1.75448 2.06686 1.66669 2.27882 1.66669 2.49984V17.4998C1.66669 17.7209 1.75448 17.9328 1.91076 18.0891C2.06705 18.2454 2.27901 18.3332 2.50002 18.3332H17.5C17.721 18.3332 17.933 18.2454 18.0893 18.0891C18.2456 17.9328 18.3334 17.7209 18.3334 17.4998V2.49984C18.3334 2.27882 18.2456 2.06686 18.0893 1.91058ZM10.8334 5.83323H13.75C13.8605 5.83323 13.9665 5.87713 14.0446 5.95527C14.1228 6.03341 14.1667 6.13939 14.1667 6.2499V7.08323C14.1667 7.19374 14.1228 7.29972 14.0446 7.37786C13.9665 7.456 13.8605 7.4999 13.75 7.4999H10.8334V13.7499C10.8334 13.8046 10.8226 13.8588 10.8016 13.9094C10.7807 13.9599 10.75 14.0058 10.7113 14.0445C10.6726 14.0832 10.6267 14.1139 10.5761 14.1348C10.5256 14.1558 10.4714 14.1666 10.4167 14.1666H9.58335C9.52864 14.1666 9.47446 14.1558 9.4239 14.1348C9.37335 14.1139 9.32742 14.0832 9.28873 14.0445C9.25004 14.0058 9.21934 13.9599 9.1984 13.9094C9.17747 13.8588 9.16669 13.8046 9.16669 13.7499V7.4999H6.25002C6.13951 7.4999 6.03353 7.456 5.95539 7.37786C5.87725 7.29972 5.83335 7.19374 5.83335 7.08323V6.2499C5.83335 6.13939 5.87725 6.03341 5.95539 5.95527C6.03353 5.87713 6.13951 5.83323 6.25002 5.83323H9.16669C9.16669 5.83323 10.8334 5.85657 10.8334 5.83323Z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.0893 1.91058C17.933 1.7543 17.721 1.6665 17.5 1.6665H2.50002C2.27901 1.6665 2.06705 1.7543 1.91076 1.91058C1.75448 2.06686 1.66669 2.27882 1.66669 2.49984V17.4998C1.66669 17.7209 1.75448 17.9328 1.91076 18.0891C2.06705 18.2454 2.27901 18.3332 2.50002 18.3332H17.5C17.721 18.3332 17.933 18.2454 18.0893 18.0891C18.2456 17.9328 18.3334 17.7209 18.3334 17.4998V2.49984C18.3334 2.27882 18.2456 2.06686 18.0893 1.91058ZM10.8334 5.83323H13.75C13.8605 5.83323 13.9665 5.87713 14.0446 5.95527C14.1228 6.03341 14.1667 6.13939 14.1667 6.2499V7.08323C14.1667 7.19374 14.1228 7.29972 14.0446 7.37786C13.9665 7.456 13.8605 7.4999 13.75 7.4999H10.8334V13.7499C10.8334 13.8046 10.8226 13.8588 10.8016 13.9094C10.7807 13.9599 10.75 14.0058 10.7113 14.0445C10.6726 14.0832 10.6267 14.1139 10.5761 14.1348C10.5256 14.1558 10.4714 14.1666 10.4167 14.1666H9.58335C9.52864 14.1666 9.47446 14.1558 9.4239 14.1348C9.37335 14.1139 9.32742 14.0832 9.28873 14.0445C9.25004 14.0058 9.21934 13.9599 9.1984 13.9094C9.17747 13.8588 9.16669 13.8046 9.16669 13.7499V7.4999H6.25002C6.13951 7.4999 6.03353 7.456 5.95539 7.37786C5.87725 7.29972 5.83335 7.19374 5.83335 7.08323V6.2499C5.83335 6.13939 5.87725 6.03341 5.95539 5.95527C6.03353 5.87713 6.13951 5.83323 6.25002 5.83323H9.16669C9.16669 5.83323 10.8334 5.85657 10.8334 5.83323Z" fill="#307EFF"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 742 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 739 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 742 KiB After Width: | Height: | Size: 63 KiB |
@ -531,7 +531,7 @@ const initOpenHandler = newWindow => {
|
||||
is-label
|
||||
themes="light"
|
||||
placement="bottom"
|
||||
:base-width="315"
|
||||
:base-width="328"
|
||||
:icon-name="dvMedia"
|
||||
title="媒体"
|
||||
>
|
||||
|
@ -195,7 +195,7 @@ const componentBackgroundStyle = computed(() => {
|
||||
if (backgroundColorSelect && backgroundColor) {
|
||||
colorRGBA = backgroundColor
|
||||
}
|
||||
if (backgroundImageEnable) {
|
||||
if (backgroundImageEnable || (config.value.innerType === 'VQuery' && backgroundColorSelect)) {
|
||||
if (backgroundType === 'outerImage' && typeof outerImage === 'string') {
|
||||
style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}`
|
||||
} else {
|
||||
|
@ -126,6 +126,9 @@ const baseComponentData = computed(() =>
|
||||
)
|
||||
const canvasStyle = computed(() => {
|
||||
let style = {}
|
||||
if (isMainCanvas(canvasId.value) && !isDashboard()) {
|
||||
style['overflowY'] = 'hidden !important'
|
||||
}
|
||||
if (canvasStyleData.value && canvasStyleData.value.width && isMainCanvas(canvasId.value)) {
|
||||
style = {
|
||||
...getCanvasStyle(canvasStyleData.value),
|
||||
@ -383,7 +386,9 @@ const filterBtnShow = computed(
|
||||
const datasetParamsInit = item => {
|
||||
customDatasetParamsRef.value?.optInit(item)
|
||||
}
|
||||
|
||||
const dataVPreview = computed(
|
||||
() => dvInfo.value.type === 'dataV' && canvasId.value === 'canvas-main'
|
||||
)
|
||||
defineExpose({
|
||||
restore
|
||||
})
|
||||
@ -394,7 +399,7 @@ defineExpose({
|
||||
:id="domId"
|
||||
class="canvas-container"
|
||||
:style="canvasStyle"
|
||||
:class="{ 'de-download-custom': downloadStatus }"
|
||||
:class="{ 'de-download-custom': downloadStatus, 'datav-preview': dataVPreview }"
|
||||
ref="previewCanvas"
|
||||
@mousedown="handleMouseDown"
|
||||
>
|
||||
@ -467,4 +472,8 @@ defineExpose({
|
||||
.fix-button {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
.datav-preview {
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -521,13 +521,14 @@ const handleMouseDownOnShape = e => {
|
||||
const left = curX - startX + startLeft
|
||||
pos['top'] = top
|
||||
pos['left'] = left
|
||||
// 非主画布非分组画布的情况 需要检测是否从Tab中移除组件(向左移除30px 或者向右移除30px)
|
||||
// 非主画布非分组画布的情况 需要检测是否从Tab中移除组件(向左移除30px 或者向右移除30px 向左移除30px)
|
||||
// 因为仪表板中组件向下移动可能只是为了挤占空间 不一定是为了移出 这里无法判断明确意图 暂时支不支持向下移出
|
||||
// 大屏和仪表板暂时做位置算法区分 仪表板暂时使用curX 因为缩放的影响 大屏使用 tab位置 + 组件位置(相对内部画布)+初始触发点
|
||||
if (
|
||||
!isMainCanvas(canvasId.value) &&
|
||||
!isGroupCanvas(canvasId.value) &&
|
||||
!isGroupArea.value &&
|
||||
(left < -30 || left + componentWidth - canvasWidth > 30)
|
||||
(top < -30 || left < -30 || left + componentWidth - canvasWidth > 30)
|
||||
) {
|
||||
contentDisplay.value = false
|
||||
dvMainStore.setMousePointShadowMap({
|
||||
@ -869,7 +870,7 @@ const componentBackgroundStyle = computed(() => {
|
||||
if (backgroundColorSelect && backgroundColor) {
|
||||
colorRGBA = backgroundColor
|
||||
}
|
||||
if (backgroundImageEnable) {
|
||||
if (backgroundImageEnable || (element.value.innerType === 'VQuery' && backgroundColorSelect)) {
|
||||
if (backgroundType === 'outerImage' && typeof outerImage === 'string') {
|
||||
style['background'] = `url(${imgUrlTrans(outerImage)}) no-repeat ${colorRGBA}`
|
||||
} else {
|
||||
|
@ -12,6 +12,7 @@ import * as vueRouter from 'vue-router'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import request from '@/config/axios'
|
||||
const { wsCache } = useCache()
|
||||
import { isNull } from '@/utils/utils'
|
||||
|
||||
const plugin = ref()
|
||||
|
||||
@ -103,11 +104,15 @@ onMounted(async () => {
|
||||
let distributed = false
|
||||
if (wsCache.get(key) === null) {
|
||||
const res = await xpackModelApi()
|
||||
wsCache.set('xpack-model-distributed', res.data)
|
||||
wsCache.set('xpack-model-distributed', isNull(res.data) ? 'null' : res.data)
|
||||
distributed = res.data
|
||||
} else {
|
||||
distributed = wsCache.get(key)
|
||||
}
|
||||
if (isNull(distributed)) {
|
||||
emits('loadFail')
|
||||
return
|
||||
}
|
||||
if (distributed) {
|
||||
const moduleName = getModuleName()
|
||||
if (window[moduleName]) {
|
||||
|
@ -12,6 +12,7 @@ import * as echarts from 'echarts'
|
||||
import router from '@/router'
|
||||
import tinymce from 'tinymce/tinymce'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { isNull } from '@/utils/utils'
|
||||
|
||||
const { wsCache } = useCache()
|
||||
|
||||
@ -107,11 +108,16 @@ onMounted(async () => {
|
||||
let distributed = false
|
||||
if (wsCache.get(key) === null) {
|
||||
const res = await xpackModelApi()
|
||||
wsCache.set('xpack-model-distributed', res.data)
|
||||
const resData = isNull(res.data) ? 'null' : res.data
|
||||
wsCache.set('xpack-model-distributed', resData)
|
||||
distributed = res.data
|
||||
} else {
|
||||
distributed = wsCache.get(key)
|
||||
}
|
||||
if (isNull(distributed)) {
|
||||
emits('loadFail')
|
||||
return
|
||||
}
|
||||
if (distributed) {
|
||||
if (window['DEXPack']) {
|
||||
const xpack = await window['DEXPack'].mapping[attrs.jsname]
|
||||
|
@ -141,6 +141,12 @@
|
||||
placeholder="选择边框..."
|
||||
@change="onBackgroundChange"
|
||||
>
|
||||
<template v-if="state.commonBackground.innerImage" #prefix>
|
||||
<border-option-prefix
|
||||
inner-image-color="state.commonBackground.innerImageColor"
|
||||
:url="state.commonBackground.innerImage"
|
||||
></border-option-prefix>
|
||||
</template>
|
||||
<el-option
|
||||
v-for="(item, index) in state.BackgroundShowMap['default']"
|
||||
:key="index"
|
||||
@ -223,6 +229,8 @@ import elementResizeDetectorMaker from 'element-resize-detector'
|
||||
import { ElMessage } from 'element-plus-secondary'
|
||||
import BoardItem from '@/components/visualization/component-background/BoardItem.vue'
|
||||
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||
import PictureOptionPrefix from '@/custom-component/picture-group/PictureOptionPrefix.vue'
|
||||
import BorderOptionPrefix from '@/components/visualization/component-background/BorderOptionPrefix.vue'
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const { t } = useI18n()
|
||||
const emits = defineEmits(['onBackgroundChange'])
|
||||
|
@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="img-option-prefix">
|
||||
<Icon
|
||||
><component
|
||||
:style="{ color: innerImageColor, width: '20px', height: '20px' }"
|
||||
class="svg-icon svg-background"
|
||||
:is="iconBoardMap[mainIconClass(url)]"
|
||||
></component
|
||||
></Icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { iconBoardMap } from '@/components/icon-group/board-list'
|
||||
import { toRefs } from 'vue'
|
||||
import { Icon } from '@/components/icon-custom'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
url: any
|
||||
innerImageColor: string
|
||||
}>(),
|
||||
{}
|
||||
)
|
||||
|
||||
const { innerImageColor } = toRefs(props)
|
||||
|
||||
const mainIconClass = url => {
|
||||
return url.replace('board/', '').replace('.svg', '')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.img-option-prefix {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
}
|
||||
</style>
|
@ -143,7 +143,9 @@ const stopEvent = e => {
|
||||
<el-collapse-item :effect="themes" title="位置" name="position" v-if="positionComponentShow">
|
||||
<component-position :themes="themes" />
|
||||
</el-collapse-item>
|
||||
|
||||
<slot name="dataset" />
|
||||
<slot name="carousel" />
|
||||
<slot name="threshold" />
|
||||
<el-collapse-item
|
||||
:effect="themes"
|
||||
title="背景"
|
||||
|
@ -2,6 +2,7 @@
|
||||
import iconVideo from '@/assets/svg/icon-video.svg'
|
||||
import dvPictureShow from '@/assets/svg/dv-picture-show.svg'
|
||||
import iconStream from '@/assets/svg/icon-stream.svg'
|
||||
import pictureGroupOrigin from '@/assets/svg/picture-group-origin.svg'
|
||||
import { toRefs } from 'vue'
|
||||
import eventBus from '@/utils/eventBus'
|
||||
import DragComponent from '@/custom-component/component-group/DragComponent.vue'
|
||||
@ -31,8 +32,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const { dvModel } = toRefs(props)
|
||||
const newComponent = params => {
|
||||
eventBus.emit('handleNew', { componentName: params, innerType: params })
|
||||
const newComponent = (componentName, innerType) => {
|
||||
eventBus.emit('handleNew', { componentName: componentName, innerType: innerType })
|
||||
}
|
||||
|
||||
const handleDragStart = e => {
|
||||
@ -47,25 +48,36 @@ const handleDragEnd = e => {
|
||||
<template>
|
||||
<div class="group" @dragstart="handleDragStart" @dragend="handleDragEnd">
|
||||
<drag-component
|
||||
class="media-component"
|
||||
:themes="themes"
|
||||
:icon="dvPictureShow"
|
||||
label="图片"
|
||||
drag-info="Picture&Picture"
|
||||
v-on:click="newComponent('Picture')"
|
||||
v-on:click="newComponent('Picture', 'Picture')"
|
||||
></drag-component>
|
||||
<drag-component
|
||||
class="media-component"
|
||||
:themes="themes"
|
||||
:icon="iconVideo"
|
||||
label="视频"
|
||||
drag-info="DeVideo&DeVideo"
|
||||
v-on:click="newComponent('DeVideo')"
|
||||
v-on:click="newComponent('DeVideo', 'DeVideo')"
|
||||
></drag-component>
|
||||
<drag-component
|
||||
class="media-component"
|
||||
:themes="themes"
|
||||
:icon="iconStream"
|
||||
label="流媒体"
|
||||
drag-info="DeStreamMedia&DeStreamMedia"
|
||||
v-on:click="newComponent('DeStreamMedia')"
|
||||
v-on:click="newComponent('DeStreamMedia', 'DeStreamMedia')"
|
||||
></drag-component>
|
||||
<drag-component
|
||||
class="media-component"
|
||||
:themes="themes"
|
||||
:icon="pictureGroupOrigin"
|
||||
label="图片组"
|
||||
drag-info="UserView&picture-group"
|
||||
v-on:click="newComponent('UserView', 'picture-group')"
|
||||
></drag-component>
|
||||
</div>
|
||||
</template>
|
||||
@ -73,6 +85,9 @@ const handleDragEnd = e => {
|
||||
<style lang="less" scoped>
|
||||
.group {
|
||||
padding: 12px 8px;
|
||||
display: inline-flex;
|
||||
}
|
||||
.media-component {
|
||||
float: left;
|
||||
margin: 0 6px !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,200 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { ElIcon, ElMessage } from 'element-plus-secondary'
|
||||
import { ref, onMounted, onBeforeUnmount, watch, PropType, computed } from 'vue'
|
||||
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
import eventBus from '@/utils/eventBus'
|
||||
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { toRefs } from 'vue'
|
||||
const { t } = useI18n()
|
||||
import { PropType } from 'vue'
|
||||
import PictureGroupUploadAttr from '@/custom-component/picture-group/PictureGroupUploadAttr.vue'
|
||||
import PictureGroupDatasetSelect from '@/custom-component/picture-group/PictureGroupDatasetSelect.vue'
|
||||
import CarouselSetting from '@/custom-component/common/CarouselSetting.vue'
|
||||
import PictureGroupThreshold from '@/custom-component/picture-group/PictureGroupThreshold.vue'
|
||||
|
||||
const props = defineProps({
|
||||
themes: {
|
||||
type: String as PropType<EditorTheme>,
|
||||
default: 'dark'
|
||||
},
|
||||
element: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
propValue: {
|
||||
urlList: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const { element } = toRefs(props)
|
||||
|
||||
const { curComponent } = storeToRefs(dvMainStore)
|
||||
|
||||
const fileList = ref([])
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false)
|
||||
const uploadDisabled = ref(false)
|
||||
const files = ref(null)
|
||||
const maxImageSize = 15000000
|
||||
|
||||
const handlePictureCardPreview = file => {
|
||||
dialogImageUrl.value = file.url
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleRemove = (_, fileList) => {
|
||||
uploadDisabled.value = false
|
||||
element.value.propValue['urlList'] = []
|
||||
fileList.value = []
|
||||
snapshotStore.recordSnapshotCache()
|
||||
}
|
||||
async function upload(file) {
|
||||
uploadFileResult(file.file, fileUrl => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
element.value.propValue.urlList.push({ name: file.file.name, url: fileUrl })
|
||||
})
|
||||
}
|
||||
|
||||
const onStyleChange = () => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
}
|
||||
|
||||
const goFile = () => {
|
||||
files.value.click()
|
||||
}
|
||||
|
||||
const reUpload = e => {
|
||||
const file = e.target.files[0]
|
||||
if (file.size > maxImageSize) {
|
||||
sizeMessage()
|
||||
return
|
||||
}
|
||||
uploadFileResult(file, fileUrl => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
element.value.propValue.url = fileUrl
|
||||
fileList.value = [{ name: file.name, url: imgUrlTrans(element.value.propValue.url) }]
|
||||
})
|
||||
}
|
||||
|
||||
const sizeMessage = () => {
|
||||
ElMessage.success('图片大小不符合')
|
||||
}
|
||||
|
||||
const fileListInit = () => {
|
||||
fileList.value = []
|
||||
if (element.value.propValue.urlList && element.value.propValue.urlList.length > 0) {
|
||||
element.value.propValue.urlList.forEach(urlInfo => {
|
||||
fileList.value.push({ name: urlInfo.name, url: imgUrlTrans(urlInfo.url) })
|
||||
})
|
||||
}
|
||||
}
|
||||
const init = () => {
|
||||
fileListInit()
|
||||
}
|
||||
|
||||
const toolTip = computed(() => {
|
||||
return props.themes === 'dark' ? 'ndark' : 'dark'
|
||||
})
|
||||
|
||||
watch(
|
||||
() => element.value.propValue.url,
|
||||
() => {
|
||||
init()
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
eventBus.on('uploadImg', goFile)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
eventBus.off('uploadImg', goFile)
|
||||
})
|
||||
const { curComponent, canvasViewInfo } = storeToRefs(dvMainStore)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-collapse-item :effect="themes" title="图片组" name="picture">
|
||||
<input
|
||||
id="input"
|
||||
ref="files"
|
||||
type="file"
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
hidden
|
||||
@click="
|
||||
e => {
|
||||
e.target.value = ''
|
||||
}
|
||||
"
|
||||
@change="reUpload"
|
||||
/>
|
||||
<el-row class="img-area" :class="`img-area_${themes}`">
|
||||
<el-col style="width: 130px !important">
|
||||
<el-upload
|
||||
<div class="attr-list de-collapse-style">
|
||||
<CommonAttr
|
||||
:themes="themes"
|
||||
:element="curComponent"
|
||||
:background-color-picker-width="197"
|
||||
:background-border-select-width="197"
|
||||
>
|
||||
<template v-slot:dataset>
|
||||
<picture-group-dataset-select
|
||||
:themes="themes"
|
||||
limit="10"
|
||||
action=""
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
class="avatar-uploader"
|
||||
list-type="picture-card"
|
||||
:class="{ disabled: uploadDisabled }"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeUploadCheck"
|
||||
:http-request="upload"
|
||||
:file-list="fileList"
|
||||
:view="canvasViewInfo[curComponent ? curComponent.id : 'default']"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<img-view-dialog v-model="dialogVisible" :image-url="dialogImageUrl"></img-view-dialog>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<span
|
||||
style="margin-top: 2px"
|
||||
v-if="!curComponent.propValue.url"
|
||||
class="image-hint"
|
||||
:class="`image-hint_${themes}`"
|
||||
>
|
||||
支持JPG、PNG、GIF、SVG
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
style="margin: 8px 0 0 -4px"
|
||||
v-if="curComponent.propValue.url"
|
||||
text
|
||||
@click="goFile"
|
||||
>
|
||||
重新上传
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row class="pic-adaptor">
|
||||
<el-form-item
|
||||
v-if="curComponent.style.adaptation"
|
||||
class="form-item form-item-custom"
|
||||
label="图片适应方式"
|
||||
size="small"
|
||||
:effect="themes"
|
||||
>
|
||||
<el-radio-group
|
||||
size="small"
|
||||
v-model="curComponent.style.adaptation"
|
||||
@change="onStyleChange"
|
||||
:effect="themes"
|
||||
>
|
||||
<el-radio label="adaptation" :effect="themes">适应组件</el-radio>
|
||||
<el-radio label="original" :effect="themes">原始尺寸</el-radio>
|
||||
<el-radio label="equiratio" :effect="themes">等比适应</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
</picture-group-dataset-select>
|
||||
</template>
|
||||
<picture-group-upload-attr
|
||||
:themes="themes"
|
||||
:element="curComponent"
|
||||
></picture-group-upload-attr>
|
||||
<template v-slot:carousel>
|
||||
<carousel-setting
|
||||
v-if="curComponent?.innerType === 'picture-group'"
|
||||
:element="curComponent"
|
||||
:themes="themes"
|
||||
></carousel-setting>
|
||||
</template>
|
||||
<template v-slot:threshold>
|
||||
<picture-group-threshold
|
||||
:themes="themes"
|
||||
:view="canvasViewInfo[curComponent ? curComponent.id : 'default']"
|
||||
></picture-group-threshold>
|
||||
</template>
|
||||
</CommonAttr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@ -254,6 +114,8 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
.img-area {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
@ -308,9 +170,9 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-custom {
|
||||
.form-item-dark {
|
||||
.ed-radio {
|
||||
margin-right: 2px !important;
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,205 @@
|
||||
<script setup lang="ts">
|
||||
import { PropType, reactive, toRefs } from 'vue'
|
||||
import { BASE_VIEW_CONFIG } from '@/views/chart/components/editor/util/chart'
|
||||
import DatasetSelect from '@/views/chart/components/editor/dataset-select/DatasetSelect.vue'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
|
||||
const props = defineProps({
|
||||
themes: {
|
||||
type: String as PropType<EditorTheme>,
|
||||
default: 'dark'
|
||||
},
|
||||
view: {
|
||||
type: Object as PropType<ChartObj>,
|
||||
required: false,
|
||||
default() {
|
||||
return { ...BASE_VIEW_CONFIG }
|
||||
}
|
||||
}
|
||||
})
|
||||
const { view } = toRefs(props)
|
||||
const state = reactive({})
|
||||
|
||||
const onDatasetUpdate = () => {
|
||||
useEmitt().emitter.emit('calcData-' + view.value.id, view)
|
||||
snapshotStore.recordSnapshotCache('calc', view.value.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-collapse-item :effect="themes" title="数据集" name="dataset">
|
||||
<dataset-select
|
||||
ref="datasetSelector"
|
||||
v-model="view.tableId"
|
||||
style="flex: 1"
|
||||
:view-id="view.id"
|
||||
:themes="themes"
|
||||
@on-dataset-change="onDatasetUpdate"
|
||||
:state-obj="state"
|
||||
/>
|
||||
</el-collapse-item>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.de-collapse-style {
|
||||
:deep(.ed-collapse-item__header) {
|
||||
height: 36px !important;
|
||||
line-height: 36px !important;
|
||||
font-size: 12px !important;
|
||||
padding: 0 !important;
|
||||
font-weight: 500 !important;
|
||||
|
||||
.ed-collapse-item__arrow {
|
||||
margin: 0 6px 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ed-collapse-item__content) {
|
||||
padding: 16px 8px 0;
|
||||
}
|
||||
:deep(.ed-form-item) {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
:deep(.ed-form-item__label) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled :deep(.el-upload--picture-card) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.avatar-uploader :deep(.ed-upload) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
line-height: 90px;
|
||||
}
|
||||
|
||||
.avatar-uploader :deep(.ed-upload-list li) {
|
||||
width: 80px !important;
|
||||
height: 80px !important;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #eff0f1;
|
||||
border: 1px dashed #dee0e3;
|
||||
border-radius: 4px;
|
||||
|
||||
.ed-icon {
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.img-area {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
&.img-area_dark {
|
||||
:deep(.ed-upload-list__item).is-success {
|
||||
border-color: #434343;
|
||||
}
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #373737;
|
||||
border-color: #434343;
|
||||
.ed-icon {
|
||||
color: #ebebeb;
|
||||
}
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.img-area_light {
|
||||
:deep(.ed-upload-list__item).is-success {
|
||||
border-color: #dee0e3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-hint {
|
||||
color: #8f959e;
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
margin-top: 2px;
|
||||
&.image-hint_dark {
|
||||
color: #757575;
|
||||
}
|
||||
}
|
||||
|
||||
.re-update-span {
|
||||
cursor: pointer;
|
||||
color: var(--ed-color-primary);
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.pic-adaptor {
|
||||
margin: 8px 0 16px 0;
|
||||
:deep(.ed-form-item__content) {
|
||||
margin-top: 8px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-dark {
|
||||
.ed-radio {
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-data {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 16px;
|
||||
|
||||
.tree-btn {
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
background: #fff;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dcdfe6;
|
||||
display: flex;
|
||||
color: #cccccc;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
&.tree-btn--dark {
|
||||
background: rgba(235, 235, 235, 0.05);
|
||||
border-color: #5f5f5f;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #3370ff;
|
||||
border-color: #3370ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-top-border {
|
||||
border-top: none !important;
|
||||
}
|
||||
&.no-top-padding {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
&:nth-child(n + 2) {
|
||||
border-top: 1px solid @side-outline-border-color;
|
||||
}
|
||||
&:first-child {
|
||||
border-top: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,211 @@
|
||||
<script setup lang="ts">
|
||||
import { PropType, toRefs } from 'vue'
|
||||
import { BASE_VIEW_CONFIG } from '@/views/chart/components/editor/util/chart'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import Threshold from '@/views/chart/components/editor/editor-senior/components/Threshold.vue'
|
||||
import { CollapseSwitchItem } from '@/components/collapse-switch-item'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
themes: {
|
||||
type: String as PropType<EditorTheme>,
|
||||
default: 'dark'
|
||||
},
|
||||
view: {
|
||||
type: Object as PropType<ChartObj>,
|
||||
required: false,
|
||||
default() {
|
||||
return { ...BASE_VIEW_CONFIG }
|
||||
}
|
||||
}
|
||||
})
|
||||
const { view } = toRefs(props)
|
||||
|
||||
const onThresholdChange = val => {
|
||||
// do
|
||||
view.value.senior.threshold = val
|
||||
snapshotStore.recordSnapshotCache('calcData', view.value.id)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<collapse-switch-item
|
||||
:effect="themes"
|
||||
:title="t('chart.threshold')"
|
||||
:change-model="view.senior.threshold"
|
||||
v-model="view.senior.threshold.enable"
|
||||
name="threshold"
|
||||
@modelChange="onThresholdChange"
|
||||
>
|
||||
<threshold
|
||||
:themes="themes"
|
||||
:chart="view"
|
||||
:property-inner="['tableThreshold']"
|
||||
@onThresholdChange="onThresholdChange"
|
||||
/>
|
||||
</collapse-switch-item>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.de-collapse-style {
|
||||
:deep(.ed-collapse-item__header) {
|
||||
height: 36px !important;
|
||||
line-height: 36px !important;
|
||||
font-size: 12px !important;
|
||||
padding: 0 !important;
|
||||
font-weight: 500 !important;
|
||||
|
||||
.ed-collapse-item__arrow {
|
||||
margin: 0 6px 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ed-collapse-item__content) {
|
||||
padding: 16px 8px 0;
|
||||
}
|
||||
:deep(.ed-form-item) {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
:deep(.ed-form-item__label) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled :deep(.el-upload--picture-card) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.avatar-uploader :deep(.ed-upload) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
line-height: 90px;
|
||||
}
|
||||
|
||||
.avatar-uploader :deep(.ed-upload-list li) {
|
||||
width: 80px !important;
|
||||
height: 80px !important;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #eff0f1;
|
||||
border: 1px dashed #dee0e3;
|
||||
border-radius: 4px;
|
||||
|
||||
.ed-icon {
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.img-area {
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
&.img-area_dark {
|
||||
:deep(.ed-upload-list__item).is-success {
|
||||
border-color: #434343;
|
||||
}
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #373737;
|
||||
border-color: #434343;
|
||||
.ed-icon {
|
||||
color: #ebebeb;
|
||||
}
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.img-area_light {
|
||||
:deep(.ed-upload-list__item).is-success {
|
||||
border-color: #dee0e3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-hint {
|
||||
color: #8f959e;
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
margin-top: 2px;
|
||||
&.image-hint_dark {
|
||||
color: #757575;
|
||||
}
|
||||
}
|
||||
|
||||
.re-update-span {
|
||||
cursor: pointer;
|
||||
color: var(--ed-color-primary);
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.pic-adaptor {
|
||||
margin: 8px 0 16px 0;
|
||||
:deep(.ed-form-item__content) {
|
||||
margin-top: 8px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-dark {
|
||||
.ed-radio {
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-data {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 16px;
|
||||
|
||||
.tree-btn {
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
background: #fff;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dcdfe6;
|
||||
display: flex;
|
||||
color: #cccccc;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
&.tree-btn--dark {
|
||||
background: rgba(235, 235, 235, 0.05);
|
||||
border-color: #5f5f5f;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #3370ff;
|
||||
border-color: #3370ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-top-border {
|
||||
border-top: none !important;
|
||||
}
|
||||
&.no-top-padding {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
&:nth-child(n + 2) {
|
||||
border-top: 1px solid @side-outline-border-color;
|
||||
}
|
||||
&:first-child {
|
||||
border-top: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,358 @@
|
||||
<script setup lang="ts">
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { ElIcon, ElMessage } from 'element-plus-secondary'
|
||||
import { ref, onMounted, onBeforeUnmount, watch, PropType, computed } from 'vue'
|
||||
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
import eventBus from '@/utils/eventBus'
|
||||
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { toRefs } from 'vue'
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
themes: {
|
||||
type: String as PropType<EditorTheme>,
|
||||
default: 'dark'
|
||||
},
|
||||
element: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
propValue: {
|
||||
urlList: []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const { element } = toRefs(props)
|
||||
|
||||
const { curComponent } = storeToRefs(dvMainStore)
|
||||
|
||||
const fileList = ref([])
|
||||
const dialogImageUrl = ref('')
|
||||
const dialogVisible = ref(false)
|
||||
const uploadDisabled = ref(false)
|
||||
const files = ref(null)
|
||||
const maxImageSize = 15000000
|
||||
|
||||
const handlePictureCardPreview = file => {
|
||||
dialogImageUrl.value = file.url
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleRemove = (_, fileList) => {
|
||||
uploadDisabled.value = false
|
||||
element.value.propValue['urlList'] = []
|
||||
fileList.value = []
|
||||
snapshotStore.recordSnapshotCache()
|
||||
}
|
||||
async function upload(file) {
|
||||
uploadFileResult(file.file, fileUrl => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
element.value.propValue.urlList.push({ name: file.file.name, url: fileUrl })
|
||||
})
|
||||
}
|
||||
|
||||
const onStyleChange = () => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
}
|
||||
|
||||
const goFile = () => {
|
||||
files.value.click()
|
||||
}
|
||||
|
||||
const reUpload = e => {
|
||||
const file = e.target.files[0]
|
||||
if (file.size > maxImageSize) {
|
||||
sizeMessage()
|
||||
return
|
||||
}
|
||||
uploadFileResult(file, fileUrl => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
element.value.propValue.url = fileUrl
|
||||
fileList.value = [{ name: file.name, url: imgUrlTrans(element.value.propValue.url) }]
|
||||
})
|
||||
}
|
||||
|
||||
const sizeMessage = () => {
|
||||
ElMessage.success('图片大小不符合')
|
||||
}
|
||||
|
||||
const fileListInit = () => {
|
||||
fileList.value = []
|
||||
if (element.value.propValue.urlList && element.value.propValue.urlList.length > 0) {
|
||||
element.value.propValue.urlList.forEach(urlInfo => {
|
||||
fileList.value.push({ name: urlInfo.name, url: imgUrlTrans(urlInfo.url) })
|
||||
})
|
||||
}
|
||||
}
|
||||
const init = () => {
|
||||
fileListInit()
|
||||
}
|
||||
|
||||
const toolTip = computed(() => {
|
||||
return props.themes === 'dark' ? 'ndark' : 'dark'
|
||||
})
|
||||
|
||||
watch(
|
||||
() => element.value.propValue.url,
|
||||
() => {
|
||||
init()
|
||||
}
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
eventBus.on('uploadImg', goFile)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
eventBus.off('uploadImg', goFile)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-collapse-item :effect="themes" title="图片组" name="picture">
|
||||
<input
|
||||
id="input"
|
||||
ref="files"
|
||||
type="file"
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
hidden
|
||||
@click="
|
||||
e => {
|
||||
e.target.value = ''
|
||||
}
|
||||
"
|
||||
@change="reUpload"
|
||||
/>
|
||||
<el-row class="img-area" :class="`img-area_${themes}`">
|
||||
<el-col style="width: 130px !important">
|
||||
<el-upload
|
||||
:themes="themes"
|
||||
limit="10"
|
||||
action=""
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
class="avatar-uploader"
|
||||
list-type="picture-card"
|
||||
:class="{ disabled: uploadDisabled }"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeUploadCheck"
|
||||
:http-request="upload"
|
||||
:file-list="fileList"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<img-view-dialog v-model="dialogVisible" :image-url="dialogImageUrl"></img-view-dialog>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<span
|
||||
style="margin-top: 2px"
|
||||
v-if="!curComponent.propValue.url"
|
||||
class="image-hint"
|
||||
:class="`image-hint_${themes}`"
|
||||
>
|
||||
支持JPG、PNG、GIF、SVG
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
style="margin: 8px 0 0 -4px"
|
||||
v-if="curComponent.propValue.url"
|
||||
text
|
||||
@click="goFile"
|
||||
>
|
||||
重新上传
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row class="pic-adaptor">
|
||||
<el-form-item
|
||||
v-if="curComponent.style.adaptation"
|
||||
class="form-item form-item-custom"
|
||||
label="图片适应方式"
|
||||
size="small"
|
||||
:effect="themes"
|
||||
>
|
||||
<el-radio-group
|
||||
size="small"
|
||||
v-model="curComponent.style.adaptation"
|
||||
@change="onStyleChange"
|
||||
:effect="themes"
|
||||
>
|
||||
<el-radio label="adaptation" :effect="themes">适应组件</el-radio>
|
||||
<el-radio label="original" :effect="themes">原始尺寸</el-radio>
|
||||
<el-radio label="equiratio" :effect="themes">等比适应</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.de-collapse-style {
|
||||
:deep(.ed-collapse-item__header) {
|
||||
height: 36px !important;
|
||||
line-height: 36px !important;
|
||||
font-size: 12px !important;
|
||||
padding: 0 !important;
|
||||
font-weight: 500 !important;
|
||||
|
||||
.ed-collapse-item__arrow {
|
||||
margin: 0 6px 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ed-collapse-item__content) {
|
||||
padding: 16px 8px 0;
|
||||
}
|
||||
:deep(.ed-form-item) {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
:deep(.ed-form-item__label) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled :deep(.el-upload--picture-card) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.avatar-uploader :deep(.ed-upload) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
line-height: 90px;
|
||||
}
|
||||
|
||||
.avatar-uploader :deep(.ed-upload-list li) {
|
||||
width: 80px !important;
|
||||
height: 80px !important;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #eff0f1;
|
||||
border: 1px dashed #dee0e3;
|
||||
border-radius: 4px;
|
||||
|
||||
.ed-icon {
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.img-area {
|
||||
margin-top: 10px;
|
||||
overflow: hidden;
|
||||
|
||||
&.img-area_dark {
|
||||
:deep(.ed-upload-list__item).is-success {
|
||||
border-color: #434343;
|
||||
}
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #373737;
|
||||
border-color: #434343;
|
||||
.ed-icon {
|
||||
color: #ebebeb;
|
||||
}
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.img-area_light {
|
||||
:deep(.ed-upload-list__item).is-success {
|
||||
border-color: #dee0e3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image-hint {
|
||||
color: #8f959e;
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
margin-top: 2px;
|
||||
&.image-hint_dark {
|
||||
color: #757575;
|
||||
}
|
||||
}
|
||||
|
||||
.re-update-span {
|
||||
cursor: pointer;
|
||||
color: var(--ed-color-primary);
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.pic-adaptor {
|
||||
margin: 8px 0 16px 0;
|
||||
:deep(.ed-form-item__content) {
|
||||
margin-top: 8px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.form-item-custom {
|
||||
.ed-radio {
|
||||
margin-right: 2px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.drag-data {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 16px;
|
||||
|
||||
.tree-btn {
|
||||
width: 100%;
|
||||
margin-top: 8px;
|
||||
background: #fff;
|
||||
height: 32px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dcdfe6;
|
||||
display: flex;
|
||||
color: #cccccc;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
justify-content: center;
|
||||
font-size: 12px;
|
||||
&.tree-btn--dark {
|
||||
background: rgba(235, 235, 235, 0.05);
|
||||
border-color: #5f5f5f;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: #3370ff;
|
||||
border-color: #3370ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-top-border {
|
||||
border-top: none !important;
|
||||
}
|
||||
&.no-top-padding {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
&:nth-child(n + 2) {
|
||||
border-top: 1px solid @side-outline-border-color;
|
||||
}
|
||||
&:first-child {
|
||||
border-top: none !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="img-option">
|
||||
<div class="img-area" :class="{ 'selected-active': active }">
|
||||
<img draggable="false" :src="imgUrlTrans(urlInfo.url)" />
|
||||
</div>
|
||||
<span :title="urlInfo.name" class="name-area">{{ urlInfo.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { toRefs } from 'vue'
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
urlInfo: any
|
||||
active: boolean
|
||||
}>(),
|
||||
{}
|
||||
)
|
||||
|
||||
const { urlInfo, active } = toRefs(props)
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.img-option {
|
||||
margin: 0 5px !important;
|
||||
width: 88px;
|
||||
height: 88px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
.selected-active {
|
||||
border: 1px solid var(--ed-color-primary-99, rgba(51, 112, 255, 0.6));
|
||||
}
|
||||
.img-area {
|
||||
&:hover {
|
||||
border: 1px dashed var(--ed-color-primary-99, rgba(51, 112, 255, 0.6));
|
||||
}
|
||||
border-radius: 4px;
|
||||
background-color: #f5f6f7;
|
||||
width: 80px;
|
||||
height: 56px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.name-area {
|
||||
margin: 6px 4px;
|
||||
width: 80px;
|
||||
line-height: 20px;
|
||||
font-size: 12px !important;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
white-space: nowrap; /* 不换行 */
|
||||
overflow: hidden; /* 隐藏超出的内容 */
|
||||
text-overflow: ellipsis; /* 用省略号表示被隐藏的部分 */
|
||||
color: rgba(100, 106, 115, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="img-option-prefix">
|
||||
<img draggable="false" :src="imgUrlTrans(url)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
url: any
|
||||
}>(),
|
||||
{}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.img-option-prefix {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-content: center;
|
||||
img {
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -6,6 +6,7 @@
|
||||
@keyup.stop
|
||||
@dblclick="setEdit"
|
||||
@click="onClick"
|
||||
:style="richTextStyle"
|
||||
>
|
||||
<chart-error v-if="isError" :err-msg="errMsg" />
|
||||
<Editor
|
||||
@ -163,7 +164,28 @@ const init = ref({
|
||||
inline: true, // 开启内联模式
|
||||
branding: false,
|
||||
icons: 'vertical-content',
|
||||
vertical_align: element.value.propValue.verticalAlign
|
||||
vertical_align: element.value.propValue.verticalAlign,
|
||||
setup: function (editor) {
|
||||
// 在表格调整大小开始时
|
||||
editor.on('ObjectResizeStart', function (e) {
|
||||
const { target, width, height } = e
|
||||
if (target.nodeName === 'TABLE') {
|
||||
// 将宽高根据缩放比例调整
|
||||
// e.width = width / props.scale
|
||||
// e.height = height / props.scale
|
||||
}
|
||||
})
|
||||
|
||||
// 在表格调整大小结束时
|
||||
editor.on('ObjectResized', function (e) {
|
||||
const { target, width, height } = e
|
||||
if (target.nodeName === 'TABLE') {
|
||||
// 将最终调整的宽高根据缩放比例重设
|
||||
// target.style.width = `${width * props.scale}px`
|
||||
// target.style.height = `${height scaleFactor}px`
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const editStatus = computed(() => {
|
||||
@ -182,6 +204,7 @@ watch(
|
||||
canEdit.value = false
|
||||
reShow()
|
||||
myValue.value = assignment(element.value.propValue.textValue)
|
||||
console.log('===myValue.value=' + myValue.value)
|
||||
ed.setContent(myValue.value)
|
||||
}
|
||||
}
|
||||
@ -241,6 +264,23 @@ const initCurFieldsChange = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const jumpTargetAdaptor = () => {
|
||||
setTimeout(() => {
|
||||
const paragraphs = document.querySelectorAll('p')
|
||||
paragraphs.forEach(p => {
|
||||
// 如果 p 标签已经有 onclick 且包含 event.stopPropagation,则跳过
|
||||
if (
|
||||
p.getAttribute('onclick') &&
|
||||
p.getAttribute('onclick').includes('event.stopPropagation()')
|
||||
) {
|
||||
return // 已经有 stopPropagation,跳过
|
||||
}
|
||||
// 否则添加 onclick 事件
|
||||
p.setAttribute('onclick', 'event.stopPropagation()')
|
||||
})
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const assignment = content => {
|
||||
const on = content.match(/\[(.+?)\]/g)
|
||||
if (on) {
|
||||
@ -266,8 +306,10 @@ const assignment = content => {
|
||||
//De 本地跳转失效问题
|
||||
content = content.replace(/href="#\//g, 'href="/#/')
|
||||
content = content.replace(/href=\\"#\//g, 'href=\\"/#/')
|
||||
content = content.replace(/href=\\"#\//g, 'href=\\"/#/')
|
||||
resetSelect()
|
||||
initFontFamily(content)
|
||||
jumpTargetAdaptor()
|
||||
return content
|
||||
}
|
||||
const initFontFamily = htmlText => {
|
||||
@ -561,6 +603,8 @@ const conditionAdaptor = (chart: Chart) => {
|
||||
return res
|
||||
}
|
||||
|
||||
const richTextStyle = computed(() => [{ '--de-canvas-scale': props.scale }])
|
||||
|
||||
onMounted(() => {
|
||||
viewInit()
|
||||
})
|
||||
@ -583,6 +627,12 @@ defineExpose({
|
||||
width: 0px !important;
|
||||
height: 0px !important;
|
||||
}
|
||||
::v-deep(p) {
|
||||
zoom: var(--de-canvas-scale);
|
||||
}
|
||||
::v-deep(td span) {
|
||||
zoom: var(--de-canvas-scale);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ol) {
|
||||
|
@ -58,18 +58,19 @@ const props = defineProps({
|
||||
|
||||
const { element, view, active, searchCount, scale } = toRefs(props)
|
||||
const autoStyle = computed(() => {
|
||||
if (element.value.innerType === 'rich-text') {
|
||||
return {
|
||||
position: 'absolute',
|
||||
height: 100 / scale.value + '%!important',
|
||||
width: 100 / scale.value + '%!important',
|
||||
left: 50 * (1 - 1 / scale.value) + '%', // 放大余量 除以 2
|
||||
top: 50 * (1 - 1 / scale.value) + '%', // 放大余量 除以 2
|
||||
transform: 'scale(' + scale.value + ')'
|
||||
} as CSSProperties
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
return {}
|
||||
// if (element.value.innerType === 'rich-text') {
|
||||
// return {
|
||||
// position: 'absolute',
|
||||
// height: 100 / scale.value + '%!important',
|
||||
// width: 100 / scale.value + '%!important',
|
||||
// left: 50 * (1 - 1 / scale.value) + '%', // 放大余量 除以 2
|
||||
// top: 50 * (1 - 1 / scale.value) + '%', // 放大余量 除以 2
|
||||
// transform: 'scale(' + scale.value + ') translateZ(0)'
|
||||
// } as CSSProperties
|
||||
// } else {
|
||||
// return {}
|
||||
// }
|
||||
})
|
||||
const emits = defineEmits(['onPointClick'])
|
||||
|
||||
|
@ -18,7 +18,8 @@ import {
|
||||
onBeforeMount,
|
||||
CSSProperties,
|
||||
shallowRef,
|
||||
provide
|
||||
provide,
|
||||
nextTick
|
||||
} from 'vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
@ -57,12 +58,15 @@ const props = defineProps({
|
||||
})
|
||||
const { element, view, scale } = toRefs(props)
|
||||
const { t } = useI18n()
|
||||
const vQueryRef = ref()
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { curComponent, canvasViewInfo, mobileInPc, firstLoadMap } = storeToRefs(dvMainStore)
|
||||
const canEdit = ref(false)
|
||||
const queryConfig = ref()
|
||||
const defaultStyle = {
|
||||
border: '',
|
||||
placeholderSize: 14,
|
||||
placeholderShow: true,
|
||||
background: '',
|
||||
text: '',
|
||||
layout: 'horizontal',
|
||||
@ -111,6 +115,27 @@ const btnStyle = computed(() => {
|
||||
|
||||
return style
|
||||
})
|
||||
|
||||
const btnPlainStyle = computed(() => {
|
||||
const style = {
|
||||
backgroundColor: 'transparent',
|
||||
borderColor: customStyle.btnColor,
|
||||
color: customStyle.btnColor
|
||||
} as CSSProperties
|
||||
if (customStyle.fontSizeBtn) {
|
||||
style.fontSize = customStyle.fontSizeBtn + 'px'
|
||||
}
|
||||
|
||||
if (customStyle.fontWeightBtn) {
|
||||
style.fontWeight = customStyle.fontWeightBtn
|
||||
}
|
||||
|
||||
if (customStyle.fontStyleBtn) {
|
||||
style.fontStyle = customStyle.fontStyleBtn
|
||||
}
|
||||
|
||||
return style
|
||||
})
|
||||
const curComponentView = computed(() => {
|
||||
return (canvasViewInfo.value[element.value.id] || {}).customStyle
|
||||
})
|
||||
@ -130,7 +155,6 @@ const setCustomStyle = val => {
|
||||
layout,
|
||||
titleShow,
|
||||
titleColor,
|
||||
textColorShow,
|
||||
title,
|
||||
fontSize,
|
||||
fontWeight,
|
||||
@ -143,12 +167,22 @@ const setCustomStyle = val => {
|
||||
queryConditionSpacing,
|
||||
labelColorBtn,
|
||||
btnColor,
|
||||
placeholderSize,
|
||||
placeholderShow,
|
||||
labelShow
|
||||
} = val
|
||||
customStyle.background = bgColorShow ? bgColor || '' : ''
|
||||
customStyle.border = borderShow ? borderColor || '' : ''
|
||||
customStyle.btnList = [...btnList]
|
||||
customStyle.layout = layout
|
||||
customStyle.placeholderShow = placeholderShow ?? true
|
||||
customStyle.placeholderSize = placeholderSize ?? 14
|
||||
nextTick(() => {
|
||||
vQueryRef.value.style.setProperty(
|
||||
'--ed-component-size',
|
||||
`${customStyle.placeholderSize + 18}px`
|
||||
)
|
||||
})
|
||||
customStyle.titleShow = titleShow
|
||||
customStyle.titleColor = titleColor
|
||||
customStyle.labelColor = labelShow ? labelColor || '' : ''
|
||||
@ -156,7 +190,7 @@ const setCustomStyle = val => {
|
||||
customStyle.fontWeight = labelShow ? fontWeight || '' : ''
|
||||
customStyle.fontStyle = labelShow ? fontStyle || '' : ''
|
||||
customStyle.title = title
|
||||
customStyle.text = textColorShow ? text || '' : ''
|
||||
customStyle.text = customStyle.placeholderShow ? text || '' : ''
|
||||
customStyle.titleLayout = titleLayout
|
||||
customStyle.fontSizeBtn = fontSizeBtn || '14'
|
||||
customStyle.fontWeightBtn = fontWeightBtn
|
||||
@ -271,6 +305,12 @@ const getCascadeList = () => {
|
||||
return props.element.cascade
|
||||
}
|
||||
|
||||
const getPlaceholder = computed(() => {
|
||||
return {
|
||||
placeholderShow: customStyle.placeholderShow
|
||||
}
|
||||
})
|
||||
|
||||
const isConfirmSearch = id => {
|
||||
if (componentWithSure.value) return
|
||||
queryDataForId(id)
|
||||
@ -282,6 +322,7 @@ provide('release-unmount-select', releaseSelect)
|
||||
provide('query-data-for-id', queryDataForId)
|
||||
provide('com-width', getQueryConditionWidth)
|
||||
provide('cascade-list', getCascadeList)
|
||||
provide('placeholder', getPlaceholder)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
emitter.off(`addQueryCriteria${element.value.id}`)
|
||||
@ -449,6 +490,10 @@ watch(
|
||||
}
|
||||
)
|
||||
|
||||
const boxWidth = computed(() => {
|
||||
return `${customStyle.placeholderSize}px`
|
||||
})
|
||||
|
||||
const queryData = () => {
|
||||
let requiredName = ''
|
||||
const emitterList = (element.value.propValue || []).reduce((pre, next) => {
|
||||
@ -536,14 +581,14 @@ const autoStyle = computed(() => {
|
||||
width: 100 / scale.value + '%!important',
|
||||
left: 50 * (1 - 1 / scale.value) + '%', // 放大余量 除以 2
|
||||
top: 50 * (1 - 1 / scale.value) + '%', // 放大余量 除以 2
|
||||
transform: 'scale(' + scale.value + ')',
|
||||
transform: 'scale(' + scale.value + ') translateZ(0)',
|
||||
opacity: element.value?.style?.opacity || 1
|
||||
} as CSSProperties
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="v-query-container" :style="autoStyle" @keydown.stop @keyup.stop>
|
||||
<div class="v-query-container" ref="vQueryRef" :style="autoStyle" @keydown.stop @keyup.stop>
|
||||
<p v-if="customStyle.titleShow" class="title" :style="titleStyle">
|
||||
{{ customStyle.title }}
|
||||
</p>
|
||||
@ -619,10 +664,20 @@ const autoStyle = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="query-button" v-if="!!listVisible.length">
|
||||
<el-button @click.stop="clearData" v-if="customStyle.btnList.includes('clear')" secondary>
|
||||
<el-button
|
||||
@click.stop="clearData"
|
||||
:style="btnPlainStyle"
|
||||
v-if="customStyle.btnList.includes('clear')"
|
||||
plain
|
||||
>
|
||||
{{ t('commons.clear') }}
|
||||
</el-button>
|
||||
<el-button @click.stop="resetData" v-if="customStyle.btnList.includes('reset')" secondary>
|
||||
<el-button
|
||||
@click.stop="resetData"
|
||||
:style="btnPlainStyle"
|
||||
v-if="customStyle.btnList.includes('reset')"
|
||||
plain
|
||||
>
|
||||
{{ t('chart.reset') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@ -653,6 +708,15 @@ const autoStyle = computed(() => {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
--ed-font-size-base: v-bind(boxWidth);
|
||||
|
||||
:deep(.ed-tag) {
|
||||
--ed-tag-font-size: v-bind(boxWidth);
|
||||
}
|
||||
|
||||
:deep(.ed-select-v2) {
|
||||
font-size: v-bind(boxWidth);
|
||||
}
|
||||
|
||||
.no-list-label {
|
||||
width: 100%;
|
||||
|
@ -325,10 +325,11 @@ defineExpose({
|
||||
<template>
|
||||
<div class="list-item top-item" v-if="curComponent.displayType === '8'" @click.stop>
|
||||
<div class="label">设置默认值</div>
|
||||
<div class="value">
|
||||
<div class="value" :class="curComponent.hideConditionSwitching && 'hide-condition_switching'">
|
||||
<div class="condition-type">
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
v-if="!curComponent.hideConditionSwitching"
|
||||
popper-class="condition-value-select-popper"
|
||||
v-model="curComponent.defaultConditionValueOperatorF"
|
||||
>
|
||||
@ -346,6 +347,7 @@ defineExpose({
|
||||
<div class="condition-type" v-if="[1, 2].includes(curComponent.conditionType)">
|
||||
<sapn class="condition-type-tip">{{ curComponent.conditionType === 1 ? '与' : '或' }}</sapn>
|
||||
<el-select
|
||||
v-if="!curComponent.hideConditionSwitching"
|
||||
class="condition-value-select"
|
||||
popper-class="condition-value-select-popper"
|
||||
v-model="curComponent.defaultConditionValueOperatorS"
|
||||
@ -710,6 +712,16 @@ defineExpose({
|
||||
margin-top: -0.5px;
|
||||
}
|
||||
}
|
||||
|
||||
&.hide-condition_switching {
|
||||
.bottom-line {
|
||||
width: 307px !important;
|
||||
|
||||
&.next-line {
|
||||
width: 288px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.value {
|
||||
.sort-field {
|
||||
|
@ -1,4 +1,3 @@
|
||||
getLastStart
|
||||
<script lang="ts" setup>
|
||||
import more_v from '@/assets/svg/more_v.svg'
|
||||
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
|
||||
@ -1020,6 +1019,7 @@ const weightlessness = () => {
|
||||
const parameterCompletion = () => {
|
||||
const attributes = {
|
||||
timeType: 'fixed',
|
||||
hideConditionSwitching: false,
|
||||
required: false,
|
||||
defaultMapValue: [],
|
||||
mapValue: [],
|
||||
@ -1067,7 +1067,7 @@ const parameterCompletion = () => {
|
||||
treeFieldList: []
|
||||
}
|
||||
Object.entries(attributes).forEach(([key, val]) => {
|
||||
!curComponent.value[key] && (curComponent.value[key] = val)
|
||||
curComponent.value[key] ?? (curComponent.value[key] = val)
|
||||
})
|
||||
|
||||
if (!curComponent.value.timeRange.relativeToCurrentRange) {
|
||||
@ -2138,6 +2138,9 @@ defineExpose({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-bottom: 10.5px" v-if="curComponent.displayType === '8'">
|
||||
<el-checkbox v-model="curComponent.hideConditionSwitching" label="隐藏条件切换" />
|
||||
</div>
|
||||
<condition-default-configuration
|
||||
ref="defaultConfigurationRef"
|
||||
@handleTimeTypeChange="handleTimeTypeChange"
|
||||
|
@ -25,6 +25,7 @@ interface SelectConfig {
|
||||
displayType: string
|
||||
showEmpty: boolean
|
||||
id: string
|
||||
placeholder: string
|
||||
resultMode: number
|
||||
displayId: string
|
||||
sort: string
|
||||
@ -73,6 +74,7 @@ const loading = ref(false)
|
||||
const multiple = ref(false)
|
||||
const options = shallowRef([])
|
||||
const unMountSelect: Ref = inject('unmount-select')
|
||||
const placeholder: Ref = inject('placeholder')
|
||||
const releaseSelect = inject('release-unmount-select', Function, true)
|
||||
const queryDataForId = inject('query-data-for-id', Function, true)
|
||||
const isConfirmSearch = inject('is-confirm-search', Function, true)
|
||||
@ -80,6 +82,12 @@ const queryConditionWidth = inject('com-width', Function, true)
|
||||
const cascadeList = inject('cascade-list', Function, true)
|
||||
const setCascadeDefault = inject('set-cascade-default', Function, true)
|
||||
|
||||
const placeholderText = computed(() => {
|
||||
if (placeholder.value.placeholderShow) {
|
||||
return props.config.placeholder
|
||||
}
|
||||
return ' '
|
||||
})
|
||||
const cascade = computed(() => {
|
||||
return cascadeList() || []
|
||||
})
|
||||
@ -583,6 +591,7 @@ defineExpose({
|
||||
key="multiple"
|
||||
ref="mult"
|
||||
v-model="selectValue"
|
||||
:placeholder="placeholderText"
|
||||
v-loading="loading"
|
||||
filterable
|
||||
@change="handleValueChange"
|
||||
@ -604,6 +613,7 @@ defineExpose({
|
||||
v-else
|
||||
v-model="selectValue"
|
||||
key="single"
|
||||
:placeholder="placeholderText"
|
||||
v-loading="loading"
|
||||
@change="handleValueChange"
|
||||
clearable
|
||||
|
@ -1,19 +1,29 @@
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, onBeforeMount, type PropType, inject, computed, nextTick } from 'vue'
|
||||
import { toRefs, onBeforeMount, type PropType, type Ref, inject, computed, nextTick } from 'vue'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
interface SelectConfig {
|
||||
id: string
|
||||
conditionValueOperatorF: string
|
||||
conditionValueF: string
|
||||
hideConditionSwitching: boolean
|
||||
conditionValueOperatorS: string
|
||||
conditionValueS: string
|
||||
placeholder: string
|
||||
defaultConditionValueOperatorF: string
|
||||
defaultConditionValueF: string
|
||||
defaultConditionValueOperatorS: string
|
||||
defaultConditionValueS: string
|
||||
conditionType: number
|
||||
}
|
||||
const placeholder: Ref = inject('placeholder')
|
||||
|
||||
const placeholderText = computed(() => {
|
||||
if (placeholder.value.placeholderShow) {
|
||||
return props.config.placeholder
|
||||
}
|
||||
return ' '
|
||||
})
|
||||
|
||||
const operators = [
|
||||
{
|
||||
@ -50,6 +60,7 @@ const props = defineProps({
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const { config } = toRefs(props)
|
||||
const setParams = () => {
|
||||
const {
|
||||
@ -90,6 +101,7 @@ const lineWidth = computed(() => {
|
||||
<div class="condition-type">
|
||||
<el-select
|
||||
class="condition-value-select"
|
||||
v-if="!config.hideConditionSwitching"
|
||||
@change="handleValueChange"
|
||||
:effect="dvInfo.type === 'dataV' ? 'dark' : ''"
|
||||
popper-class="condition-value-select-popper"
|
||||
@ -100,6 +112,7 @@ const lineWidth = computed(() => {
|
||||
</el-select>
|
||||
<el-input
|
||||
:style="selectStyle"
|
||||
:placeholder="placeholderText"
|
||||
@blur="handleValueChange"
|
||||
class="condition-value-input"
|
||||
v-model="config.conditionValueF"
|
||||
@ -109,6 +122,7 @@ const lineWidth = computed(() => {
|
||||
<div class="condition-type" v-if="[1, 2].includes(config.conditionType)">
|
||||
<sapn class="condition-type-tip">{{ config.conditionType === 1 ? '与' : '或' }}</sapn>
|
||||
<el-select
|
||||
v-if="!config.hideConditionSwitching"
|
||||
class="condition-value-select"
|
||||
@change="handleValueChange"
|
||||
:effect="dvInfo.type === 'dataV' ? 'dark' : ''"
|
||||
@ -121,6 +135,7 @@ const lineWidth = computed(() => {
|
||||
<el-input
|
||||
:style="selectStyle"
|
||||
@blur="handleValueChange"
|
||||
:placeholder="placeholderText"
|
||||
class="condition-value-input"
|
||||
v-model="config.conditionValueS"
|
||||
/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { toRefs, PropType, ref, onBeforeMount, watch, nextTick, computed, inject } from 'vue'
|
||||
import { toRefs, PropType, ref, Ref, onBeforeMount, watch, nextTick, computed, inject } from 'vue'
|
||||
import { type DatePickType } from 'element-plus-secondary'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import type { ManipulateType } from 'dayjs'
|
||||
@ -25,6 +25,7 @@ interface SelectConfig {
|
||||
timeGranularity: DatePickType
|
||||
timeGranularityMultiple: DatePickType
|
||||
timeRange: TimeRange
|
||||
placeholder: string
|
||||
setTimeRange: boolean
|
||||
}
|
||||
|
||||
@ -62,6 +63,13 @@ const props = defineProps({
|
||||
default: false
|
||||
}
|
||||
})
|
||||
const placeholder: Ref = inject('placeholder')
|
||||
const placeholderText = computed(() => {
|
||||
if (placeholder.value.placeholderShow) {
|
||||
return props.config.placeholder
|
||||
}
|
||||
return ' '
|
||||
})
|
||||
const selectValue = ref()
|
||||
const multiple = ref(false)
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
@ -412,9 +420,10 @@ const formatDate = computed(() => {
|
||||
['datetimerange', 'daterange'].includes(config.timeGranularityMultiple) ? shortcuts : []
|
||||
"
|
||||
@change="handleValueChange"
|
||||
:editable="false"
|
||||
:range-separator="$t('cron.to')"
|
||||
:start-placeholder="$t('datasource.start_time')"
|
||||
:end-placeholder="$t('datasource.end_time')"
|
||||
:start-placeholder="placeholderText"
|
||||
:end-placeholder="placeholderText"
|
||||
/>
|
||||
<el-date-picker
|
||||
v-else
|
||||
@ -422,7 +431,7 @@ const formatDate = computed(() => {
|
||||
:type="config.timeGranularity"
|
||||
@change="handleValueChange"
|
||||
:style="selectStyle"
|
||||
:placeholder="$t('commons.date.select_date_time')"
|
||||
:placeholder="placeholderText"
|
||||
/>
|
||||
<div
|
||||
v-if="dvMainStore.mobileInPc"
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
onMounted,
|
||||
computed,
|
||||
inject,
|
||||
Ref,
|
||||
shallowRef
|
||||
} from 'vue'
|
||||
import { cloneDeep, debounce } from 'lodash-es'
|
||||
@ -20,6 +21,7 @@ interface SelectConfig {
|
||||
checkedFieldsMap: object
|
||||
displayType: string
|
||||
id: string
|
||||
placeholder: string
|
||||
checkedFields: string[]
|
||||
treeFieldList: Array<any>
|
||||
dataset: {
|
||||
@ -53,6 +55,14 @@ const props = defineProps({
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const placeholder: Ref = inject('placeholder')
|
||||
const placeholderText = computed(() => {
|
||||
if (placeholder.value.placeholderShow) {
|
||||
return props.config.placeholder
|
||||
}
|
||||
return ' '
|
||||
})
|
||||
const { config } = toRefs(props)
|
||||
|
||||
const multiple = ref(false)
|
||||
@ -231,6 +241,7 @@ const selectStyle = computed(() => {
|
||||
:render-after-expand="false"
|
||||
show-checkbox
|
||||
showBtn
|
||||
:placeholder="placeholderText"
|
||||
collapse-tags
|
||||
:showWholePath="showWholePath"
|
||||
collapse-tags-tooltip
|
||||
@ -245,6 +256,7 @@ const selectStyle = computed(() => {
|
||||
:data="treeOptionList"
|
||||
check-strictly
|
||||
clearable
|
||||
:placeholder="placeholderText"
|
||||
:render-after-expand="false"
|
||||
v-else-if="!multiple && !loading"
|
||||
key="singleTree"
|
||||
@ -256,6 +268,7 @@ const selectStyle = computed(() => {
|
||||
v-model="fakeValue"
|
||||
v-loading="loading"
|
||||
:data="[]"
|
||||
:placeholder="placeholderText"
|
||||
:render-after-expand="false"
|
||||
v-else
|
||||
key="fakeTree"
|
||||
|
@ -365,7 +365,11 @@ export default {
|
||||
please_insert_end: 'End Time Column Name',
|
||||
save_form: 'Save Form',
|
||||
default: 'default',
|
||||
default_built_in: 'Built-in Database'
|
||||
default_built_in: 'Built-in Database',
|
||||
lt_check: 'need less than {0}',
|
||||
gt_check: 'need greater than {0}',
|
||||
le_check: 'need less than or equal to {0}',
|
||||
ge_check: 'need greater than or equal to {0}'
|
||||
},
|
||||
database: {
|
||||
nvarchar: 'Nvarchar',
|
||||
|
@ -266,7 +266,11 @@ export default {
|
||||
please_insert_end: '請輸入結束時間',
|
||||
save_form: '保存表單',
|
||||
default: '默認',
|
||||
default_built_in: '內建數據庫'
|
||||
default_built_in: '內建數據庫',
|
||||
lt_check: '值需要小于{0}',
|
||||
gt_check: '值需要大于{0}',
|
||||
le_check: '值需要小于等于{0}',
|
||||
ge_check: '值需要大于等于{0}'
|
||||
},
|
||||
database: {
|
||||
nvarchar: '字符串',
|
||||
|
@ -996,8 +996,9 @@ export default {
|
||||
drag_block_value_axis_left: '左值轴',
|
||||
drag_block_value_axis_right: '右值轴',
|
||||
drag_block_table_data_column: '数据列',
|
||||
drag_block_pie_angel: '扇区角度',
|
||||
drag_block_pie_angle: '扇区角度',
|
||||
drag_block_pie_label: '扇区标签',
|
||||
drag_block_pie_radius: '扇区半径',
|
||||
drag_block_gauge_angel: '指针角度',
|
||||
drag_block_label_value: '值',
|
||||
drag_block_funnel_width: '漏斗层宽',
|
||||
@ -2703,7 +2704,11 @@ export default {
|
||||
please_insert_end: '请输入结束时间',
|
||||
save_form: '保存表单',
|
||||
default: '默认',
|
||||
default_built_in: '内建数据库'
|
||||
default_built_in: '内建数据库',
|
||||
lt_check: '值需要小于{0}',
|
||||
gt_check: '值需要大于{0}',
|
||||
le_check: '值需要小于等于{0}',
|
||||
ge_check: '值需要大于等于{0}'
|
||||
},
|
||||
database: {
|
||||
nvarchar: '字符串',
|
||||
|
@ -281,6 +281,14 @@ declare interface ChartBasicStyle {
|
||||
* 汇总表总计标签
|
||||
*/
|
||||
summaryLabel: string
|
||||
/**
|
||||
* 符号地图符号大小最小值
|
||||
*/
|
||||
mapSymbolSizeMin: number
|
||||
/**
|
||||
* 符号地图符号大小最大值
|
||||
*/
|
||||
mapSymbolSizeMax: number
|
||||
}
|
||||
/**
|
||||
* 表头属性
|
||||
@ -860,6 +868,10 @@ declare interface ChartLabelAttr {
|
||||
* 总计标签格式化设置
|
||||
*/
|
||||
totalFormatter: BaseFormatter
|
||||
/**
|
||||
* 柱状图堆叠指标
|
||||
*/
|
||||
showStackQuota: boolean
|
||||
}
|
||||
/**
|
||||
* 提示设置
|
||||
|
@ -198,6 +198,28 @@ declare interface Threshold {
|
||||
* url
|
||||
*/
|
||||
url: string
|
||||
/**
|
||||
* 类型,固定值、动态值
|
||||
*/
|
||||
type: 'fixed' | 'dynamic'
|
||||
/**
|
||||
* 动态值字段
|
||||
*/
|
||||
dynamicField: ThresholdDynamicField
|
||||
/**
|
||||
* 动态值最小值字段 仅当term为between时使用
|
||||
*/
|
||||
dynamicMinField: ThresholdDynamicField
|
||||
/**
|
||||
* 动态值最大值字段 仅当term为between时使用
|
||||
*/
|
||||
dynamicMaxField: ThresholdDynamicField
|
||||
}
|
||||
|
||||
declare interface ThresholdDynamicField {
|
||||
fieldId: string
|
||||
summary: string
|
||||
field: ChartViewField
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,6 +88,10 @@ declare type AxisSpec = {
|
||||
* 轴提示
|
||||
*/
|
||||
tooltip?: string
|
||||
/**
|
||||
* 允许为空
|
||||
*/
|
||||
allowEmpty?: boolean
|
||||
}
|
||||
/**
|
||||
* 图表编辑表单
|
||||
|
@ -8,6 +8,7 @@ import eventBus from '@/utils/eventBus'
|
||||
import { adaptCurThemeCommonStyle } from '@/utils/canvasStyle'
|
||||
import { composeStoreWithOut } from '@/store/modules/data-visualization/compose'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import { maxYComponentCount } from '@/utils/canvasUtils'
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const composeStore = composeStoreWithOut()
|
||||
@ -62,7 +63,7 @@ export const copyStore = defineStore('copy', {
|
||||
}
|
||||
// dataV 数据大屏
|
||||
newComponent.x = newComponent.sizeX * xPositionOffset + 1
|
||||
newComponent.y = 200
|
||||
newComponent.y = maxYComponentCount() + 10
|
||||
// dataV 数据大屏
|
||||
newComponent.style.left = 0
|
||||
newComponent.style.top = 0
|
||||
|
@ -482,6 +482,8 @@ export const dvMainStore = defineStore('dataVisualization', {
|
||||
fontStyleBtn: '',
|
||||
queryConditionWidth: 227,
|
||||
nameboxSpacing: 8,
|
||||
placeholderShow: true,
|
||||
placeholderSize: 14,
|
||||
queryConditionSpacing: 16,
|
||||
labelColorBtn: '#ffffff',
|
||||
btnColor: '#3370ff'
|
||||
|
@ -731,3 +731,14 @@ export function componentPreSort(componentData) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function maxYComponentCount() {
|
||||
if (componentData.value.length === 0) {
|
||||
return 1
|
||||
} else {
|
||||
return componentData.value
|
||||
.filter(item => item.y)
|
||||
.map(item => item.y + item.sizeY) // 计算每个元素的 y + sizeY
|
||||
.reduce((max, current) => Math.max(max, current), 0)
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ export default function findComponent(key) {
|
||||
|
||||
export function findComponentAttr(component) {
|
||||
const key =
|
||||
component.component === 'UserView' && component.innerType === 'Picture'
|
||||
? 'PictureAttr'
|
||||
component.component === 'UserView' && component.innerType === 'picture-group'
|
||||
? 'PictureGroupAttr'
|
||||
: component.component + 'Attr'
|
||||
return componentsMap[key]
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ const removeCache = () => {
|
||||
if (
|
||||
key.startsWith('de-plugin-') ||
|
||||
key === 'de-platform-client' ||
|
||||
key === 'pwd-validity-period'
|
||||
key === 'pwd-validity-period' ||
|
||||
key === 'xpack-model-distributed'
|
||||
) {
|
||||
wsCache.delete(key)
|
||||
}
|
||||
|
@ -184,3 +184,7 @@ export function cutTargetTree(tree: BusiTreeNode[], targetId: string | number) {
|
||||
export const isLink = () => {
|
||||
return window.location.hash.startsWith('#/de-link/')
|
||||
}
|
||||
|
||||
export const isNull = arg => {
|
||||
return typeof arg === 'undefined' || arg === null || arg === 'null'
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ const removeDistributeModule = () => {
|
||||
localStorage.removeItem(key)
|
||||
}
|
||||
const importLic = file => {
|
||||
removeDistributeModule()
|
||||
const reader = new FileReader()
|
||||
reader.onload = function (e) {
|
||||
const licKey = e.target.result
|
||||
@ -97,7 +98,6 @@ const importLic = file => {
|
||||
reader.readAsText(file)
|
||||
}
|
||||
const validateHandler = (param, success) => {
|
||||
removeDistributeModule()
|
||||
validateApi(param).then(success)
|
||||
}
|
||||
const getLicense = result => {
|
||||
|
@ -249,7 +249,10 @@ const quickCalc = param => {
|
||||
break
|
||||
case 'setting':
|
||||
// 选择占比外,设置自动
|
||||
resetValueFormatter(item.value)
|
||||
// 指标卡不需要重置数值格式
|
||||
if (chart.value.type !== 'indicator') {
|
||||
resetValueFormatter(item.value)
|
||||
}
|
||||
editCompare()
|
||||
break
|
||||
case 'percent':
|
||||
@ -370,57 +373,6 @@ onMounted(() => {
|
||||
class="drop-style"
|
||||
:class="themes === 'dark' ? 'dark-dimension-quota' : ''"
|
||||
>
|
||||
<!-- <el-dropdown-item @click.prevent v-if="chart.type === 'chart-mix'">
|
||||
<el-dropdown
|
||||
:effect="themes"
|
||||
placement="right-start"
|
||||
popper-class="data-dropdown_popper_mr9"
|
||||
style="width: 100%"
|
||||
@command="switchChartType"
|
||||
>
|
||||
<span class="el-dropdown-link inner-dropdown-menu menu-item-padding">
|
||||
<span class="menu-item-content">
|
||||
<el-icon>
|
||||
<Icon name="icon_dashboard_outlined" ><icon_dashboard_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
<span>{{ t('chart.chart_type') }}</span>
|
||||
</span>
|
||||
<el-icon>
|
||||
<Icon name="icon_right_outlined"><icon_right_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu
|
||||
:effect="themes"
|
||||
class="drop-style sub"
|
||||
:class="themes === 'dark' ? 'dark-dimension-quota' : ''"
|
||||
>
|
||||
<el-dropdown-item class="menu-item-padding" :command="beforeSwitchType('bar')">
|
||||
<span
|
||||
class="sub-menu-content"
|
||||
:class="'bar' === item.chartType ? 'content-active' : ''"
|
||||
>
|
||||
{{ t('chart.chart_bar') }}
|
||||
<el-icon class="sub-menu-content--icon">
|
||||
<Icon name="icon_done_outlined" v-if="'bar' === item.chartType" ><icon_done_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item class="menu-item-padding" :command="beforeSwitchType('line')">
|
||||
<span
|
||||
class="sub-menu-content"
|
||||
:class="'line' === item.chartType ? 'content-active' : ''"
|
||||
>
|
||||
{{ t('chart.chart_line') }}
|
||||
<el-icon class="sub-menu-content--icon">
|
||||
<Icon name="icon_done_outlined" v-if="'line' === item.chartType" ><icon_done_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</span>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</el-dropdown-item>-->
|
||||
<el-dropdown-item
|
||||
@click.prevent
|
||||
v-if="chart.type !== 'table-info' && item.summary !== ''"
|
||||
@ -681,7 +633,7 @@ onMounted(() => {
|
||||
props.type !== 'extLabel' &&
|
||||
props.type !== 'extTooltip' &&
|
||||
props.type !== 'extBubble' &&
|
||||
!chart.type.includes('chart-mix')
|
||||
!['chart-mix', 'indicator', 'liquid', 'gauge'].includes(chart.type)
|
||||
"
|
||||
:divided="chart.type !== 'table-info'"
|
||||
>
|
||||
@ -763,7 +715,7 @@ onMounted(() => {
|
||||
:command="beforeClickItem('filter')"
|
||||
:divided="chart.type.includes('chart-mix')"
|
||||
>
|
||||
<span>{{ t('chart.filter') }}...</span>
|
||||
<span>{{ t('chart.filter') }}</span>
|
||||
</el-dropdown-item>
|
||||
|
||||
<el-dropdown-item
|
||||
@ -773,7 +725,7 @@ onMounted(() => {
|
||||
:command="beforeClickItem('formatter')"
|
||||
>
|
||||
<el-icon />
|
||||
<span>{{ t('chart.value_formatter') }}...</span>
|
||||
<span>{{ t('chart.value_formatter') }}</span>
|
||||
</el-dropdown-item>
|
||||
|
||||
<el-dropdown-item class="menu-item-padding" :command="beforeClickItem('rename')">
|
||||
|
@ -25,7 +25,7 @@ const props = defineProps({
|
||||
>{{ t('chart.drag_block_value_axis') }}</span
|
||||
>
|
||||
<span v-else-if="props.view.type && props.view.type.includes('pie')">{{
|
||||
t('chart.drag_block_pie_angel')
|
||||
t('chart.drag_block_pie_angle')
|
||||
}}</span>
|
||||
<span v-else-if="props.view.type && props.view.type.includes('funnel')">{{
|
||||
t('chart.drag_block_funnel_width')
|
||||
|
@ -32,6 +32,7 @@ import { cloneDeep, defaultsDeep } from 'lodash-es'
|
||||
import BubbleAnimateCfg from '@/views/chart/components/editor/editor-senior/components/BubbleAnimateCfg.vue'
|
||||
import { XpackComponent } from '@/components/plugin'
|
||||
import CarouselSetting from '@/custom-component/common/CarouselSetting.vue'
|
||||
import { Icon } from 'vant'
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
|
||||
const { nowPanelTrackInfo, nowPanelJumpInfo, dvInfo, componentData, curComponent } =
|
||||
@ -338,28 +339,34 @@ const removeJumpSenior = () => {
|
||||
已设置
|
||||
</span>
|
||||
<button
|
||||
:class="'label-' + props.themes"
|
||||
class="circle-button_icon"
|
||||
:title="t('chart.delete')"
|
||||
:class="'label-' + props.themes"
|
||||
:style="{ margin: '0 8px' }"
|
||||
@click="removeLinkageSenior"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_delete-trash_outlined"
|
||||
><icon_deleteTrash_outlined class="svg-icon"
|
||||
<Icon
|
||||
><icon_deleteTrash_outlined
|
||||
:class="chart.linkageActive && 'primary-color'"
|
||||
class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</button>
|
||||
</template>
|
||||
<button
|
||||
:class="'label-' + props.themes"
|
||||
class="circle-button_icon"
|
||||
:title="t('chart.edit')"
|
||||
:class="'label-' + props.themes"
|
||||
@click="linkageSetOpen"
|
||||
:disabled="!chart.linkageActive"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_edit_outlined"><icon_edit_outlined class="svg-icon" /></Icon>
|
||||
<Icon
|
||||
><icon_edit_outlined
|
||||
:class="chart.linkageActive && 'primary-color'"
|
||||
class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</button>
|
||||
</span>
|
||||
@ -381,28 +388,34 @@ const removeJumpSenior = () => {
|
||||
已设置
|
||||
</span>
|
||||
<button
|
||||
:class="'label-' + props.themes"
|
||||
class="circle-button_icon"
|
||||
:title="t('chart.delete')"
|
||||
:class="'label-' + props.themes"
|
||||
:style="{ margin: '0 8px' }"
|
||||
@click="removeJumpSenior"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_delete-trash_outlined"
|
||||
><icon_deleteTrash_outlined class="svg-icon"
|
||||
<Icon
|
||||
><icon_deleteTrash_outlined
|
||||
:class="chart.jumpActive && 'primary-color'"
|
||||
class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</button>
|
||||
</template>
|
||||
<button
|
||||
:class="'label-' + props.themes"
|
||||
class="circle-button_icon"
|
||||
:title="t('chart.edit')"
|
||||
:class="'label-' + props.themes"
|
||||
@click="linkJumpSetOpen"
|
||||
:disabled="!chart.jumpActive"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_edit_outlined"><icon_edit_outlined class="svg-icon" /></Icon>
|
||||
<Icon
|
||||
><icon_edit_outlined
|
||||
:class="chart.jumpActive && 'primary-color'"
|
||||
class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</button>
|
||||
</span>
|
||||
@ -492,7 +505,7 @@ span {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
color: #a6a6a6 !important;
|
||||
color: #a6a6a6;
|
||||
}
|
||||
|
||||
.inner-container {
|
||||
|
@ -166,7 +166,11 @@ onMounted(() => {
|
||||
@click="editLine"
|
||||
>
|
||||
<el-icon>
|
||||
<Icon name="icon_edit_outlined"><icon_edit_outlined class="svg-icon" /></Icon>
|
||||
<Icon
|
||||
><icon_edit_outlined
|
||||
:class="state.assistLineCfg.enable && 'primary-color'"
|
||||
class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</button>
|
||||
</span>
|
||||
@ -363,7 +367,7 @@ span {
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
color: #a6a6a6 !important;
|
||||
color: #a6a6a6;
|
||||
&.ed-button {
|
||||
color: var(--ed-color-primary) !important;
|
||||
}
|
||||
|
@ -193,40 +193,62 @@ const changeTableThreshold = () => {
|
||||
ElMessage.error(t('chart.exp_can_not_empty'))
|
||||
return
|
||||
}
|
||||
if (ele.term === 'between') {
|
||||
if (
|
||||
!ele.term.includes('null') &&
|
||||
!ele.term.includes('empty') &&
|
||||
(ele.min === '' || ele.max === '')
|
||||
) {
|
||||
ElMessage.error(t('chart.value_can_not_empty'))
|
||||
return
|
||||
}
|
||||
if (
|
||||
(field.field.deType === 2 || field.field.deType === 3 || field.field.deType === 4) &&
|
||||
(parseFloat(ele.min).toString() === 'NaN' || parseFloat(ele.max).toString() === 'NaN')
|
||||
) {
|
||||
ElMessage.error(t('chart.value_error'))
|
||||
return
|
||||
}
|
||||
if (
|
||||
(field.field.deType === 2 || field.field.deType === 3 || field.field.deType === 4) &&
|
||||
parseFloat(ele.min) > parseFloat(ele.max)
|
||||
) {
|
||||
ElMessage.error(t('chart.value_min_max_invalid'))
|
||||
return
|
||||
if (ele.type !== 'dynamic') {
|
||||
if (ele.term === 'between') {
|
||||
if (
|
||||
!ele.term.includes('null') &&
|
||||
!ele.term.includes('empty') &&
|
||||
(ele.min === '' || ele.max === '')
|
||||
) {
|
||||
ElMessage.error(t('chart.value_can_not_empty'))
|
||||
return
|
||||
}
|
||||
if (
|
||||
(field.field.deType === 2 || field.field.deType === 3 || field.field.deType === 4) &&
|
||||
(parseFloat(ele.min).toString() === 'NaN' || parseFloat(ele.max).toString() === 'NaN')
|
||||
) {
|
||||
ElMessage.error(t('chart.value_error'))
|
||||
return
|
||||
}
|
||||
if (
|
||||
(field.field.deType === 2 || field.field.deType === 3 || field.field.deType === 4) &&
|
||||
parseFloat(ele.min) > parseFloat(ele.max)
|
||||
) {
|
||||
ElMessage.error(t('chart.value_min_max_invalid'))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (!ele.term.includes('null') && !ele.term.includes('empty') && ele.value === '') {
|
||||
ElMessage.error(t('chart.value_can_not_empty'))
|
||||
return
|
||||
}
|
||||
if (
|
||||
(field.field.deType === 2 || field.field.deType === 3 || field.field.deType === 4) &&
|
||||
parseFloat(ele.value).toString() === 'NaN'
|
||||
) {
|
||||
ElMessage.error(t('chart.value_error'))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!ele.term.includes('null') && !ele.term.includes('empty') && ele.value === '') {
|
||||
ElMessage.error(t('chart.value_can_not_empty'))
|
||||
return
|
||||
}
|
||||
if (
|
||||
(field.field.deType === 2 || field.field.deType === 3 || field.field.deType === 4) &&
|
||||
parseFloat(ele.value).toString() === 'NaN'
|
||||
) {
|
||||
ElMessage.error(t('chart.value_error'))
|
||||
return
|
||||
if (ele.term === 'between') {
|
||||
if (
|
||||
!ele.term.includes('null') &&
|
||||
!ele.term.includes('empty') &&
|
||||
(!ele.dynamicMinField?.fieldId || !ele.dynamicMaxField?.fieldId)
|
||||
) {
|
||||
ElMessage.error(t('chart.field_can_not_empty'))
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
!ele.term.includes('null') &&
|
||||
!ele.term.includes('empty') &&
|
||||
!ele.dynamicField?.fieldId
|
||||
) {
|
||||
ElMessage.error(t('chart.field_can_not_empty'))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -235,7 +257,24 @@ const changeTableThreshold = () => {
|
||||
changeThreshold()
|
||||
closeTableThreshold()
|
||||
}
|
||||
const getFieldName = field => (field.chartShowName ? field.chartShowName : field.name)
|
||||
|
||||
const getDynamicStyleLabel = (item, fieldObj) => {
|
||||
const handleSummary = field => {
|
||||
if (!field?.field) {
|
||||
return ''
|
||||
}
|
||||
if (field.summary === 'value') {
|
||||
return getFieldName(field.field) + '(' + t('chart.field') + ')'
|
||||
} else {
|
||||
let suffix = field.summary === 'avg' ? t('chart.drag_block_label_value') : ''
|
||||
return getFieldName(field.field) + '(' + t('chart.' + field.summary) + suffix + ')'
|
||||
}
|
||||
}
|
||||
if (item.type === 'dynamic') {
|
||||
return handleSummary(fieldObj)
|
||||
}
|
||||
}
|
||||
init()
|
||||
</script>
|
||||
|
||||
@ -519,17 +558,15 @@ init()
|
||||
style="flex-direction: column"
|
||||
>
|
||||
<div class="field-style" :class="{ 'field-style-dark': themes === 'dark' }">
|
||||
<span>
|
||||
<el-icon>
|
||||
<Icon :className="`field-icon-${fieldType[fieldItem.field.deType]}`"
|
||||
><component
|
||||
class="svg-icon"
|
||||
:class="`field-icon-${fieldType[fieldItem.field.deType]}`"
|
||||
:is="iconFieldMap[fieldType[fieldItem.field.deType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
</span>
|
||||
<el-icon>
|
||||
<Icon :className="`field-icon-${fieldType[fieldItem.field.deType]}`"
|
||||
><component
|
||||
class="svg-icon"
|
||||
:class="`field-icon-${fieldType[fieldItem.field.deType]}`"
|
||||
:is="iconFieldMap[fieldType[fieldItem.field.deType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
<span :title="fieldItem.field.name" class="field-text">{{
|
||||
fieldItem.field.name
|
||||
}}</span>
|
||||
@ -577,7 +614,17 @@ init()
|
||||
</span>
|
||||
<span v-else-if="item.term === 'default'" title="默认"> 默认 </span>
|
||||
</div>
|
||||
<div style="flex: 1; margin: 0 8px">
|
||||
<div v-if="item.type !== 'dynamic'" style="flex: 1; margin: 0 8px">
|
||||
<span style="margin: 0 8px">
|
||||
{{ t('chart.fix') }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-else style="flex: 1; margin: 0 8px">
|
||||
<span style="margin: 0 8px">
|
||||
{{ t('chart.dynamic') }}
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="item.type !== 'dynamic'" style="flex: 1; margin: 0 8px">
|
||||
<span
|
||||
v-if="
|
||||
!item.term.includes('null') &&
|
||||
@ -594,11 +641,44 @@ init()
|
||||
!item.term.includes('empty') &&
|
||||
item.term === 'between'
|
||||
"
|
||||
:title="item.min + ' ≤= ' + t('chart.drag_block_label_value') + ' ≤ ' + item.max"
|
||||
>
|
||||
{{ item.min }} ≤{{ t('chart.drag_block_label_value') }}≤ {{ item.max }}
|
||||
</span>
|
||||
<span v-else> </span>
|
||||
</div>
|
||||
<div v-else style="flex: 1; margin: 0 8px">
|
||||
<span
|
||||
v-if="
|
||||
!item.term.includes('null') &&
|
||||
!item.term.includes('default') &&
|
||||
!item.term.includes('empty') &&
|
||||
item.term !== 'between'
|
||||
"
|
||||
:title="getDynamicStyleLabel(item, item.dynamicField) + ''"
|
||||
>
|
||||
{{ getDynamicStyleLabel(item, item.dynamicField) }}</span
|
||||
>
|
||||
<span
|
||||
v-else-if="
|
||||
!item.term.includes('null') &&
|
||||
!item.term.includes('empty') &&
|
||||
item.term === 'between'
|
||||
"
|
||||
:title="
|
||||
getDynamicStyleLabel(item, item.dynamicMinField) +
|
||||
'≤' +
|
||||
t('chart.drag_block_label_value') +
|
||||
'≤' +
|
||||
getDynamicStyleLabel(item, item.dynamicMaxField)
|
||||
"
|
||||
>
|
||||
{{ getDynamicStyleLabel(item, item.dynamicMinField) }}≤{{
|
||||
t('chart.drag_block_label_value')
|
||||
}}≤{{ getDynamicStyleLabel(item, item.dynamicMaxField) }}
|
||||
</span>
|
||||
<span v-else> </span>
|
||||
</div>
|
||||
<template v-if="chart.type === 'picture-group'">
|
||||
<div title="显示图片" class="pic-group-main">
|
||||
<img
|
||||
@ -688,7 +768,7 @@ init()
|
||||
v-model="state.editTableThresholdDialog"
|
||||
:title="t('chart.threshold')"
|
||||
:visible="state.editTableThresholdDialog"
|
||||
width="800px"
|
||||
width="1050px"
|
||||
class="dialog-css"
|
||||
append-to-body
|
||||
>
|
||||
@ -826,12 +906,21 @@ span {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
:nth-child(1) {
|
||||
width: 48px;
|
||||
}
|
||||
:nth-child(2) {
|
||||
width: 40px !important;
|
||||
}
|
||||
:nth-child(3) {
|
||||
width: 30px !important;
|
||||
}
|
||||
&:deep(span) {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@ -868,9 +957,7 @@ span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
background: #f5f6f7;
|
||||
|
||||
&.field-style-dark {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
@ -898,7 +985,7 @@ span {
|
||||
border-radius: 2px;
|
||||
}
|
||||
.pic-group-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -7,6 +7,8 @@ import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { COLOR_PANEL } from '../../../util/chart'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import { iconFieldMap } from '@/components/icon-group/field-list'
|
||||
import PictureItem from '@/custom-component/picture-group/PictureItem.vue'
|
||||
import PictureOptionPrefix from '@/custom-component/picture-group/PictureOptionPrefix.vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -429,13 +431,25 @@ init()
|
||||
>
|
||||
<div class="color-title">展示图片</div>
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.url" @change="changeThreshold">
|
||||
<el-select
|
||||
v-model="item.url"
|
||||
@change="changeThreshold"
|
||||
popper-class="picture-group-select"
|
||||
>
|
||||
<template v-if="item.url" #prefix>
|
||||
<picture-option-prefix :url="item.url"></picture-option-prefix>
|
||||
</template>
|
||||
<el-option
|
||||
v-for="urlInfo in element.propValue.urlList"
|
||||
:key="urlInfo.url"
|
||||
:label="urlInfo.name"
|
||||
:value="urlInfo.url"
|
||||
/>
|
||||
>
|
||||
<picture-item
|
||||
:active="item.url === urlInfo.url"
|
||||
:url-info="urlInfo"
|
||||
></picture-item>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
@ -597,3 +611,30 @@ span {
|
||||
padding: 0 11px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.picture-group-select {
|
||||
min-width: 50px !important;
|
||||
width: 304px;
|
||||
.ed-scrollbar__view {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(3, 1fr) !important;
|
||||
}
|
||||
.ed-select-dropdown__item {
|
||||
height: 100px !important;
|
||||
text-align: center;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
.ed-select-dropdown__item.selected::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ed-select-dropdown__item.hover {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
.ed-select-dropdown__item.selected {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -7,6 +7,7 @@ import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { COLOR_PANEL } from '../../../util/chart'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import { iconFieldMap } from '@/components/icon-group/field-list'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -30,7 +31,11 @@ const thresholdCondition = {
|
||||
color: '#ff0000ff',
|
||||
backgroundColor: '#ffffff00',
|
||||
min: '0',
|
||||
max: '1'
|
||||
max: '1',
|
||||
type: 'fixed',
|
||||
dynamicField: { summary: 'value' },
|
||||
dynamicMinField: { summary: 'value' },
|
||||
dynamicMaxField: { summary: 'value' }
|
||||
}
|
||||
const textOptions = [
|
||||
{
|
||||
@ -180,12 +185,13 @@ const init = () => {
|
||||
state.thresholdArr = JSON.parse(JSON.stringify(props.threshold)) as TableThreshold[]
|
||||
initFields()
|
||||
}
|
||||
const initOptions = item => {
|
||||
if (item.field) {
|
||||
if ([0, 5, 7].includes(item.field.deType)) {
|
||||
const initOptions = (item, fieldObj) => {
|
||||
if (fieldObj) {
|
||||
if ([0, 5, 7].includes(fieldObj.deType)) {
|
||||
item.options = JSON.parse(JSON.stringify(textOptions))
|
||||
} else if (item.field.deType === 1) {
|
||||
} else if (fieldObj.deType === 1) {
|
||||
item.options = JSON.parse(JSON.stringify(dateOptions))
|
||||
item.type = 'fixed'
|
||||
} else {
|
||||
item.options = JSON.parse(JSON.stringify(valueOptions))
|
||||
}
|
||||
@ -225,7 +231,13 @@ const changeThreshold = () => {
|
||||
}
|
||||
|
||||
const addConditions = item => {
|
||||
item.conditions.push(JSON.parse(JSON.stringify(thresholdCondition)))
|
||||
const newCondition = JSON.parse(JSON.stringify(thresholdCondition))
|
||||
// 获取单元格默认背景颜色
|
||||
const tableCell = props.chart?.customAttr?.tableCell
|
||||
if (tableCell) {
|
||||
newCondition.backgroundColor = cloneDeep(tableCell.tableItemBgColor)
|
||||
}
|
||||
item.conditions.push(newCondition)
|
||||
changeThreshold()
|
||||
}
|
||||
const removeCondition = (item, index) => {
|
||||
@ -239,13 +251,106 @@ const addField = item => {
|
||||
state.fields.forEach(ele => {
|
||||
if (item.fieldId === ele.id) {
|
||||
item.field = JSON.parse(JSON.stringify(ele))
|
||||
initOptions(item)
|
||||
initOptions(item, item.field)
|
||||
}
|
||||
if (item.dynamicField?.fieldId === ele.id) {
|
||||
item.dynamicField.field = JSON.parse(JSON.stringify(ele))
|
||||
initOptions(item, item.dynamicField.field)
|
||||
}
|
||||
if (item.dynamicMinField?.fieldId === ele.id) {
|
||||
item.dynamicMinField.field = JSON.parse(JSON.stringify(ele))
|
||||
initOptions(item, item.dynamicMinField.field)
|
||||
}
|
||||
if (item.dynamicMaxField?.fieldId === ele.id) {
|
||||
item.dynamicMaxField.field = JSON.parse(JSON.stringify(ele))
|
||||
initOptions(item, item.dynamicMaxField.field)
|
||||
}
|
||||
})
|
||||
}
|
||||
changeThreshold()
|
||||
}
|
||||
|
||||
const fieldOptions = [
|
||||
{ label: t('chart.field_fixed'), value: 'fixed' },
|
||||
{ label: t('chart.field_dynamic'), value: 'dynamic' }
|
||||
]
|
||||
const dynamicSummaryOptions = [
|
||||
{
|
||||
id: 'value',
|
||||
name: t('chart.field') + t('chart.drag_block_label_value')
|
||||
},
|
||||
{
|
||||
id: 'avg',
|
||||
name: t('chart.avg') + t('chart.drag_block_label_value')
|
||||
},
|
||||
{
|
||||
id: 'max',
|
||||
name: t('chart.max')
|
||||
},
|
||||
{
|
||||
id: 'min',
|
||||
name: t('chart.min')
|
||||
}
|
||||
]
|
||||
|
||||
const getConditionsFields = (fieldItem, conditionItem, conditionItemField) => {
|
||||
const fieldItemDeType = state.fields.filter(ele => ele.id === fieldItem.fieldId)?.[0]?.deType
|
||||
if (fieldItemDeType === undefined || fieldItemDeType === null) {
|
||||
conditionItem.fieldId = null
|
||||
conditionItemField.fieldId = null
|
||||
}
|
||||
const result = state.fields.filter(item => item.deType === fieldItemDeType) ?? []
|
||||
if (!result.find(ele => ele.id === conditionItemField.fieldId)) {
|
||||
conditionItemField.fieldId = result[0]?.id
|
||||
addField(conditionItem)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const getDynamicSummaryOptions = itemId => {
|
||||
const deType = state.fields.filter(ele => ele.id === itemId)?.[0]?.deType
|
||||
if (deType === 1) {
|
||||
// 时间
|
||||
return dynamicSummaryOptions.filter(ele => {
|
||||
return ele.id !== 'avg'
|
||||
})
|
||||
} else if (deType === 0 || deType === 5) {
|
||||
// 文本、地理位置
|
||||
return dynamicSummaryOptions.filter(ele => {
|
||||
return ele.id === 'value'
|
||||
})
|
||||
} else {
|
||||
return dynamicSummaryOptions
|
||||
}
|
||||
}
|
||||
|
||||
const isNotEmptyAndNull = item => {
|
||||
return !item.term.includes('null') && !item.term.includes('empty')
|
||||
}
|
||||
|
||||
const isBetween = item => {
|
||||
return item.term === 'between'
|
||||
}
|
||||
|
||||
const isDynamic = item => {
|
||||
return item.type === 'dynamic'
|
||||
}
|
||||
const changeConditionItemType = item => {
|
||||
if (item.type === 'dynamic') {
|
||||
item.dynamicField.summary = 'value'
|
||||
item.dynamicMinField.summary = 'value'
|
||||
item.dynamicMaxField.summary = 'value'
|
||||
}
|
||||
}
|
||||
const getFieldOptions = fieldItem => {
|
||||
const deType = state.fields.filter(ele => ele.id === fieldItem.fieldId)?.[0]?.deType
|
||||
if (deType === 1) {
|
||||
return fieldOptions.filter(ele => ele.value === 'fixed')
|
||||
} else {
|
||||
return fieldOptions
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
</script>
|
||||
|
||||
@ -310,9 +415,9 @@ init()
|
||||
v-for="(item, index) in fieldItem.conditions"
|
||||
:key="index"
|
||||
class="line-item"
|
||||
:gutter="10"
|
||||
:gutter="12"
|
||||
>
|
||||
<el-col :span="4">
|
||||
<el-col :span="3">
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.term" @change="changeThreshold">
|
||||
<el-option-group
|
||||
@ -330,13 +435,27 @@ init()
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="2" v-if="isNotEmptyAndNull(item)" style="padding-left: 0 !important">
|
||||
<el-form-item class="form-item">
|
||||
<el-select
|
||||
v-model="item.type"
|
||||
class="select-item"
|
||||
@change="changeConditionItemType(item)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in getFieldOptions(fieldItem)"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--不是between 不是动态值-->
|
||||
<el-col
|
||||
v-if="
|
||||
!item.term.includes('null') &&
|
||||
!item.term.includes('empty') &&
|
||||
item.term !== 'between'
|
||||
"
|
||||
:span="10"
|
||||
v-if="isNotEmptyAndNull(item) && !isBetween(item) && !isDynamic(item)"
|
||||
:span="12"
|
||||
style="text-align: center"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
@ -359,8 +478,72 @@ init()
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col v-if="item.term === 'between'" :span="4" style="text-align: center">
|
||||
<!--不是between 是动态值-->
|
||||
<!--动态值 字段-->
|
||||
<el-col v-if="isNotEmptyAndNull(item) && !isBetween(item) && isDynamic(item)" :span="6">
|
||||
<el-form-item class="form-item">
|
||||
<el-select
|
||||
v-model="item.dynamicField.fieldId"
|
||||
@change="addField(item)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
class="series-select-option"
|
||||
v-for="itemFieldOption in getConditionsFields(
|
||||
fieldItem,
|
||||
item,
|
||||
item.dynamicField
|
||||
)"
|
||||
:key="itemFieldOption.id"
|
||||
:label="itemFieldOption.name"
|
||||
:value="itemFieldOption.id"
|
||||
:disabled="chart.type === 'table-info' && itemFieldOption.deType === 7"
|
||||
>
|
||||
<el-icon style="margin-right: 8px">
|
||||
<Icon
|
||||
><component
|
||||
:class="`field-icon-${
|
||||
fieldType[[2, 3].includes(itemFieldOption.deType) ? 2 : 0]
|
||||
}`"
|
||||
class="svg-icon"
|
||||
:is="iconFieldMap[fieldType[itemFieldOption.deType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
{{ itemFieldOption.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--动态值聚合方式-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && !isBetween(item) && isDynamic(item)"
|
||||
:span="6"
|
||||
style="text-align: center"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-select
|
||||
:placeholder="t('chart.aggregation')"
|
||||
v-model="item.dynamicField.summary"
|
||||
@change="changeThreshold"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in getDynamicSummaryOptions(item.dynamicField.fieldId)"
|
||||
:key="opt.id"
|
||||
:label="opt.name"
|
||||
:value="opt.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--是between 不是动态值-->
|
||||
<!--between 开始值-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && isBetween(item) && !isDynamic(item)"
|
||||
:span="5"
|
||||
style="text-align: center"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-input-number
|
||||
v-model="item.min"
|
||||
@ -372,14 +555,21 @@ init()
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col v-if="item.term === 'between'" :span="2" style="text-align: center">
|
||||
<span style="margin: 0 4px">
|
||||
≤ {{ t('chart.drag_block_label_value') }} ≤
|
||||
<el-col
|
||||
v-if="isBetween(item) && !isDynamic(item)"
|
||||
:span="2"
|
||||
style="margin-top: 4px; text-align: center"
|
||||
>
|
||||
<span style="margin: 0 -5px">
|
||||
≤ {{ t('chart.drag_block_label_value') }} ≤
|
||||
</span>
|
||||
</el-col>
|
||||
|
||||
<el-col v-if="item.term === 'between'" :span="4" style="text-align: center">
|
||||
<!--between 结束值-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && isBetween(item) && !isDynamic(item)"
|
||||
:span="5"
|
||||
style="text-align: center"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-input-number
|
||||
v-model="item.max"
|
||||
@ -392,11 +582,127 @@ init()
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<div
|
||||
style="display: flex; align-items: center; justify-content: center; margin-left: 8px"
|
||||
<!--是between 动态值-->
|
||||
<!--开始值 动态值字段-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && isBetween(item) && isDynamic(item)"
|
||||
class="minField"
|
||||
:span="3"
|
||||
>
|
||||
<div class="color-title">{{ t('chart.textColor') }}</div>
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.dynamicMinField.fieldId" @change="addField(item)">
|
||||
<el-option
|
||||
class="series-select-option"
|
||||
v-for="itemFieldOption in getConditionsFields(
|
||||
fieldItem,
|
||||
item,
|
||||
item.dynamicMinField
|
||||
)"
|
||||
:key="itemFieldOption.id"
|
||||
:label="itemFieldOption.name"
|
||||
:value="itemFieldOption.id"
|
||||
:disabled="chart.type === 'table-info' && itemFieldOption.deType === 7"
|
||||
>
|
||||
<el-icon style="margin-right: 8px">
|
||||
<Icon
|
||||
><component
|
||||
:class="`field-icon-${
|
||||
fieldType[[2, 3].includes(itemFieldOption.deType) ? 2 : 0]
|
||||
}`"
|
||||
class="svg-icon"
|
||||
:is="iconFieldMap[fieldType[itemFieldOption.deType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
{{ itemFieldOption.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--开始值 动态值聚合方式-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && isBetween(item) && isDynamic(item)"
|
||||
class="minValue"
|
||||
:span="2"
|
||||
style="padding-left: 0 !important"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.dynamicMinField.summary" @change="changeThreshold">
|
||||
<el-option
|
||||
v-for="opt in getDynamicSummaryOptions(item.dynamicMinField.fieldId)"
|
||||
:key="opt.id"
|
||||
:label="opt.name"
|
||||
:value="opt.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col
|
||||
v-if="isBetween(item) && isDynamic(item)"
|
||||
class="term"
|
||||
:span="2"
|
||||
style="margin-top: 4px; text-align: center"
|
||||
>
|
||||
<span style="margin: 0 -5px">
|
||||
≤ {{ t('chart.drag_block_label_value') }} ≤
|
||||
</span>
|
||||
</el-col>
|
||||
<!--结束值 动态值字段-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && isBetween(item) && isDynamic(item)"
|
||||
class="maxField"
|
||||
:span="3"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.dynamicMaxField.fieldId" @change="addField(item)">
|
||||
<el-option
|
||||
class="series-select-option"
|
||||
v-for="itemFieldOption in getConditionsFields(
|
||||
fieldItem,
|
||||
item,
|
||||
item.dynamicMaxField
|
||||
)"
|
||||
:key="itemFieldOption.id"
|
||||
:label="itemFieldOption.name"
|
||||
:value="itemFieldOption.id"
|
||||
:disabled="chart.type === 'table-info' && itemFieldOption.deType === 7"
|
||||
>
|
||||
<el-icon style="margin-right: 8px">
|
||||
<Icon
|
||||
><component
|
||||
:class="`field-icon-${
|
||||
fieldType[[2, 3].includes(itemFieldOption.deType) ? 2 : 0]
|
||||
}`"
|
||||
class="svg-icon"
|
||||
:is="iconFieldMap[fieldType[itemFieldOption.deType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
{{ itemFieldOption.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--结束值 动态值聚合方式-->
|
||||
<el-col
|
||||
v-if="isNotEmptyAndNull(item) && isBetween(item) && isDynamic(item)"
|
||||
class="maxValue"
|
||||
:span="2"
|
||||
style="padding-left: 0 !important"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.dynamicMaxField.summary" @change="changeThreshold">
|
||||
<el-option
|
||||
v-for="opt in getDynamicSummaryOptions(item.dynamicMaxField.fieldId)"
|
||||
:key="opt.id"
|
||||
:label="opt.name"
|
||||
:value="opt.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-form-item class="form-item" :label="t('chart.textColor')">
|
||||
<el-color-picker
|
||||
is-custom
|
||||
size="large"
|
||||
@ -407,12 +713,9 @@ init()
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div
|
||||
style="display: flex; align-items: center; justify-content: center; margin-left: 8px"
|
||||
>
|
||||
<div class="color-title">{{ t('chart.backgroundColor') }}</div>
|
||||
<el-form-item class="form-item">
|
||||
</el-col>
|
||||
<el-col :span="3">
|
||||
<el-form-item class="form-item" :label="t('chart.backgroundColor')">
|
||||
<el-color-picker
|
||||
is-custom
|
||||
size="large"
|
||||
@ -423,22 +726,22 @@ init()
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div
|
||||
style="display: flex; align-items: center; justify-content: center; margin-left: 8px"
|
||||
>
|
||||
<el-button
|
||||
class="circle-button m-icon-btn"
|
||||
text
|
||||
@click="removeCondition(fieldItem, index)"
|
||||
>
|
||||
<el-icon size="20px" style="color: #646a73">
|
||||
<Icon name="icon_delete-trash_outlined"
|
||||
><icon_deleteTrash_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<div style="display: flex; align-items: center; justify-content: center">
|
||||
<el-button
|
||||
class="circle-button m-icon-btn"
|
||||
text
|
||||
@click="removeCondition(fieldItem, index)"
|
||||
>
|
||||
<el-icon size="20px" style="color: #646a73">
|
||||
<Icon name="icon_delete-trash_outlined"
|
||||
><icon_deleteTrash_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row>
|
||||
|
||||
|
@ -28,7 +28,7 @@ import FlowMapLineSelector from '@/views/chart/components/editor/editor-style/co
|
||||
import FlowMapPointSelector from '@/views/chart/components/editor/editor-style/components/FlowMapPointSelector.vue'
|
||||
import CommonEvent from '@/custom-component/common/CommonEvent.vue'
|
||||
import CommonBorderSetting from '@/custom-component/common/CommonBorderSetting.vue'
|
||||
import PictureGroupAttr from '@/custom-component/picture-group/Attr.vue'
|
||||
import PictureGroupUploadAttr from '@/custom-component/picture-group/PictureGroupUploadAttr.vue'
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { dvInfo, batchOptStatus, curComponent } = storeToRefs(dvMainStore)
|
||||
@ -612,11 +612,11 @@ watch(
|
||||
@onChangeYAxisExtForm="onChangeYAxisExtForm"
|
||||
/>
|
||||
</collapse-switch-item>
|
||||
<PictureGroupAttr
|
||||
<PictureGroupUploadAttr
|
||||
v-if="pictureGroupShow"
|
||||
:themes="themes"
|
||||
:element="curComponent"
|
||||
></PictureGroupAttr>
|
||||
></PictureGroupUploadAttr>
|
||||
</el-collapse>
|
||||
</el-row>
|
||||
</div>
|
||||
|
@ -1,16 +1,19 @@
|
||||
<script lang="tsx" setup>
|
||||
import { ElMessage } from 'element-plus-secondary'
|
||||
import icon_bold_outlined from '@/assets/svg/icon_bold_outlined.svg'
|
||||
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
|
||||
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||
import icon_italic_outlined from '@/assets/svg/icon_italic_outlined.svg'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import icon_info_outlined from '@/assets/svg/icon_info_outlined.svg'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { PropType, toRefs, computed } from 'vue'
|
||||
import { PropType, toRefs, computed, reactive, watch, ref, onMounted } from 'vue'
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
import { COLOR_PANEL } from '@/views/chart/components/editor/util/chart'
|
||||
import CollapseSwitchItem from '@/components/collapse-switch-item/src/CollapseSwitchItem.vue'
|
||||
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
const { t } = useI18n()
|
||||
const state = {
|
||||
styleActiveNames: ['basicStyle']
|
||||
}
|
||||
const styleActiveNames = ref(['basicStyle'])
|
||||
|
||||
const props = defineProps({
|
||||
element: {
|
||||
@ -41,40 +44,162 @@ for (let i = 10; i <= 60; i = i + 2) {
|
||||
value: i + ''
|
||||
})
|
||||
}
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const files = ref(null)
|
||||
|
||||
const state = reactive({
|
||||
commonBackground: {},
|
||||
fileList: [],
|
||||
dialogImageUrl: '',
|
||||
dialogVisible: false
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.commonBackgroundPop,
|
||||
() => {
|
||||
init()
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.element.id,
|
||||
() => {
|
||||
initParams()
|
||||
}
|
||||
)
|
||||
|
||||
const currentPlaceholder = ref()
|
||||
const currentSearch = ref({
|
||||
placeholder: ''
|
||||
})
|
||||
|
||||
const handleCurrentPlaceholder = val => {
|
||||
const obj = props.element.propValue.find(ele => {
|
||||
return ele.id === val
|
||||
}) || {
|
||||
placeholder: ''
|
||||
}
|
||||
if (obj.placeholder === undefined) {
|
||||
obj.placeholder = ''
|
||||
}
|
||||
currentSearch.value = obj
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
state.commonBackground = cloneDeep(props.commonBackgroundPop)
|
||||
if (state.commonBackground['outerImage']) {
|
||||
state.fileList.push({ url: imgUrlTrans(state.commonBackground['outerImage']) })
|
||||
} else {
|
||||
state.fileList = []
|
||||
}
|
||||
}
|
||||
const handleRemove = () => {
|
||||
state.commonBackground['outerImage'] = null
|
||||
state.fileList = []
|
||||
onBackgroundChange()
|
||||
}
|
||||
const handlePictureCardPreview = file => {
|
||||
state.dialogImageUrl = file.url
|
||||
state.dialogVisible = true
|
||||
}
|
||||
const upload = file => {
|
||||
return uploadFileResult(file.file, fileUrl => {
|
||||
state.commonBackground['outerImage'] = fileUrl
|
||||
state.fileList = [{ url: imgUrlTrans(state.commonBackground['outerImage']) }]
|
||||
onBackgroundChange()
|
||||
})
|
||||
}
|
||||
const goFile = () => {
|
||||
files.value.click()
|
||||
}
|
||||
|
||||
const onBackgroundChange = () => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
commonBackgroundPop.value.outerImage = state.commonBackground['outerImage']
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
const reUpload = e => {
|
||||
const file = e.target.files[0]
|
||||
if (file.size > 15000000) {
|
||||
ElMessage.success('图片大小不符合')
|
||||
return
|
||||
}
|
||||
uploadFileResult(file, fileUrl => {
|
||||
state.commonBackground['outerImage'] = fileUrl
|
||||
state.fileList = [{ url: imgUrlTrans(state.commonBackground['outerImage']) }]
|
||||
onBackgroundChange()
|
||||
})
|
||||
}
|
||||
|
||||
const checkBold = type => {
|
||||
if (!chart.value.customStyle.component.labelShow) return
|
||||
chart.value.customStyle.component[type] = chart.value.customStyle.component[type] ? '' : 'bold'
|
||||
}
|
||||
|
||||
const handleCurrentPlaceholderChange = () => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
}
|
||||
|
||||
const checkItalic = type => {
|
||||
if (!chart.value.customStyle.component.labelShow) return
|
||||
chart.value.customStyle.component[type] = chart.value.customStyle.component[type] ? '' : 'italic'
|
||||
}
|
||||
const { chart, commonBackgroundPop } = toRefs(props)
|
||||
if (!chart.value.customStyle.component.hasOwnProperty('labelShow')) {
|
||||
chart.value.customStyle.component = {
|
||||
...chart.value.customStyle.component,
|
||||
labelShow: true,
|
||||
fontWeight: '',
|
||||
fontStyle: '',
|
||||
fontSize: '14',
|
||||
fontSizeBtn: '14',
|
||||
fontWeightBtn: '',
|
||||
fontStyleBtn: '',
|
||||
queryConditionWidth: 227,
|
||||
nameboxSpacing: 8,
|
||||
queryConditionSpacing: 16,
|
||||
labelColorBtn: '#ffffff',
|
||||
btnColor: '#3370ff'
|
||||
const initParams = () => {
|
||||
if (!chart.value.customStyle.component.hasOwnProperty('labelShow')) {
|
||||
chart.value.customStyle.component = {
|
||||
...chart.value.customStyle.component,
|
||||
labelShow: true,
|
||||
fontWeight: '',
|
||||
fontStyle: '',
|
||||
fontSize: '14',
|
||||
fontSizeBtn: '14',
|
||||
fontWeightBtn: '',
|
||||
fontStyleBtn: '',
|
||||
queryConditionWidth: 227,
|
||||
nameboxSpacing: 8,
|
||||
queryConditionSpacing: 16,
|
||||
labelColorBtn: '#ffffff',
|
||||
btnColor: '#3370ff'
|
||||
}
|
||||
}
|
||||
|
||||
if (!chart.value.customStyle.component.hasOwnProperty('placeholderShow')) {
|
||||
chart.value.customStyle.component = {
|
||||
...chart.value.customStyle.component,
|
||||
placeholderShow: true,
|
||||
placeholderSize: 14
|
||||
}
|
||||
}
|
||||
|
||||
if (props.element.propValue.length) {
|
||||
currentPlaceholder.value = props.element.propValue[0].id
|
||||
handleCurrentPlaceholder(props.element.propValue[0].id)
|
||||
}
|
||||
}
|
||||
initParams()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="attr-style">
|
||||
<input
|
||||
id="input"
|
||||
ref="files"
|
||||
type="file"
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
hidden
|
||||
@click="
|
||||
e => {
|
||||
e.target.value = ''
|
||||
}
|
||||
"
|
||||
@change="reUpload"
|
||||
/>
|
||||
<el-row class="de-collapse-style">
|
||||
<el-collapse v-model="state.styleActiveNames" class="style-collapse">
|
||||
<el-collapse v-model="styleActiveNames" class="style-collapse">
|
||||
<el-collapse-item :effect="themes" name="basicStyle" :title="t('chart.basic_style')">
|
||||
<el-form label-position="top">
|
||||
<el-form-item class="form-item margin-bottom-8" :class="'form-item-' + themes">
|
||||
@ -122,6 +247,82 @@ if (!chart.value.customStyle.component.hasOwnProperty('labelShow')) {
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
style="padding-left: 20px"
|
||||
class="form-item margin-bottom-8"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-radio-group
|
||||
:disabled="!commonBackgroundPop.backgroundColorSelect"
|
||||
:effect="themes"
|
||||
v-model="commonBackgroundPop.backgroundType"
|
||||
>
|
||||
<el-radio
|
||||
key="innerImage"
|
||||
v-if="commonBackgroundPop.backgroundType === 'innerImage'"
|
||||
label="innerImage"
|
||||
:effect="themes"
|
||||
>
|
||||
背景颜色
|
||||
</el-radio>
|
||||
<el-radio key="color" v-else label="color" :effect="themes"> 背景颜色 </el-radio>
|
||||
<el-radio label="outerImage" :effect="themes"> 背景图片 </el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="commonBackgroundPop.backgroundType === 'outerImage'"
|
||||
style="padding-left: 20px"
|
||||
class="form-item margin-bottom-8"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<div
|
||||
class="indented-item"
|
||||
:class="{
|
||||
disabled: !commonBackgroundPop.backgroundColorSelect
|
||||
}"
|
||||
>
|
||||
<div class="avatar-uploader-container" :class="`img-area_${themes}`">
|
||||
<el-upload
|
||||
action=""
|
||||
:effect="themes"
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
class="avatar-uploader"
|
||||
list-type="picture-card"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeUploadCheck"
|
||||
:http-request="upload"
|
||||
:file-list="state.fileList"
|
||||
:disabled="!commonBackgroundPop.backgroundColorSelect"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<el-row>
|
||||
<span
|
||||
style="margin-top: 2px"
|
||||
v-if="!state.commonBackground['outerImage']"
|
||||
class="image-hint"
|
||||
:class="`image-hint_${themes}`"
|
||||
>
|
||||
支持JPG、PNG、GIF、SVG
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
style="margin: 8px 0 0 -4px"
|
||||
v-if="state.commonBackground['outerImage']"
|
||||
text
|
||||
:disabled="!commonBackgroundPop.backgroundColorSelect"
|
||||
@click="goFile"
|
||||
>
|
||||
重新上传
|
||||
</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
<img-view-dialog v-model="state.dialogVisible" :image-url="state.dialogImageUrl" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-else
|
||||
class="form-item"
|
||||
style="padding-left: 20px"
|
||||
:class="'form-item-' + themes"
|
||||
@ -166,23 +367,62 @@ if (!chart.value.customStyle.component.hasOwnProperty('labelShow')) {
|
||||
<el-checkbox
|
||||
:effect="themes"
|
||||
size="small"
|
||||
v-model="chart.customStyle.component.textColorShow"
|
||||
v-model="chart.customStyle.component.placeholderShow"
|
||||
>
|
||||
提示文字颜色
|
||||
提示词
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="文本"
|
||||
class="form-item"
|
||||
style="padding-left: 20px"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-color-picker
|
||||
<div style="display: flex; align-items: center; width: 100%">
|
||||
<el-color-picker
|
||||
:effect="themes"
|
||||
:trigger-width="56"
|
||||
is-custom
|
||||
v-model="chart.customStyle.component.text"
|
||||
:disabled="!chart.customStyle.component.placeholderShow"
|
||||
:predefine="predefineColors"
|
||||
/>
|
||||
<el-input-number
|
||||
v-model="chart.customStyle.component.placeholderSize"
|
||||
:min="10"
|
||||
:max="20"
|
||||
style="margin-left: 8px"
|
||||
step-strictly
|
||||
:effect="themes"
|
||||
controls-position="right"
|
||||
/>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center; width: 100%; margin-top: 8px">
|
||||
<el-select
|
||||
v-model="currentPlaceholder"
|
||||
@change="handleCurrentPlaceholder"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in element.propValue"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="提示词"
|
||||
class="form-item"
|
||||
style="padding-left: 20px"
|
||||
:class="'form-item-' + themes"
|
||||
>
|
||||
<el-input
|
||||
:effect="themes"
|
||||
:trigger-width="108"
|
||||
is-custom
|
||||
v-model="chart.customStyle.component.text"
|
||||
:disabled="!chart.customStyle.component.textColorShow"
|
||||
:predefine="predefineColors"
|
||||
@change="handleCurrentPlaceholderChange"
|
||||
:disabled="!chart.customStyle.component.placeholderShow || !currentPlaceholder"
|
||||
v-model.lazy="currentSearch.placeholder"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item class="form-item margin-bottom-8" :class="'form-item-' + themes">
|
||||
@ -461,6 +701,85 @@ if (!chart.value.customStyle.component.hasOwnProperty('labelShow')) {
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.indented-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
.fill {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
color: #8f959e;
|
||||
|
||||
:deep(.avatar-uploader) {
|
||||
width: 90px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.img-area_dark {
|
||||
:deep(.ed-upload--picture-card) {
|
||||
.ed-icon {
|
||||
color: #5f5f5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
.img-area_light {
|
||||
:deep(.ed-upload--picture-card) {
|
||||
.ed-icon {
|
||||
color: #bbbfc4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: #8f959e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
width: 90px;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.avatar-uploader {
|
||||
width: 90px;
|
||||
:deep(.ed-upload) {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
line-height: 90px;
|
||||
}
|
||||
|
||||
:deep(.ed-upload-list li) {
|
||||
width: 80px !important;
|
||||
height: 80px !important;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #eff0f1;
|
||||
border: 1px dashed #dee0e3;
|
||||
border-radius: 4px;
|
||||
|
||||
.ed-icon {
|
||||
color: #1f2329;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-item {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, PropType, reactive, watch } from 'vue'
|
||||
import { computed, onMounted, PropType, reactive, watch } from 'vue'
|
||||
import {
|
||||
COLOR_PANEL,
|
||||
DEFAULT_BASIC_STYLE,
|
||||
@ -236,6 +236,10 @@ const mapSymbolOptions = [
|
||||
{ name: t('chart.line_symbol_diamond'), value: 'rhombus' }
|
||||
]
|
||||
|
||||
const customSymbolicMapSizeRange = computed(() => {
|
||||
let { extBubble } = JSON.parse(JSON.stringify(props.chart))
|
||||
return ['symbolic-map'].includes(props.chart.type) && extBubble?.length > 0
|
||||
})
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
@ -476,11 +480,53 @@ onMounted(() => {
|
||||
:max="40"
|
||||
v-model="state.basicStyleForm.mapSymbolSize"
|
||||
@change="changeBasicStyle('mapSymbolSize')"
|
||||
:disabled="customSymbolicMapSizeRange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="alpha-setting">
|
||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||
{{ t('chart.size') }}区间
|
||||
</label>
|
||||
<el-row style="flex: 1">
|
||||
<el-col :span="12">
|
||||
<el-form-item class="form-item alpha-slider" :class="'form-item-' + themes">
|
||||
<el-input
|
||||
type="number"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.mapSymbolSizeMin"
|
||||
:min="0"
|
||||
:max="100"
|
||||
class="basic-input-number"
|
||||
:controls="false"
|
||||
@change="changeBasicStyle('mapSymbolSizeMin')"
|
||||
:disabled="!customSymbolicMapSizeRange"
|
||||
>
|
||||
<template #suffix> PX </template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item class="form-item alpha-slider" :class="'form-item-' + themes">
|
||||
<el-input
|
||||
type="number"
|
||||
:effect="themes"
|
||||
v-model="state.basicStyleForm.mapSymbolSizeMax"
|
||||
:min="0"
|
||||
:max="100"
|
||||
class="basic-input-number"
|
||||
:controls="false"
|
||||
@change="changeBasicStyle('mapSymbolSizeMax')"
|
||||
:disabled="!customSymbolicMapSizeRange"
|
||||
>
|
||||
<template #suffix> PX </template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="alpha-setting">
|
||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||
{{ t('chart.not_alpha') }}
|
||||
|
@ -12,6 +12,7 @@ import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import Icon from '../../../../../../components/icon-custom/src/Icon.vue'
|
||||
import { iconFieldMap } from '@/components/icon-group/field-list'
|
||||
import { parseJson } from '../../../js/util'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@ -242,6 +243,7 @@ const init = () => {
|
||||
if (chart.customAttr) {
|
||||
const customAttr = chart.customAttr
|
||||
if (customAttr.label) {
|
||||
configCompat(customAttr.label)
|
||||
state.labelForm = defaultsDeep(customAttr.label, cloneDeep(COMPUTED_DEFAULT_LABEL.value))
|
||||
if (chartType.value === 'liquid' && state.labelForm.fontSize < fontSizeList.value[0].value) {
|
||||
state.labelForm.fontSize = fontSizeList.value[0].value
|
||||
@ -249,6 +251,13 @@ const init = () => {
|
||||
initSeriesLabel()
|
||||
formatterSelector.value?.blur()
|
||||
}
|
||||
//初始化标签位置
|
||||
initPosition()
|
||||
}
|
||||
}
|
||||
const configCompat = (labelAttr: DeepPartial<ChartLabelAttr>) => {
|
||||
if (labelAttr.showStackQuota === undefined) {
|
||||
labelAttr.showStackQuota = labelAttr.show
|
||||
}
|
||||
}
|
||||
const checkLabelContent = contentProp => {
|
||||
@ -320,33 +329,79 @@ const showPositionV = computed(() => {
|
||||
}
|
||||
return false
|
||||
})
|
||||
function initBidirectionalBarPosition() {
|
||||
if (chartType.value === 'bidirectional-bar') {
|
||||
const layout = props.chart.customAttr.basicStyle.layout
|
||||
const oldPosition = state?.labelForm?.position
|
||||
if (state?.labelForm?.position === 'inner' || state?.labelForm?.position === 'outer') {
|
||||
state.labelForm.position = 'middle'
|
||||
}
|
||||
if (layout === 'horizontal') {
|
||||
if (state?.labelForm?.position === 'top') {
|
||||
state.labelForm.position = 'right'
|
||||
}
|
||||
if (state?.labelForm?.position === 'bottom') {
|
||||
state.labelForm.position = 'left'
|
||||
}
|
||||
}
|
||||
if (layout === 'vertical') {
|
||||
if (state?.labelForm?.position === 'left') {
|
||||
state.labelForm.position = 'bottom'
|
||||
}
|
||||
if (state?.labelForm?.position === 'right') {
|
||||
state.labelForm.position = 'top'
|
||||
}
|
||||
}
|
||||
if (oldPosition !== state.labelForm.position) {
|
||||
changeLabelAttr('position')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initPosition() {
|
||||
if (chartType.value === 'bidirectional-bar') {
|
||||
initBidirectionalBarPosition()
|
||||
} else {
|
||||
const oldPosition = state?.labelForm?.position
|
||||
if (showProperty('rPosition')) {
|
||||
if (state?.labelForm?.position !== 'inner') {
|
||||
state.labelForm.position = 'outer'
|
||||
}
|
||||
} else if (showProperty('hPosition')) {
|
||||
if (state?.labelForm?.position === 'top') {
|
||||
state.labelForm.position = 'right'
|
||||
} else if (state?.labelForm?.position === 'bottom') {
|
||||
state.labelForm.position = 'left'
|
||||
} else if (state?.labelForm?.position === 'inner' || state?.labelForm?.position === 'outer') {
|
||||
state.labelForm.position = 'middle'
|
||||
}
|
||||
} else if (showProperty('vPosition')) {
|
||||
if (state?.labelForm?.position === 'left') {
|
||||
state.labelForm.position = 'bottom'
|
||||
} else if (state?.labelForm?.position === 'right') {
|
||||
state.labelForm.position = 'top'
|
||||
} else if (state?.labelForm?.position === 'inner' || state?.labelForm?.position === 'outer') {
|
||||
state.labelForm.position = 'middle'
|
||||
}
|
||||
}
|
||||
if (oldPosition !== state.labelForm.position) {
|
||||
changeLabelAttr('position')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.chart.customAttr.basicStyle.layout,
|
||||
() => {
|
||||
const layout = props.chart.customAttr.basicStyle.layout
|
||||
if (chartType.value === 'bidirectional-bar') {
|
||||
if (layout === 'horizontal') {
|
||||
if (state?.labelForm?.position === 'top') {
|
||||
state.labelForm.position = 'right'
|
||||
}
|
||||
if (state?.labelForm?.position === 'bottom') {
|
||||
state.labelForm.position = 'left'
|
||||
}
|
||||
}
|
||||
if (layout === 'vertical') {
|
||||
if (state?.labelForm?.position === 'left') {
|
||||
state.labelForm.position = 'bottom'
|
||||
}
|
||||
if (state?.labelForm?.position === 'right') {
|
||||
state.labelForm.position = 'top'
|
||||
}
|
||||
}
|
||||
changeLabelAttr('position')
|
||||
}
|
||||
initBidirectionalBarPosition()
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
watch(chartType, (value, oldValue) => {
|
||||
initPosition()
|
||||
})
|
||||
|
||||
const allFields = computed(() => {
|
||||
return defaultTo(props.allFields, []).map(item => ({
|
||||
key: item.dataeaseName,
|
||||
@ -403,6 +458,36 @@ const conversionPrecision = [
|
||||
label-position="top"
|
||||
>
|
||||
<el-row v-show="showEmpty" style="margin-bottom: 12px"> 无其他可设置的属性</el-row>
|
||||
<div>
|
||||
<el-form-item
|
||||
v-if="showProperty('showStackQuota')"
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
style="display: inline-block; margin-right: 8px"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.labelForm.showStackQuota"
|
||||
@change="changeLabelAttr('showStackQuota')"
|
||||
:label="t('chart.quota')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="showProperty('showTotal')"
|
||||
class="form-item"
|
||||
:class="'form-item-' + themes"
|
||||
style="display: inline-block"
|
||||
>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.labelForm.showTotal"
|
||||
@change="changeLabelAttr('showTotal')"
|
||||
:label="t('chart.total_show')"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-if="!isGroupBar">
|
||||
<el-space>
|
||||
<el-form-item
|
||||
@ -665,15 +750,6 @@ const conversionPrecision = [
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item v-if="showProperty('showTotal')" class="form-item" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="state.labelForm.showTotal"
|
||||
@change="changeLabelAttr('showTotal')"
|
||||
:label="t('chart.total_show')"
|
||||
/>
|
||||
</el-form-item>
|
||||
<template v-if="false && showProperty('totalFormatter')">
|
||||
<el-divider class="m-divider" :class="{ 'divider-dark': themes === 'dark' }" />
|
||||
<div v-show="state.labelForm.showTotal">
|
||||
|
@ -250,7 +250,7 @@ const init = () => {
|
||||
const showProperty = prop => {
|
||||
const instance = chartViewManager.getChartView(props.chart.render, props.chart.type)
|
||||
if (instance) {
|
||||
return instance.propertyInner['tooltip-selector'].includes(prop)
|
||||
return instance.propertyInner['tooltip-selector']?.includes(prop)
|
||||
}
|
||||
return props.propertyInner?.includes(prop)
|
||||
}
|
||||
|
@ -836,6 +836,7 @@ const calcData = (view, resetDrill = false, updateQuery = '') => {
|
||||
|
||||
const updateChartData = view => {
|
||||
curComponent.value['state'] = 'ready'
|
||||
useEmitt().emitter.emit('checkShowEmpty', { allFields: allFields.value, view: view })
|
||||
calcData(view, true, 'updateQuery')
|
||||
}
|
||||
|
||||
@ -1074,7 +1075,19 @@ const onAssistLineChange = val => {
|
||||
|
||||
const onThresholdChange = val => {
|
||||
view.value.senior.threshold = val
|
||||
renderChart(view.value)
|
||||
let type = undefined
|
||||
view.value.senior.threshold?.tableThreshold?.some(item => {
|
||||
if (item.conditions.some(i => i.type === 'dynamic')) {
|
||||
type = 'calcData'
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
if (type) {
|
||||
calcData(view.value)
|
||||
} else {
|
||||
renderChart(view.value)
|
||||
}
|
||||
}
|
||||
|
||||
const onMapMappingChange = val => {
|
||||
@ -1766,13 +1779,14 @@ const deleteChartFieldItem = id => {
|
||||
</div>
|
||||
<el-popover show-arrow :offset="8" placement="bottom" width="200" trigger="click">
|
||||
<template #reference>
|
||||
<el-icon
|
||||
v-show="route.path !== '/dvCanvas'"
|
||||
style="margin-left: 4px; cursor: pointer"
|
||||
<el-icon style="margin-left: 4px; cursor: pointer"
|
||||
><Icon><dvInfoSvg class="svg-icon" /></Icon
|
||||
></el-icon>
|
||||
</template>
|
||||
{{ view.id }}
|
||||
<div style="margin-bottom: 4px; font-size: 14px; color: #646a73">图表ID</div>
|
||||
<div style="font-size: 14px; color: #1f2329">
|
||||
{{ view.id }}
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</el-row>
|
||||
@ -3468,12 +3482,7 @@ const deleteChartFieldItem = id => {
|
||||
class="name-edit-form no-margin-bottom"
|
||||
prop="chartShowName"
|
||||
>
|
||||
<el-input
|
||||
v-model="state.itemForm.chartShowName"
|
||||
class="text"
|
||||
:maxlength="20"
|
||||
clearable
|
||||
/>
|
||||
<el-input v-model="state.itemForm.chartShowName" class="text" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
@ -339,7 +339,8 @@ export const DEFAULT_LABEL: ChartLabelAttr = {
|
||||
showTotal: false,
|
||||
totalFontSize: 12,
|
||||
totalColor: '#FFF',
|
||||
totalFormatter: formatterItem
|
||||
totalFormatter: formatterItem,
|
||||
showStackQuota: false
|
||||
}
|
||||
export const DEFAULT_TOOLTIP: ChartTooltipAttr = {
|
||||
show: true,
|
||||
@ -1494,7 +1495,7 @@ export const CHART_TYPE_CONFIGS = [
|
||||
},
|
||||
{
|
||||
category: 'other',
|
||||
title: '富文本',
|
||||
title: '其他',
|
||||
display: 'hidden',
|
||||
details: [
|
||||
{
|
||||
@ -1503,6 +1504,13 @@ export const CHART_TYPE_CONFIGS = [
|
||||
value: 'rich-text',
|
||||
title: '富文本',
|
||||
icon: 'rich-text'
|
||||
},
|
||||
{
|
||||
render: 'custom',
|
||||
category: 'quota',
|
||||
value: 'picture-group',
|
||||
title: '图片组',
|
||||
icon: 'picture-group'
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1570,7 +1578,9 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
||||
showSummary: false,
|
||||
summaryLabel: '总计',
|
||||
seriesColor: [],
|
||||
layout: 'horizontal'
|
||||
layout: 'horizontal',
|
||||
mapSymbolSizeMin: 4,
|
||||
mapSymbolSizeMax: 30
|
||||
}
|
||||
|
||||
export const BASE_VIEW_CONFIG = {
|
||||
|
@ -106,6 +106,14 @@ const noChildrenFieldChart = chart => {
|
||||
return ['area', 'bar'].includes(chart.type)
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持最值图表的折线图,面积图,柱状图,分组柱状图
|
||||
* @param chart
|
||||
*/
|
||||
const supportExtremumChartType = chart => {
|
||||
return ['line', 'area', 'bar', 'bar-group'].includes(chart.type)
|
||||
}
|
||||
|
||||
const chartContainerId = chart => {
|
||||
return chart.container + '_'
|
||||
}
|
||||
@ -131,6 +139,10 @@ function removeDivsWithPrefix(parentDivId, prefix) {
|
||||
|
||||
export const extremumEvt = (newChart, chart, _options, container) => {
|
||||
chart.container = container
|
||||
if (!supportExtremumChartType(chart)) {
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
const { yAxis } = parseJson(chart)
|
||||
newChart.once('beforerender', ev => {
|
||||
@ -145,8 +157,12 @@ export const extremumEvt = (newChart, chart, _options, container) => {
|
||||
}
|
||||
let showExtremum = false
|
||||
if (noChildrenFieldChart(chart) || yAxis.length > 1) {
|
||||
const seriesLabelFormatter = labelAttr.seriesLabelFormatter.find(
|
||||
d => d.name === minItem._origin.category || d.name === maxItem._origin.category
|
||||
const seriesLabelFormatter = labelAttr.seriesLabelFormatter.find(d =>
|
||||
d.chartShowName
|
||||
? d.chartShowName
|
||||
: d.name === minItem._origin.category || d.chartShowName
|
||||
? d.chartShowName
|
||||
: d.name === maxItem._origin.category
|
||||
)
|
||||
showExtremum = seriesLabelFormatter?.showExtremum
|
||||
} else {
|
||||
@ -248,8 +264,10 @@ export const createExtremumPoint = (chart, ev) => {
|
||||
let attr
|
||||
let showExtremum = false
|
||||
if (noChildrenFieldChart(chart) || yAxis.length > 1) {
|
||||
const seriesLabelFormatter = labelAttr.seriesLabelFormatter.find(
|
||||
d => d.name === pointObj._origin.category
|
||||
const seriesLabelFormatter = labelAttr.seriesLabelFormatter.find(d =>
|
||||
d.chartShowName
|
||||
? d.chartShowName === pointObj._origin.category
|
||||
: d.name === pointObj._origin.category
|
||||
)
|
||||
showExtremum = seriesLabelFormatter?.showExtremum
|
||||
attr = seriesLabelFormatter
|
||||
|
@ -18,7 +18,11 @@ import {
|
||||
BAR_EDITOR_PROPERTY,
|
||||
BAR_EDITOR_PROPERTY_INNER
|
||||
} from '@/views/chart/components/js/panel/charts/bar/common'
|
||||
import { getPadding, setGradientColor } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import {
|
||||
getLabel,
|
||||
getPadding,
|
||||
setGradientColor
|
||||
} from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { DEFAULT_LABEL } from '@/views/chart/components/editor/util/chart'
|
||||
import { clearExtremum, extremumEvt } from '@/views/chart/components/js/extremumUitl'
|
||||
@ -97,6 +101,7 @@ export class Bar extends G2PlotChartView<ColumnOptions, Column> {
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<Column>): Promise<Column> {
|
||||
const { chart, container, action } = drawOptions
|
||||
if (!chart?.data?.data?.length) {
|
||||
chart.container = container
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
@ -270,25 +275,55 @@ export class StackBar extends Bar {
|
||||
'showTotal',
|
||||
'totalColor',
|
||||
'totalFontSize',
|
||||
'totalFormatter'
|
||||
'totalFormatter',
|
||||
'showStackQuota'
|
||||
],
|
||||
'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'tooltipFormatter', 'show']
|
||||
}
|
||||
protected configLabel(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
const baseOptions = super.configLabel(chart, options)
|
||||
if (!baseOptions.label) {
|
||||
return baseOptions
|
||||
let label = getLabel(chart)
|
||||
if (!label) {
|
||||
return options
|
||||
}
|
||||
options = { ...options, label }
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum) {
|
||||
return valueFormatter(param.value, labelAttr.labelFormatter)
|
||||
if (labelAttr.showStackQuota || labelAttr.showStackQuota === undefined) {
|
||||
label.style.fill = labelAttr.color
|
||||
label = {
|
||||
...label,
|
||||
formatter: function (param: Datum) {
|
||||
return valueFormatter(param.value, labelAttr.labelFormatter)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
label = false
|
||||
}
|
||||
if (labelAttr.showTotal) {
|
||||
const formatterCfg = labelAttr.labelFormatter ?? formatterItem
|
||||
each(groupBy(options.data, 'field'), (values, key) => {
|
||||
const total = values.reduce((a, b) => a + b.value, 0)
|
||||
const value = valueFormatter(total, formatterCfg)
|
||||
if (!options.annotations) {
|
||||
options = {
|
||||
...options,
|
||||
annotations: []
|
||||
}
|
||||
}
|
||||
options.annotations.push({
|
||||
type: 'text',
|
||||
position: [key, total],
|
||||
content: `${value}`,
|
||||
style: {
|
||||
textAlign: 'center',
|
||||
fontSize: labelAttr.fontSize,
|
||||
fill: labelAttr.color
|
||||
},
|
||||
offsetY: -(parseInt(labelAttr.fontSize as unknown as string) / 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
return {
|
||||
...baseOptions,
|
||||
...options,
|
||||
label
|
||||
}
|
||||
}
|
||||
@ -347,38 +382,6 @@ export class StackBar extends Bar {
|
||||
return options
|
||||
}
|
||||
|
||||
protected configTotalLabel(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
if (!options.label) {
|
||||
return options
|
||||
}
|
||||
const { label } = parseJson(chart.customAttr)
|
||||
if (label.showTotal) {
|
||||
const formatterCfg = label.labelFormatter ?? formatterItem
|
||||
each(groupBy(options.data, 'field'), (values, key) => {
|
||||
const total = values.reduce((a, b) => a + b.value, 0)
|
||||
const value = valueFormatter(total, formatterCfg)
|
||||
if (!options.annotations) {
|
||||
options = {
|
||||
...options,
|
||||
annotations: []
|
||||
}
|
||||
}
|
||||
options.annotations.push({
|
||||
type: 'text',
|
||||
position: [key, total],
|
||||
content: `${value}`,
|
||||
style: {
|
||||
textAlign: 'center',
|
||||
fontSize: label.fontSize,
|
||||
fill: label.color
|
||||
},
|
||||
offsetY: -(parseInt(label.fontSize as unknown as string) / 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] {
|
||||
return setUpStackSeriesColor(chart, data)
|
||||
}
|
||||
@ -396,8 +399,7 @@ export class StackBar extends Bar {
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse,
|
||||
this.configData,
|
||||
this.configTotalLabel
|
||||
this.configData
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
@ -510,6 +512,25 @@ export class GroupStackBar extends StackBar {
|
||||
}
|
||||
}
|
||||
|
||||
protected configLabel(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
const baseOptions = super.configLabel(chart, options)
|
||||
if (!baseOptions.label) {
|
||||
return baseOptions
|
||||
}
|
||||
const { label: labelAttr } = parseJson(chart.customAttr)
|
||||
baseOptions.label.style.fill = labelAttr.color
|
||||
const label = {
|
||||
...baseOptions.label,
|
||||
formatter: function (param: Datum) {
|
||||
return valueFormatter(param.value, labelAttr.labelFormatter)
|
||||
}
|
||||
}
|
||||
return {
|
||||
...baseOptions,
|
||||
label
|
||||
}
|
||||
}
|
||||
|
||||
protected configTooltip(chart: Chart, options: ColumnOptions): ColumnOptions {
|
||||
const tooltipAttr = parseJson(chart.customAttr).tooltip
|
||||
if (!tooltipAttr.show) {
|
||||
|
@ -31,6 +31,10 @@ const DEFAULT_DATA = []
|
||||
export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_value_axis')} / ${t('chart.quota')}`,
|
||||
type: 'q'
|
||||
@ -301,6 +305,14 @@ export class HorizontalBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
* 堆叠条形图
|
||||
*/
|
||||
export class HorizontalStackBar extends HorizontalBar {
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
extStack: {
|
||||
name: `${t('chart.stack_item')} / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
propertyInner = {
|
||||
...this['propertyInner'],
|
||||
'label-selector': ['color', 'fontSize', 'hPosition', 'labelFormatter'],
|
||||
@ -360,7 +372,7 @@ export class HorizontalStackBar extends HorizontalBar {
|
||||
if (mainSort || subSort) {
|
||||
return options
|
||||
}
|
||||
const quotaSort = yAxis?.[0].sort !== 'none'
|
||||
const quotaSort = yAxis?.[0]?.sort !== 'none'
|
||||
if (!quotaSort || !extStack.length || !yAxis.length) {
|
||||
return options
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ const { t } = useI18n()
|
||||
|
||||
export class ProgressBar extends G2PlotChartView<BarOptions, G2Progress> {
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.form_type')} / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
|
@ -23,7 +23,6 @@ const DEFAULT_DATA = []
|
||||
*/
|
||||
export class RangeBar extends G2PlotChartView<BarOptions, Bar> {
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_value_start')} / ${t('chart.time_dimension_or_quota')}`,
|
||||
limit: 1,
|
||||
|
@ -4,6 +4,8 @@ import { flow, hexColorToRGBA, parseJson } from '../../../util'
|
||||
import { valueFormatter } from '../../../formatter'
|
||||
import { getPadding, getTooltipSeriesTotalMap, setGradientColor } from '../../common/common_antv'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
/**
|
||||
* 瀑布图
|
||||
@ -62,6 +64,17 @@ export class Waterfall extends G2PlotChartView<WaterfallOptions, G2Waterfall> {
|
||||
]
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'filter', 'drill', 'extLabel', 'extTooltip']
|
||||
axisConfig = {
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_value_axis')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Waterfall>): Promise<G2Waterfall> {
|
||||
const { chart, container, action } = drawOptions
|
||||
if (!chart.data?.data) {
|
||||
|
@ -44,6 +44,10 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
|
||||
axis: AxisType[] = [...LINE_AXIS_TYPE]
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_value_axis')} / ${t('chart.quota')}`,
|
||||
type: 'q'
|
||||
@ -98,6 +102,7 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Area>): Promise<G2Area> {
|
||||
const { chart, container, action } = drawOptions
|
||||
if (!chart.data?.data?.length) {
|
||||
chart.container = container
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
@ -288,6 +293,14 @@ export class StackArea extends Area {
|
||||
'label-selector': ['fontSize', 'color', 'labelFormatter'],
|
||||
'tooltip-selector': ['fontSize', 'color', 'tooltipFormatter', 'show']
|
||||
}
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
extStack: {
|
||||
name: `${t('chart.stack_item')} / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
protected configLabel(chart: Chart, options: AreaOptions): AreaOptions {
|
||||
const customAttr = parseJson(chart.customAttr)
|
||||
const labelAttr = customAttr.label
|
||||
|
@ -42,6 +42,15 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
axis: AxisType[] = [...LINE_AXIS_TYPE, 'xAxisExt']
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
},
|
||||
xAxisExt: {
|
||||
name: `${t('chart.chart_group')} / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_value_axis')} / ${t('chart.quota')}`,
|
||||
type: 'q'
|
||||
@ -50,6 +59,7 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Line>): Promise<G2Line> {
|
||||
const { chart, action, container } = drawOptions
|
||||
if (!chart.data?.data?.length) {
|
||||
chart.container = container
|
||||
clearExtremum(chart)
|
||||
return
|
||||
}
|
||||
@ -288,8 +298,11 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
}
|
||||
protected configLegend(chart: Chart, options: LineOptions): LineOptions {
|
||||
const optionTmp = super.configLegend(chart, options)
|
||||
if (!optionTmp.legend) {
|
||||
return optionTmp
|
||||
}
|
||||
const xAxisExt = chart.xAxisExt[0]
|
||||
if (optionTmp.legend && xAxisExt?.customSort?.length > 0) {
|
||||
if (xAxisExt?.customSort?.length > 0) {
|
||||
// 图例自定义排序
|
||||
const l = optionTmp.legend
|
||||
const basicStyle = parseJson(chart.customAttr).basicStyle
|
||||
@ -302,11 +315,8 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
marker: {
|
||||
symbol: l.marker.symbol,
|
||||
style: {
|
||||
r: 6,
|
||||
fill: 'rgba(0,0,0,0)',
|
||||
lineWidth: 2,
|
||||
lineJoin: 'round',
|
||||
stroke: basicStyle.colors[index % basicStyle.colors.length]
|
||||
r: 4,
|
||||
fill: basicStyle.colors[index % basicStyle.colors.length]
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -321,6 +331,12 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
legend
|
||||
}
|
||||
}
|
||||
optionTmp.legend.marker.style = style => {
|
||||
return {
|
||||
r: 4,
|
||||
fill: style.stroke
|
||||
}
|
||||
}
|
||||
return optionTmp
|
||||
}
|
||||
protected setupOptions(chart: Chart, options: LineOptions): LineOptions {
|
||||
|
@ -46,7 +46,6 @@ export class StockLine extends G2PlotChartView<MixOptions, Mix> {
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'filter', 'extLabel', 'extTooltip']
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `日期 / ${t('chart.dimension')}`,
|
||||
limit: 1,
|
||||
|
@ -47,18 +47,21 @@ export class FlowMap extends L7ChartView<Scene, L7Config> {
|
||||
flowMapStartName: {
|
||||
name: `起点名称 / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
flowMapEndName: {
|
||||
name: `终点名称 / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
yAxis: {
|
||||
name: `线条粗细 / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1,
|
||||
tooltip: '该指标生效时,样式中线条配置的线条宽度属性将失效'
|
||||
tooltip: '该指标生效时,样式中线条配置的线条宽度属性将失效',
|
||||
allowEmpty: true
|
||||
}
|
||||
}
|
||||
constructor() {
|
||||
|
@ -52,13 +52,16 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
xAxisExt: {
|
||||
name: `颜色 / ${t('chart.dimension')}`,
|
||||
type: 'd',
|
||||
limit: 1
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
extBubble: {
|
||||
name: `${t('chart.bubble_size')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1,
|
||||
tooltip: '该指标生效时,样式基础样式中的大小属性将失效'
|
||||
tooltip:
|
||||
'该指标生效时,样式基础样式中的大小属性将失效,同时可在样式基础样式中的大小区间配置大小区间',
|
||||
allowEmpty: true
|
||||
}
|
||||
}
|
||||
constructor() {
|
||||
@ -158,8 +161,16 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
const xAxis = deepCopy(chart.xAxis)
|
||||
const xAxisExt = deepCopy(chart.xAxisExt)
|
||||
const extBubble = deepCopy(chart.extBubble)
|
||||
const { mapSymbolOpacity, mapSymbolSize, mapSymbol, mapSymbolStrokeWidth, colors, alpha } =
|
||||
deepCopy(basicStyle)
|
||||
const {
|
||||
mapSymbolOpacity,
|
||||
mapSymbolSize,
|
||||
mapSymbol,
|
||||
mapSymbolStrokeWidth,
|
||||
colors,
|
||||
alpha,
|
||||
mapSymbolSizeMin,
|
||||
mapSymbolSizeMax
|
||||
} = deepCopy(basicStyle)
|
||||
const colorsWithAlpha = colors.map(color => hexColorToRGBA(color, alpha))
|
||||
let colorIndex = 0
|
||||
// 存储已分配的颜色
|
||||
@ -179,7 +190,7 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
return {
|
||||
...item,
|
||||
color,
|
||||
size: item[sizeKey] ?? mapSymbolSize,
|
||||
size: parseInt(item[sizeKey]) ?? mapSymbolSize,
|
||||
name: identifier
|
||||
}
|
||||
})
|
||||
@ -212,7 +223,7 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
})
|
||||
}
|
||||
if (sizeKey) {
|
||||
pointLayer.size('size', [4, 30])
|
||||
pointLayer.size('size', [mapSymbolSizeMin, mapSymbolSizeMax])
|
||||
} else {
|
||||
pointLayer.size(mapSymbolSize)
|
||||
}
|
||||
|
@ -88,11 +88,11 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
'extTooltip'
|
||||
]
|
||||
axisConfig: AxisConfig = {
|
||||
...this['axisConfig'],
|
||||
extBubble: {
|
||||
name: `${t('chart.bubble_size')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
},
|
||||
xAxis: {
|
||||
name: `${t('chart.form_type')} / ${t('chart.dimension')}`,
|
||||
@ -413,7 +413,7 @@ export class Quadrant extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
if (!(xAxis?.length && yAxis?.length && yAxisExt?.length)) {
|
||||
return []
|
||||
}
|
||||
const tmp = data[0].data
|
||||
const tmp = data?.[0]?.data
|
||||
return setUpSingleDimensionSeriesColor(chart, tmp)
|
||||
}
|
||||
protected setupOptions(chart: Chart, options: ScatterOptions) {
|
||||
|
@ -24,7 +24,6 @@ const DEFAULT_DATA = []
|
||||
*/
|
||||
export class RangeBar extends G2PlotChartView<SankeyOptions, Sankey> {
|
||||
axisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis_start')} / ${t('chart.dimension')}`,
|
||||
limit: 1,
|
||||
|
@ -75,7 +75,10 @@ export class Scatter extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'yAxis', 'extBubble', 'filter', 'drill', 'extLabel', 'extTooltip']
|
||||
axisConfig: AxisConfig = {
|
||||
...this['axisConfig'],
|
||||
xAxis: {
|
||||
name: `${t('chart.drag_block_type_axis')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
...this['axisConfig'].yAxis,
|
||||
limit: undefined
|
||||
@ -83,7 +86,8 @@ export class Scatter extends G2PlotChartView<ScatterOptions, G2Scatter> {
|
||||
extBubble: {
|
||||
name: `${t('chart.bubble_size')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1
|
||||
limit: 1,
|
||||
allowEmpty: true
|
||||
}
|
||||
}
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Scatter>): Promise<G2Scatter> {
|
||||
|
@ -56,7 +56,7 @@ export const PIE_AXIS_CONFIG: AxisConfig = {
|
||||
type: 'd'
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_pie_label')} / ${t('chart.quota')}`,
|
||||
name: `${t('chart.drag_block_pie_angle')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1
|
||||
}
|
||||
|
@ -19,12 +19,21 @@ import { valueFormatter } from '@/views/chart/components/js/formatter'
|
||||
import { Datum } from '@antv/g2plot/esm/types/common'
|
||||
import { add } from 'mathjs'
|
||||
import isEmpty from 'lodash-es/isEmpty'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
const { t } = useI18n()
|
||||
|
||||
export class Rose extends G2PlotChartView<RoseOptions, G2Rose> {
|
||||
axis: AxisType[] = PIE_AXIS_TYPE
|
||||
properties: EditorProperty[] = PIE_EDITOR_PROPERTY
|
||||
propertyInner: EditorPropertyInner = PIE_EDITOR_PROPERTY_INNER
|
||||
axisConfig = PIE_AXIS_CONFIG
|
||||
axisConfig: AxisConfig = {
|
||||
...PIE_AXIS_CONFIG,
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_pie_radius')} / ${t('chart.quota')}`,
|
||||
type: 'q',
|
||||
limit: 1
|
||||
}
|
||||
}
|
||||
|
||||
async drawChart(drawOptions: G2PlotDrawOptions<G2Rose>): Promise<G2Rose> {
|
||||
const { chart, container, action } = drawOptions
|
||||
|
@ -1,4 +1,12 @@
|
||||
import { S2Event, S2Options, TableColCell, TableDataCell, TableSheet, ViewMeta } from '@antv/s2'
|
||||
import {
|
||||
type LayoutResult,
|
||||
S2Event,
|
||||
S2Options,
|
||||
TableColCell,
|
||||
TableDataCell,
|
||||
TableSheet,
|
||||
ViewMeta
|
||||
} from '@antv/s2'
|
||||
import { formatterItem, valueFormatter } from '../../../formatter'
|
||||
import { parseJson } from '../../../util'
|
||||
import { S2ChartView, S2DrawOptions } from '../../types/impl/s2'
|
||||
@ -65,7 +73,7 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
const containerDom = document.getElementById(container)
|
||||
|
||||
// fields
|
||||
let fields = chart.data.fields
|
||||
let fields = chart.data?.fields ?? []
|
||||
const columns = []
|
||||
const meta = []
|
||||
const axisMap = chart.xAxis.reduce((pre, cur) => {
|
||||
@ -187,11 +195,66 @@ export class TableInfo extends S2ChartView<TableSheet> {
|
||||
}
|
||||
} else {
|
||||
// header interaction
|
||||
chart.container = container
|
||||
this.configHeaderInteraction(chart, s2Options)
|
||||
}
|
||||
// 开始渲染
|
||||
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)
|
||||
|
||||
// 自适应铺满
|
||||
if (customAttr.basicStyle.tableColumnMode === 'adapt') {
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, () => {
|
||||
newChart.store.set('lastLayoutResult', newChart.facet.layoutResult)
|
||||
})
|
||||
newChart.on(S2Event.LAYOUT_AFTER_HEADER_LAYOUT, (ev: LayoutResult) => {
|
||||
const status = newChart.store.get('status')
|
||||
if (status === 'default') {
|
||||
return
|
||||
}
|
||||
const lastLayoutResult = newChart.store.get('lastLayoutResult') as LayoutResult
|
||||
if (status === 'expanded' && lastLayoutResult) {
|
||||
// 拖拽表头定义宽度,和上一次布局对比,保留除已拖拽列之外的宽度
|
||||
const widthByFieldValue = newChart.options.style?.colCfg?.widthByFieldValue
|
||||
const lastLayoutWidthMap: Record<string, number> = lastLayoutResult?.colLeafNodes.reduce(
|
||||
(p, n) => {
|
||||
p[n.value] = widthByFieldValue?.[n.value] ?? n.width
|
||||
return p
|
||||
},
|
||||
{}
|
||||
)
|
||||
const totalWidth = ev.colLeafNodes.reduce((p, n) => {
|
||||
n.width = lastLayoutWidthMap[n.value]
|
||||
n.x = p
|
||||
return p + n.width
|
||||
}, 0)
|
||||
ev.colsHierarchy.width = totalWidth
|
||||
} else {
|
||||
// 第一次渲染初始化,把图片字段固定为 120 进行计算
|
||||
const urlFields = fields.filter(field => field.deType === 7).map(f => f.dataeaseName)
|
||||
const totalWidthWithImg = ev.colLeafNodes.reduce((p, n) => {
|
||||
return p + (urlFields.includes(n.field) ? 120 : n.width)
|
||||
}, 0)
|
||||
if (containerDom.offsetWidth <= totalWidthWithImg) {
|
||||
// 图库计算的布局宽度已经大于等于容器宽度,不需要再扩大,不处理
|
||||
newChart.store.set('status', 'default')
|
||||
return
|
||||
}
|
||||
// 图片字段固定 120, 剩余宽度按比例均摊到其他字段进行扩大
|
||||
const totalWidthWithoutImg = ev.colLeafNodes.reduce((p, n) => {
|
||||
return p + (urlFields.includes(n.field) ? 0 : n.width)
|
||||
}, 0)
|
||||
const restWidth = containerDom.offsetWidth - urlFields.length * 120
|
||||
const scale = restWidth / totalWidthWithoutImg
|
||||
const totalWidth = ev.colLeafNodes.reduce((p, n) => {
|
||||
n.width = urlFields.includes(n.field) ? 120 : n.width * scale
|
||||
n.x = p
|
||||
return p + n.width
|
||||
}, 0)
|
||||
ev.colsHierarchy.width = Math.min(containerDom.offsetWidth, totalWidth)
|
||||
newChart.store.set('status', 'expanded')
|
||||
}
|
||||
})
|
||||
}
|
||||
// click
|
||||
newChart.on(S2Event.DATA_CELL_CLICK, ev => {
|
||||
const cell = newChart.getCell(ev.target)
|
||||
|
@ -4,6 +4,7 @@ import { copyContent, SortTooltip } from '@/views/chart/components/js/panel/comm
|
||||
import { S2ChartView, S2DrawOptions } from '@/views/chart/components/js/panel/types/impl/s2'
|
||||
import { parseJson } from '@/views/chart/components/js/util'
|
||||
import {
|
||||
type LayoutResult,
|
||||
S2Event,
|
||||
S2Options,
|
||||
SHAPE_STYLE_MAP,
|
||||
@ -165,6 +166,7 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
}
|
||||
} else {
|
||||
// header interaction
|
||||
chart.container = container
|
||||
this.configHeaderInteraction(chart, s2Options)
|
||||
}
|
||||
|
||||
@ -207,7 +209,63 @@ export class TableNormal extends S2ChartView<TableSheet> {
|
||||
}
|
||||
// 开始渲染
|
||||
const newChart = new TableSheet(containerDom, s2DataConfig, s2Options)
|
||||
|
||||
// 总计紧贴在单元格后面
|
||||
if (customAttr.basicStyle.showSummary) {
|
||||
newChart.on(S2Event.LAYOUT_BEFORE_RENDER, () => {
|
||||
const totalHeight =
|
||||
customAttr.tableHeader.tableTitleHeight * 2 +
|
||||
customAttr.tableCell.tableItemHeight * (newData.length - 1)
|
||||
if (totalHeight < newChart.options.height) {
|
||||
// 6 是阴影高度
|
||||
newChart.options.height =
|
||||
totalHeight < newChart.options.height - 6 ? totalHeight + 6 : totalHeight
|
||||
}
|
||||
})
|
||||
}
|
||||
// 自适应铺满
|
||||
if (customAttr.basicStyle.tableColumnMode === 'adapt') {
|
||||
newChart.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, () => {
|
||||
newChart.store.set('lastLayoutResult', newChart.facet.layoutResult)
|
||||
})
|
||||
newChart.on(S2Event.LAYOUT_AFTER_HEADER_LAYOUT, (ev: LayoutResult) => {
|
||||
const status = newChart.store.get('status')
|
||||
if (status === 'default') {
|
||||
return
|
||||
}
|
||||
const lastLayoutResult = newChart.store.get('lastLayoutResult') as LayoutResult
|
||||
if (status === 'expanded' && lastLayoutResult) {
|
||||
// 拖拽表头定义宽度,和上一次布局对比,保留除已拖拽列之外的宽度
|
||||
const widthByFieldValue = newChart.options.style?.colCfg?.widthByFieldValue
|
||||
const lastLayoutWidthMap: Record<string, number> = lastLayoutResult?.colLeafNodes.reduce(
|
||||
(p, n) => {
|
||||
p[n.value] = widthByFieldValue?.[n.value] ?? n.width
|
||||
return p
|
||||
},
|
||||
{}
|
||||
)
|
||||
const totalWidth = ev.colLeafNodes.reduce((p, n) => {
|
||||
n.width = lastLayoutWidthMap[n.value]
|
||||
n.x = p
|
||||
return p + n.width
|
||||
}, 0)
|
||||
ev.colsHierarchy.width = totalWidth
|
||||
} else {
|
||||
const scale = containerDom.offsetWidth / ev.colsHierarchy.width
|
||||
if (scale <= 1) {
|
||||
// 图库计算的布局宽度已经大于等于容器宽度,不需要再扩大,不处理
|
||||
newChart.store.set('status', 'default')
|
||||
return
|
||||
}
|
||||
const totalWidth = ev.colLeafNodes.reduce((p, n) => {
|
||||
n.width = n.width * scale
|
||||
n.x = p
|
||||
return p + n.width
|
||||
}, 0)
|
||||
ev.colsHierarchy.width = Math.min(containerDom.offsetWidth, totalWidth)
|
||||
newChart.store.set('status', 'expanded')
|
||||
}
|
||||
})
|
||||
}
|
||||
// click
|
||||
newChart.on(S2Event.DATA_CELL_CLICK, ev => {
|
||||
const cell = newChart.getCell(ev.target)
|
||||
|
@ -107,7 +107,8 @@ export class TablePivot extends S2ChartView<PivotSheet> {
|
||||
},
|
||||
xAxisExt: {
|
||||
name: `${t('chart.drag_block_table_data_column')} / ${t('chart.dimension')}`,
|
||||
type: 'd'
|
||||
type: 'd',
|
||||
allowEmpty: true
|
||||
},
|
||||
yAxis: {
|
||||
name: `${t('chart.drag_block_table_data_column')} / ${t('chart.quota')}`,
|
||||
@ -508,7 +509,7 @@ function getCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
const rowPath = getTreePath(query, row)
|
||||
const colPath = getTreePath(query, col)
|
||||
const path = [...rowPath, ...colPath]
|
||||
const { data } = colSubTotal[subLevel]
|
||||
const { data } = colSubTotal?.[subLevel]
|
||||
let val
|
||||
if (path.length && data) {
|
||||
path.push(quotaField)
|
||||
@ -525,6 +526,11 @@ function getCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
path.push(quotaField)
|
||||
val = get(rowTotal.data, path)
|
||||
}
|
||||
// 列维度为空,行维度不为空
|
||||
if (!col.length && row.length) {
|
||||
const path = [query[EXTRA_FIELD]]
|
||||
val = get(rowTotal.data, path)
|
||||
}
|
||||
return val
|
||||
}
|
||||
// 行小计
|
||||
@ -534,7 +540,7 @@ function getCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
const colPath = getTreePath(query, col)
|
||||
const rowPath = getTreePath(query, row)
|
||||
const path = [...colPath, ...rowPath]
|
||||
const { data } = rowSubTotal[rowLevel]
|
||||
const { data } = rowSubTotal?.[rowLevel]
|
||||
let val
|
||||
if (path.length && rowSubTotal) {
|
||||
path.push(quotaField)
|
||||
@ -546,7 +552,7 @@ function getCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
if (status.isRowTotal && status.isColSubTotal) {
|
||||
const { colSubInRowTotal } = customCalc
|
||||
const colLevel = getSubLevel(query, col)
|
||||
const { data } = colSubInRowTotal[colLevel]
|
||||
const { data } = colSubInRowTotal?.[colLevel]
|
||||
const colPath = getTreePath(query, col)
|
||||
let val
|
||||
if (colPath.length && colSubInRowTotal) {
|
||||
@ -559,7 +565,7 @@ function getCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
if (status.isColTotal && status.isRowSubTotal) {
|
||||
const { rowSubInColTotal } = customCalc
|
||||
const rowSubLevel = getSubLevel(query, row)
|
||||
const data = rowSubInColTotal[rowSubLevel]?.data
|
||||
const data = rowSubInColTotal?.[rowSubLevel]?.data
|
||||
const path = getTreePath(query, row)
|
||||
let val
|
||||
if (path.length && rowSubInColTotal) {
|
||||
@ -573,7 +579,7 @@ function getCustomCalcResult(query, axisMap, status: TotalStatus, customCalc) {
|
||||
const { rowSubInColSub } = customCalc
|
||||
const rowSubLevel = getSubLevel(query, row)
|
||||
const colSubLevel = getSubLevel(query, col)
|
||||
const { data } = rowSubInColSub[rowSubLevel][colSubLevel]
|
||||
const { data } = rowSubInColSub?.[rowSubLevel]?.[colSubLevel]
|
||||
const rowPath = getTreePath(query, row)
|
||||
const colPath = getTreePath(query, col)
|
||||
const path = [...rowPath, ...colPath]
|
||||
|
@ -308,7 +308,10 @@ export function getLegend(chart: Chart) {
|
||||
offsetX: offsetX,
|
||||
offsetY: offsetY,
|
||||
marker: {
|
||||
symbol: legendSymbol
|
||||
symbol: legendSymbol,
|
||||
style: {
|
||||
r: 4
|
||||
}
|
||||
},
|
||||
itemHeight: l.fontSize + 4,
|
||||
radio: false,
|
||||
|