Merge pull request #5327 from dataease/pr@dev@feat_chart_empty_data_filter

feat(视图-地图,汇总表): ECharts 地图,AntV 汇总表支持空值过滤
This commit is contained in:
wisonic-s 2023-05-25 19:00:19 +08:00 committed by GitHub
commit fba6b51f11
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 118 additions and 16 deletions

View File

@ -1489,6 +1489,7 @@ export default {
total_sort_desc: 'DESC', total_sort_desc: 'DESC',
total_sort_field: 'Sort Field', total_sort_field: 'Sort Field',
empty_data_strategy: 'Empty Data Strategy', empty_data_strategy: 'Empty Data Strategy',
empty_data_field_ctrl: 'Field Control',
break_line: 'Keep', break_line: 'Keep',
set_zero: 'Set Zero', set_zero: 'Set Zero',
ignore_data: 'Hide Data', ignore_data: 'Hide Data',

View File

@ -1491,6 +1491,7 @@ export default {
break_line: '保持為空', break_line: '保持為空',
set_zero: '置為0', set_zero: '置為0',
ignore_data: '隱藏空值', ignore_data: '隱藏空值',
empty_data_field_ctrl: '字段設置',
sub_dimension_tip: '該字段為必填項,且不應使用類別軸中的字段,若無需該字段,請選擇基礎圖表進行展示,否則展示效果不理想', sub_dimension_tip: '該字段為必填項,且不應使用類別軸中的字段,若無需該字段,請選擇基礎圖表進行展示,否則展示效果不理想',
drill_dimension_tip: '鑽取字段僅支持數據集中的字段', drill_dimension_tip: '鑽取字段僅支持數據集中的字段',
table_scroll_tip: '明細表僅在分頁模式為"下拉"時生效。', table_scroll_tip: '明細表僅在分頁模式為"下拉"時生效。',

View File

@ -1487,6 +1487,7 @@ export default {
total_sort_desc: '降序', total_sort_desc: '降序',
total_sort_field: '排序字段', total_sort_field: '排序字段',
empty_data_strategy: '空值处理', empty_data_strategy: '空值处理',
empty_data_field_ctrl: '字段设置',
break_line: '保持为空', break_line: '保持为空',
set_zero: '置为0', set_zero: '置为0',
ignore_data: '隐藏空值', ignore_data: '隐藏空值',

View File

@ -467,7 +467,8 @@ export const DEFAULT_FUNCTION_CFG = {
sliderBg: '#FFFFFF', sliderBg: '#FFFFFF',
sliderFillBg: '#BCD6F1', sliderFillBg: '#BCD6F1',
sliderTextClolor: '#999999', sliderTextClolor: '#999999',
emptyDataStrategy: 'breakLine' emptyDataStrategy: 'breakLine',
emptyDataFieldCtrl: []
} }
export const DEFAULT_THRESHOLD = { export const DEFAULT_THRESHOLD = {
gaugeThreshold: '', gaugeThreshold: '',

View File

@ -38,7 +38,7 @@ const fillGradientColor = (data, colors) => {
}) })
return data return data
} }
export function baseMapOption(chart_option, chart, themeStyle, curAreaCode, seriesId) { export function baseMapOption(chart_option, geoJson, chart, themeStyle, curAreaCode, seriesId) {
// 处理shape attr // 处理shape attr
let customAttr = {} let customAttr = {}
let isGradient = false let isGradient = false
@ -151,18 +151,16 @@ export function baseMapOption(chart_option, chart, themeStyle, curAreaCode, seri
if (senior) { if (senior) {
senior = JSON.parse(senior) senior = JSON.parse(senior)
} }
// 空值处理echarts 对于值为 null 的默认策略是不展示,也就是保持为空,所以只需要处理忽略数据和置为 0 就行 // 空值处理echarts 对于值为 null 的默认策略是不展示,也就是保持为空,所以只需要处理置为 0 就行
// 隐藏和不展示的区别是隐藏不会参与颜色分布的计算,而不展示会参与颜色计算
let emptyDataStrategy = senior?.functionCfg?.emptyDataStrategy let emptyDataStrategy = senior?.functionCfg?.emptyDataStrategy
if (!emptyDataStrategy) { if (!emptyDataStrategy) {
emptyDataStrategy = 'breakLine' emptyDataStrategy = 'breakLine'
} }
const subArea = new Set(geoJson.features.map(item => item.properties.name))
for (let i = 0; i < valueArr.length; i++) { for (let i = 0; i < valueArr.length; i++) {
const y = valueArr[i] const y = valueArr[i]
if (y.value === null && emptyDataStrategy === 'ignoreData') {
continue
}
y.name = chart.data.x[i] y.name = chart.data.x[i]
subArea.delete(y.name)
if (y.value === null && emptyDataStrategy === 'setZero') { if (y.value === null && emptyDataStrategy === 'setZero') {
const tmp = _.clone(y) const tmp = _.clone(y)
tmp.value = 0 tmp.value = 0
@ -171,6 +169,14 @@ export function baseMapOption(chart_option, chart, themeStyle, curAreaCode, seri
} }
chart_option.series[0].data.push(y) chart_option.series[0].data.push(y)
} }
if (emptyDataStrategy === 'setZero' && subArea.size > 0) {
subArea.forEach(item => {
chart_option.series[0].data.push({
name: item,
value: 0
})
})
}
if (isGradient) { if (isGradient) {
chart_option.series[0].data = fillGradientColor(chart_option.series[0].data, customAttr.color.colors) chart_option.series[0].data = fillGradientColor(chart_option.series[0].data, customAttr.color.colors)

View File

@ -2,7 +2,7 @@ import { TableSheet, S2Event, PivotSheet, DataCell, EXTRA_FIELD, TOTAL_VALUE } f
import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table' import { getCustomTheme, getSize } from '@/views/chart/chart/common/common_table'
import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart' import { DEFAULT_COLOR_CASE, DEFAULT_TOTAL } from '@/views/chart/chart/chart'
import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter' import { formatterItem, valueFormatter } from '@/views/chart/chart/formatter'
import { hexColorToRGBA } from '@/views/chart/chart/util' import { handleTableEmptyStrategy, hexColorToRGBA } from '@/views/chart/chart/util'
export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) { export function baseTableInfo(s2, container, chart, action, tableData, pageInfo) {
const containerDom = document.getElementById(container) const containerDom = document.getElementById(container)
@ -300,13 +300,15 @@ export function baseTableNormal(s2, container, chart, action, tableData) {
}) })
} }
// 空值处理
const newData = handleTableEmptyStrategy(tableData, chart)
// data config // data config
const s2DataConfig = { const s2DataConfig = {
fields: { fields: {
columns: columns columns: columns
}, },
meta: meta, meta: meta,
data: tableData data: newData
} }
const customAttr = JSON.parse(chart.customAttr) const customAttr = JSON.parse(chart.customAttr)

View File

@ -3690,3 +3690,38 @@ export function resetRgbOpacity(sourceColor, times) {
} }
return sourceColor return sourceColor
} }
export function handleTableEmptyStrategy(tableData, chart) {
let newData = tableData
let intersection = []
let senior = chart.senior
if (senior) {
senior = JSON.parse(senior)
}
let emptyDataStrategy = senior?.functionCfg?.emptyDataStrategy
if (!emptyDataStrategy) {
emptyDataStrategy = 'breakLine'
}
const emptyDataFieldCtrl = senior?.functionCfg?.emptyDataFieldCtrl
if (emptyDataStrategy !== 'breakLine' && emptyDataFieldCtrl?.length && tableData?.length) {
const deNames = _.keys(tableData[0])
intersection = _.intersection(deNames, emptyDataFieldCtrl)
}
if (intersection.length) {
newData = _.clone(tableData)
for (let i = 0; i < newData.length; i++) {
for (let j = 0, tmp = intersection.length; j < tmp; j++) {
const deName = intersection[j]
if (newData[i][deName] === null) {
if (emptyDataStrategy === 'setZero') {
newData[i][deName] = 0
}
if (emptyDataStrategy === 'ignoreData') {
newData = _.filter(newData, (_, index) => index !== i)
}
}
}
}
}
return newData
}

