fix(图表): 修复水波图无法加载数据的问题,以及优化动态字段处理逻辑,确保正确重置和获取字段值

This commit is contained in:
jianneng-fit2cloud
2026-05-14 17:29:47 +08:00
parent f371690af6
commit 262ac29db6
5 changed files with 130 additions and 17 deletions

View File

@@ -6,7 +6,6 @@ import io.dataease.chart.utils.ChartDataBuild;
import io.dataease.engine.sql.SQLProvider;
import io.dataease.engine.trans.Quota2SQLObj;
import io.dataease.engine.utils.Utils;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.dto.DatasetTableFieldDTO;
import io.dataease.extensions.datasource.dto.DatasourceRequest;
import io.dataease.extensions.datasource.dto.DatasourceSchemaDTO;
@@ -14,7 +13,6 @@ import io.dataease.extensions.datasource.model.SQLMeta;
import io.dataease.extensions.datasource.provider.Provider;
import io.dataease.extensions.view.dto.*;
import io.dataease.extensions.view.util.FieldUtil;
import io.dataease.i18n.Translator;
import io.dataease.utils.BeanUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@@ -22,8 +20,6 @@ import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NumericalChartHandler extends DefaultChartHandler {
@Override
@@ -64,13 +60,26 @@ public class NumericalChartHandler extends DefaultChartHandler {
String maxType = (String) target.get(type);
if (StringUtils.equalsIgnoreCase("dynamic", maxType)) {
Map<String, Object> maxField = (Map<String, Object>) target.get(field);
if (maxField.get("id") == null || StringUtils.isEmpty(maxField.get("id").toString())) {
DEException.throwException(Translator.get("i18n_gauge_field_delete"));
if (maxField == null || maxField.get("id") == null || StringUtils.isBlank(maxField.get("id").toString())) {
resetDynamicField(target, type, field);
return null;
}
Long id;
try {
id = Long.valueOf(maxField.get("id").toString());
} catch (NumberFormatException e) {
resetDynamicField(target, type, field);
return null;
}
Long id = Long.valueOf((String) maxField.get("id"));
String summary = (String) maxField.get("summary");
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(id);
if (ObjectUtils.isNotEmpty(datasetTableField)) {
if (datasetTableField.getDeType() == 0 || datasetTableField.getDeType() == 1 || datasetTableField.getDeType() == 5) {
if (!StringUtils.containsIgnoreCase(summary, "count")) {
resetDynamicField(target, type, field);
return null;
}
}
ChartViewFieldDTO dto = new ChartViewFieldDTO();
BeanUtils.copyBean(dto, datasetTableField);
if (StringUtils.isEmpty(dto.getSummary())) {
@@ -78,9 +87,30 @@ public class NumericalChartHandler extends DefaultChartHandler {
}
return dto;
} else {
DEException.throwException(Translator.get("i18n_gauge_field_delete"));
resetDynamicField(target, type, field);
}
}
return null;
}
protected void resetDynamicField(Map<String, Object> target, String type, String field) {
target.put(type, "fix");
target.put(field, Map.of("id", "", "summary", ""));
switch (type) {
case "gaugeMinType":
target.putIfAbsent("gaugeMin", 0);
target.putIfAbsent("gaugeMin", 0);
break;
case "gaugeMaxType":
target.putIfAbsent("gaugeMax", 100);
target.putIfAbsent("gaugeMax", 100);
break;
case "liquidMaxType":
target.putIfAbsent("liquidMax", 100);
target.putIfAbsent("liquidMax", 100);
break;
default:
break;
}
}
}

View File

@@ -447,13 +447,24 @@ public class ChartDataManage {
String maxType = (String) sizeObj.get(type);
if (StringUtils.equalsIgnoreCase("dynamic", maxType)) {
Map<String, Object> maxField = (Map<String, Object>) sizeObj.get(field);
Long id = Long.valueOf((String) maxField.get("id"));
if (maxField == null || maxField.get("id") == null || StringUtils.isBlank(maxField.get("id").toString())) {
resetDynamicField(sizeObj, type, field);
return null;
}
long id;
try {
id = Long.parseLong(maxField.get("id").toString());
} catch (NumberFormatException e) {
resetDynamicField(sizeObj, type, field);
return null;
}
String summary = (String) maxField.get("summary");
DatasetTableFieldDTO datasetTableField = datasetTableFieldManage.selectById(id);
if (ObjectUtils.isNotEmpty(datasetTableField)) {
if (datasetTableField.getDeType() == 0 || datasetTableField.getDeType() == 1 || datasetTableField.getDeType() == 5) {
if (!StringUtils.containsIgnoreCase(summary, "count")) {
DEException.throwException(Translator.get("i18n_gauge_field_change"));
resetDynamicField(sizeObj, type, field);
return null;
}
}
ChartViewFieldDTO dto = new ChartViewFieldDTO();
@@ -461,12 +472,33 @@ public class ChartDataManage {
dto.setSummary(summary);
return dto;
} else {
DEException.throwException(Translator.get("i18n_gauge_field_delete"));
resetDynamicField(sizeObj, type, field);
}
}
return null;
}
private void resetDynamicField(Map<String, Object> sizeObj, String type, String field) {
sizeObj.put(type, "fix");
sizeObj.put(field, Map.of("id", "", "summary", ""));
switch (type) {
case "gaugeMinType":
sizeObj.putIfAbsent("gaugeMin", 0);
sizeObj.putIfAbsent("gaugeMin", 0);
break;
case "gaugeMaxType":
sizeObj.putIfAbsent("gaugeMax", 100);
sizeObj.putIfAbsent("gaugeMax", 100);
break;
case "liquidMaxType":
sizeObj.putIfAbsent("liquidMax", 100);
sizeObj.putIfAbsent("liquidMax", 100);
break;
default:
break;
}
}
private ChartViewDTO emptyChartViewDTO(ChartViewDTO view) {
ChartViewDTO dto = new ChartViewDTO();
BeanUtils.copyBean(dto, view);

View File

@@ -91,6 +91,8 @@ public class ChartDataServer implements ChartDataApi {
chartDataManage.encodeData(dto);
return dto;
}
} catch (DEException e) {
throw e;
} catch (Exception e) {
DEException.throwException(ResultCode.DATA_IS_WRONG.code(), e.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(e));
}

View File

@@ -140,6 +140,9 @@ const positionComponentShow = computed(() => {
})
const showProperties = (property: EditorProperty) => properties.value?.includes(property)
const getPropertyInner = (property: EditorProperty) => propertyInnerAll.value?.[property] || []
const showPropertySwitch = (property: EditorProperty, prop: string) =>
getPropertyInner(property).includes(prop)
const onMiscChange = (val, prop) => {
emit('onMiscChange', val, prop)
@@ -201,7 +204,7 @@ const onBackgroundChange = (val, prop) => {
state.initReady && emit('onBackgroundChange', val, prop)
}
const onActiveChange = val => {
const onActiveChange = () => {
snapshotStore.recordSnapshotCache('onActiveChange')
state.initReady &&
emit('onStyleAttrChange', {
@@ -490,11 +493,12 @@ watch(
/>
</collapse-switch-item>
<collapse-switch-item
v-if="showProperties('tooltip-selector')"
v-model="chart.customAttr.tooltip.show"
:themes="themes"
:change-model="chart.customAttr.tooltip"
:title="t('chart.tooltip')"
:show-switch="propertyInnerAll['tooltip-selector'].includes('show')"
:show-switch="showPropertySwitch('tooltip-selector', 'show')"
name="tooltip"
@modelChange="val => onTooltipChange({ data: val }, 'show')"
>
@@ -514,7 +518,7 @@ watch(
:change-model="chart.customAttr.tableHeader"
:effect="themes"
:title="t('chart.table_header')"
:show-switch="propertyInnerAll['table-header-selector'].includes('showTableHeader')"
:show-switch="showPropertySwitch('table-header-selector', 'showTableHeader')"
name="tableHeader"
@modelChange="val => onTableHeaderChange(val, 'showTableHeader')"
>

View File

@@ -84,7 +84,7 @@ const validMaxField = computed(() => {
return isValidField(state.miscForm.gaugeMaxField)
})
const isValidField = field => {
return field.id !== '-1' && quotaData.value.findIndex(ele => ele.id === field.id) !== -1
return field?.id !== '-1' && quotaData.value.findIndex(ele => ele.id === field?.id) !== -1
}
const state = reactive({
@@ -110,21 +110,66 @@ const init = () => {
}
const initField = () => {
state.quotaData = props.quotaFields.filter(ele => ele.id !== '-1')
// 数据集字段中,如果没有 y 轴字段,直接返回
const yAxisInDataset = props.quotaFields.find(ele => ele.id === props.chart.yAxis?.[0]?.id)
if (!yAxisInDataset) {
syncInvalidDynamicField()
return
}
// 过滤掉记录数字段
state.quotaData = props.quotaFields.filter(ele => ele.id !== '-1')
syncInvalidDynamicField()
}
const NUMBER_DE_TYPE = [2, 3]
const DYNAMIC_FIELD_FALLBACK = {
gaugeMin: 0,
gaugeMax: 100,
liquidMax: 100
}
const getDynamicField = () => {
return (
quotaData.value?.find(item => item.id === props.chart.yAxis?.[0]?.id) || quotaData.value?.[0]
)
}
const resetDynamicFieldConfig = (typeKey, fieldKey, valueKey) => {
const miscForm = state.miscForm as Record<string, any>
const currentField = miscForm[fieldKey] || {}
const changed = miscForm[typeKey] === 'dynamic' || !!currentField.id || !!currentField.summary
miscForm[typeKey] = 'fix'
miscForm[fieldKey] = { id: '', summary: '' }
if ([undefined, null, ''].includes(miscForm[valueKey])) {
miscForm[valueKey] = DYNAMIC_FIELD_FALLBACK[valueKey]
}
return changed
}
const sanitizeDynamicFieldConfig = (typeKey, fieldKey, valueKey) => {
const miscForm = state.miscForm as Record<string, any>
if (miscForm[typeKey] !== 'dynamic') {
return false
}
const currentField = miscForm[fieldKey] || {}
if (!isValidField(currentField)) {
return resetDynamicFieldConfig(typeKey, fieldKey, valueKey)
}
const quotaField = getQuotaField(currentField.id)
if (!quotaField?.id) {
return resetDynamicFieldConfig(typeKey, fieldKey, valueKey)
}
return false
}
const syncInvalidDynamicField = () => {
let changed = false
if (isGauge.value) {
changed = sanitizeDynamicFieldConfig('gaugeMinType', 'gaugeMinField', 'gaugeMin') || changed
changed = sanitizeDynamicFieldConfig('gaugeMaxType', 'gaugeMaxField', 'gaugeMax') || changed
}
if (isLiquid.value) {
changed = sanitizeDynamicFieldConfig('liquidMaxType', 'liquidMaxField', 'liquidMax') || changed
}
if (changed) {
changeMisc('', true)
}
}
const changeQuotaField = (type: string, resetSummary?: boolean) => {
if (isGauge.value) {
if (type === 'max') {