View File

@ -439,7 +439,7 @@ export default {
this.buttonTextColor = null this.buttonTextColor = null
} }
} }
const chart_option = baseMapOption(base_json, chart, this.buttonTextColor, curAreaCode, this.currentSeriesId) const chart_option = baseMapOption(base_json, geoJson, chart, this.buttonTextColor, curAreaCode, this.currentSeriesId)
this.myEcharts(chart_option) this.myEcharts(chart_option)
const opt = this.myChart.getOption() const opt = this.myChart.getOption()
if (opt && opt.series) { if (opt && opt.series) {

View File

@ -80,9 +80,32 @@
> >
<el-radio :label="'breakLine'">{{ $t('chart.break_line') }}</el-radio> <el-radio :label="'breakLine'">{{ $t('chart.break_line') }}</el-radio>
<el-radio :label="'setZero'">{{ $t('chart.set_zero') }}</el-radio> <el-radio :label="'setZero'">{{ $t('chart.set_zero') }}</el-radio>
<el-radio :label="'ignoreData'">{{ $t('chart.ignore_data') }}</el-radio> <el-radio
v-show="showIgnoreOption"
:label="'ignoreData'"
>
{{ $t('chart.ignore_data') }}
</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item
v-show="showEmptyDataFieldCtrl"
:label="$t('chart.empty_data_field_ctrl')"
class="form-item"
>
<el-select
v-model="functionForm.emptyDataFieldCtrl"
multiple
@change="changeFunctionCfg"
>
<el-option
v-for="option in fieldOptions"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
</el-form-item>
</el-form> </el-form>
</el-col> </el-col>
</div> </div>
@ -103,7 +126,8 @@ export default {
data() { data() {
return { return {
functionForm: JSON.parse(JSON.stringify(DEFAULT_FUNCTION_CFG)), functionForm: JSON.parse(JSON.stringify(DEFAULT_FUNCTION_CFG)),
predefineColors: COLOR_PANEL predefineColors: COLOR_PANEL,
fieldOptions: []
} }
}, },
computed: { computed: {
@ -111,8 +135,18 @@ export default {
return this.chart.type !== 'bidirectional-bar' && !equalsAny(this.chart.type, 'map') return this.chart.type !== 'bidirectional-bar' && !equalsAny(this.chart.type, 'map')
}, },
showEmptyStrategy() { showEmptyStrategy() {
return (this.chart.render === 'antv' && includesAny(this.chart.type, 'line', 'bar', 'area')) || return (this.chart.render === 'antv' &&
this.chart.render === 'echarts' && equalsAny(this.chart.type, 'map') (includesAny(this.chart.type, 'line', 'bar', 'area') ||
equalsAny(this.chart.type, 'table-normal'))) ||
(this.chart.render === 'echarts' && equalsAny(this.chart.type, 'map'))
},
showIgnoreOption() {
return !equalsAny(this.chart.type, 'map')
},
showEmptyDataFieldCtrl() {
return this.showEmptyStrategy &&
this.functionForm.emptyDataStrategy !== 'breakLine' &&
equalsAny(this.chart.type, 'table-normal')
} }
}, },
watch: { watch: {
@ -140,6 +174,26 @@ export default {
} else { } else {
this.functionForm = JSON.parse(JSON.stringify(DEFAULT_FUNCTION_CFG)) this.functionForm = JSON.parse(JSON.stringify(DEFAULT_FUNCTION_CFG))
} }
this.initFieldCtrl()
}
},
initFieldCtrl() {
if (this.showEmptyDataFieldCtrl) {
this.fieldOptions = []
let yAxis = []
if (Object.prototype.toString.call(this.chart.xaxis) === '[object Array]') {
yAxis = this.chart.yaxis
} else {
yAxis = JSON.parse(this.chart.yaxis)
}
if (this.chart.type === 'table-normal') {
yAxis.forEach(item => {
this.fieldOptions.push({
label: item.name,
value: item.dataeaseName
})
})
}
} }
}, },
changeFunctionCfg() { changeFunctionCfg() {

View File

@ -1955,11 +1955,12 @@ export default {
equalsAny(this.view.type, 'text', 'label', 'map', 'buddle-map') equalsAny(this.view.type, 'text', 'label', 'map', 'buddle-map')
}, },
showSeniorCfg() { showSeniorCfg() {
return includesAny(this.view.type, 'bar', 'line', 'area', 'mix') || return includesAny(this.view.type, 'bar', 'line', 'area', 'mix', 'table') ||
equalsAny(this.view.type, 'table-normal', 'table-info', 'map') equalsAny(this.view.type, 'table-normal', 'table-info', 'map')
}, },
showFunctionCfg() { showFunctionCfg() {
return includesAny(this.view.type, 'bar', 'line', 'area', 'mix', 'map') return includesAny(this.view.type, 'bar', 'line', 'area', 'mix', 'table') ||
equalsAny(this.view.type, 'map')
}, },
showScrollCfg() { showScrollCfg() {
return equalsAny(this.view.type, 'table-normal', 'table-info') return equalsAny(this.view.type, 'table-normal', 'table-info')