feat(视图): 透视表阈值支持选择维度 close #7523

This commit is contained in:
wisonic-s 2024-03-25 19:31:48 +08:00
parent a7a96452de
commit c6a7747d35
6 changed files with 261 additions and 49 deletions

View File

@ -1470,7 +1470,7 @@ export default {
line_type_dotted: 'Dotted',
value_can_not_empty: 'Value can not be empty',
value_error: 'Value illegal',
threshold: 'Threshold',
threshold: 'Conditional styles',
threshold_range: 'Range',
gauge_threshold_format_error: 'Format Error',
total_cfg: 'Total Config',
@ -1660,7 +1660,8 @@ export default {
regression_pow: 'Power law',
regression_loess: 'LOESS',
regression_algo: 'Algorithm',
trend_line: 'Trend Line'
trend_line: 'Trend Line',
field_enum: 'Enumeration values'
},
dataset: {
scope_edit: 'Effective only when editing',

View File

@ -1468,7 +1468,7 @@ export default {
line_type_dotted: '點',
value_can_not_empty: '值不能為空',
value_error: '值必須為數值',
threshold: '閾值',
threshold: '條件樣式',
threshold_range: '閾值區間',
gauge_threshold_format_error: '格式錯誤',
total_cfg: '總計配置',
@ -1652,7 +1652,8 @@ export default {
regression_pow: '冪函數',
regression_loess: '局部加權',
regression_algo: '算法',
trend_line: '趨勢線'
trend_line: '趨勢線',
field_enum: '枚舉值'
},
dataset: {
scope_edit: '僅編輯時生效',

View File

@ -1468,7 +1468,7 @@ export default {
line_type_dotted: '点',
value_can_not_empty: '值不能为空',
value_error: '值必须为数值',
threshold: '阈值',
threshold: '条件样式',
threshold_range: '阈值区间',
gauge_threshold_format_error: '格式错误',
total_cfg: '总计配置',
@ -1652,7 +1652,8 @@ export default {
regression_pow: '幂函数',
regression_loess: '局部加权',
regression_algo: '算法',
trend_line: '趋势线'
trend_line: '趋势线',
field_enum: '枚举值'
},
dataset: {
scope_edit: '仅编辑时生效',

View File

@ -766,12 +766,16 @@ function getConditions(chart) {
// table item color
let valueColor = DEFAULT_COLOR_CASE.tableFontColor
let valueBgColor = DEFAULT_COLOR_CASE.tableItemBgColor
let headerColor = DEFAULT_COLOR_CASE.tableHeaderFontColor
let headerBgColor = DEFAULT_COLOR_CASE.tableHeaderBgColor
if (chart.customAttr) {
const customAttr = JSON.parse(chart.customAttr)
// color
if (customAttr.color) {
const c = JSON.parse(JSON.stringify(customAttr.color))
valueColor = c.tableFontColor
headerColor = c.tableHeaderFontColor
headerBgColor = c.tableHeaderBgColor
const enableTableCrossBG = c.enableTableCrossBG
if (!enableTableCrossBG) {
valueBgColor = hexColorToRGBA(c.tableItemBgColor, c.alpha)
@ -781,21 +785,35 @@ function getConditions(chart) {
}
}
const dimensionAxis = [...JSON.parse(chart.xaxis), ...JSON.parse(chart.xaxisExt)]
const filedValueMap = getFieldValueMap(chart)
for (let i = 0; i < conditions.length; i++) {
const field = conditions[i]
let defaultTextColor = valueColor
let defaultBgColor = valueBgColor
if (chart.type === 'table-pivot') {
const index = dimensionAxis.findIndex(i => i.dataeaseName === field.field.dataeaseName)
defaultTextColor = index === -1 ? valueColor : headerColor
defaultBgColor = index === -1 ? valueBgColor : headerBgColor
}
res.text.push({
field: field.field.dataeaseName,
mapping(value, rowData) {
if (rowData?.isTotals) {
return null
}
return {
fill: mappingColor(value, valueColor, field, 'color', filedValueMap, rowData)
fill: mappingColor(value, defaultTextColor, field, 'color', filedValueMap, rowData)
}
}
})
res.background.push({
field: field.field.dataeaseName,
mapping(value, rowData) {
const fill = mappingColor(value, valueBgColor, field, 'backgroundColor', filedValueMap, rowData)
if (rowData?.isTotals) {
return null
}
const fill = mappingColor(value, defaultBgColor, field, 'backgroundColor', filedValueMap, rowData)
if (fill) {
return { fill }
}
@ -884,29 +902,63 @@ function mappingColor(value, defaultColor, field, type, filedValueMap, rowData)
let tv
if (t.field === '1') {
tv = getValue(t.targetField, filedValueMap, rowData)
} else if (t.field === '2') {
tv = t.enumValues
} else {
tv = t.value
}
if (t.term === 'eq') {
if (t.field === '2') {
const index = tv?.findIndex(v => v === value)
if (index !== -1) {
color = t[type]
flag = true
}
} else {
if (value === tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'not_eq') {
if (t.field === '2') {
const index = tv?.findIndex(v => v === value)
if (index === -1) {
color = t[type]
flag = true
}
} else {
if (value !== tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'like') {
if (t.field === '2') {
const index = tv?.findIndex(v => value.includes(v))
if (index !== -1) {
color = t[type]
flag = true
}
} else {
if (value.includes(tv)) {
color = t[type]
flag = true
}
}
} else if (t.term === 'not like') {
if (t.field === '2') {
const index = tv?.findIndex(v => value.includes(v))
if (index === -1) {
color = t[type]
flag = true
}
} else {
if (!value.includes(tv)) {
color = t[type]
flag = true
}
}
} else if (t.term === 'null') {
if (value === null || value === undefined || value === '') {
color = t[type]
@ -931,21 +983,42 @@ function mappingColor(value, defaultColor, field, type, filedValueMap, rowData)
if (fieldValue) {
tv = new Date(fieldValue.replace(/-/g, '/') + ' GMT+8').getTime()
}
} else if (t.field === '2') {
tv = []
t.enumValues?.forEach(v => {
tv.push(new Date(v.replace(/-/g, '/') + ' GMT+8').getTime())
})
} else {
tv = new Date(t.value.replace(/-/g, '/') + ' GMT+8').getTime()
}
const v = new Date(value.replace(/-/g, '/') + ' GMT+8').getTime()
if (t.term === 'eq') {
if (t.field === '2') {
const index = tv.findIndex(val => v === val)
if (index !== -1) {
color = t[type]
flag = true
}
} else {
if (v === tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'not_eq') {
if (t.field === '2') {
const index = tv.findIndex(val => v === val)
if (index === -1) {
color = t[type]
flag = true
}
} else {
if (v !== tv) {
color = t[type]
flag = true
}
}
} else if (t.term === 'lt') {
if (v < tv) {
color = t[type]

View File

@ -329,6 +329,10 @@
v-if="item.field === '1'"
:title="$t('chart.field_dynamic')"
>{{ $t('chart.field_dynamic') }}</span>
<span
v-if="item.field === '2'"
:title="$t('chart.field_enum')"
>{{ $t('chart.field_enum') }}</span>
</el-col>
<el-col
v-if="item.term.includes('null') || item.term.includes('empty')"
@ -369,6 +373,23 @@
<span v-else>&nbsp;</span>
</el-col>
<el-col
v-if="item.field === '2'"
:span="10"
>
<div
v-if="item.enumValues && item.enumValues.length"
style="display: flex; box-sizing: border-box; justify-content: start; align-items: center; overflow: hidden"
>
<span style="display: inline"> {{ item.enumValues.join(',') }}</span>
<el-tooltip
v-if="item.enumValues && item.enumValues.length"
:content="item.enumValues.join(',')"
>
<i class="el-icon-info"></i>
</el-tooltip>
</div>
</el-col>
<el-col :span="2">
<span

View File

@ -76,7 +76,7 @@
<el-select
v-model="item.term"
size="mini"
@change="changeThresholdField(item)"
@change="changeThresholdField(item, fieldItem)"
>
<el-option-group
v-for="(group,idx) in fieldItem.options"
@ -99,10 +99,10 @@
v-model="item.field"
size="mini"
style="margin-left: 10px;"
@change="changeThresholdField(item)"
@change="changeThresholdField(item, fieldItem)"
>
<el-option
v-for="opt in fieldTypeOptions"
v-for="opt in getFieldTypeOptions(fieldItem.field, item)"
:key="opt.value"
:label="opt.label"
:value="opt.value"
@ -328,7 +328,26 @@
</span>
</el-col>
<el-col
v-if="item.field === '2'"
:span="12"
>
<el-select
v-if="!item.term.includes('null') && !item.term.includes('empty') && item.term !== 'between'"
v-model="item.enumValues"
size="mini"
style="margin-left: 10px; width: 100%"
multiple
clearable
>
<el-option
v-for="value in fieldEnumValues[fieldItem.fieldId]"
:key="value"
:value="value"
:label="value"
/>
</el-select>
</el-col>
<el-col
:span="3"
style="display: flex;align-items: center;justify-content: center;"
@ -373,6 +392,7 @@
<script>
import { COLOR_PANEL } from '@/views/chart/chart/chart'
import { post } from '@/api/dataset/dataset'
export default {
name: 'TableThresholdEdit',
@ -410,7 +430,8 @@ export default {
max: '1',
targetField: {},
minField: {},
maxField: {}
maxField: {},
enumValues: []
},
summaryOptions: [{
id: 'value',
@ -530,9 +551,16 @@ export default {
],
fieldTypeOptions: [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_dynamic'), value: '1' }
{ label: this.$t('chart.field_dynamic'), value: '1' },
{ label: this.$t('chart.field_enum'), value: '2' }
],
predefineColors: COLOR_PANEL
predefineColors: COLOR_PANEL,
fieldEnumValues: {}
}
},
computed: {
panelInfo() {
return this.$store.state.panel.panelInfo
}
},
mounted() {
@ -595,11 +623,23 @@ export default {
this.fields = JSON.parse(this.chart.xaxis)
}
} else if (this.chart.type === 'table-pivot') {
const totalFields = []
if (Object.prototype.toString.call(this.chart.yaxis) === '[object Array]') {
this.fields = JSON.parse(JSON.stringify(this.chart.yaxis))
totalFields.splice(totalFields.length, 0, ...JSON.parse(JSON.stringify(this.chart.yaxis)))
} else {
this.fields = JSON.parse(this.chart.yaxis)
totalFields.splice(totalFields.length, 0, ...JSON.parse(this.chart.yaxis))
}
if (Object.prototype.toString.call(this.chart.xaxis) === '[object Array]') {
totalFields.splice(totalFields.length, 0, ...JSON.parse(JSON.stringify(this.chart.xaxis)))
} else {
totalFields.splice(totalFields.length, 0, ...JSON.parse(this.chart.xaxis))
}
if (Object.prototype.toString.call(this.chart.xaxisExt) === '[object Array]') {
totalFields.splice(totalFields.length, 0, ...JSON.parse(JSON.stringify(this.chart.xaxisExt)))
} else {
totalFields.splice(totalFields.length, 0, ...JSON.parse(this.chart.xaxisExt))
}
this.fields.splice(0, this.fields.length, ...totalFields)
} else {
if (Object.prototype.toString.call(this.chart.xaxis) === '[object Array]') {
this.fields = this.fields.concat(JSON.parse(JSON.stringify(this.chart.xaxis)))
@ -654,8 +694,14 @@ export default {
changeThreshold() {
this.$emit('onTableThresholdChange', this.thresholdArr)
},
changeThresholdField(item) {
if (item.field === '1') {
changeThresholdField(item, curField) {
switch (item.field) {
case '0':
item.targetField = {}
item.minField = {}
item.maxField = {}
break
case '1':
if (item.term === 'between') {
item.minField.curField = this.getQuotaField(item.minField.fieldId)
item.maxField.curField = this.getQuotaField(item.maxField.fieldId)
@ -665,13 +711,33 @@ export default {
item.minField = {}
item.maxField = {}
}
} else {
item.targetField = {}
item.minField = {}
item.maxField = {}
break
case '2':
if (!curField?.fieldId) {
break
}
//
if (curField.field.deType === 1 && !['eq', 'not_eq'].includes(item.term)) {
item.field = '0'
}
this.getFieldEnumValues(curField.field)
break
default:
break
}
this.changeThreshold()
},
getFieldEnumValues(field) {
if (this.fieldEnumValues[field.id]) {
return
}
const fieldType = this.getFieldType(field.id)
if (fieldType) {
post('/chart/view/getFieldData/' + this.chart.id + '/' + this.panelInfo.id + '/' + field.id + '/' + fieldType, {}).then(response => {
this.$set(this.fieldEnumValues, field.id, response.data)
})
}
},
getQuotaField(id) {
if (!id) {
return {}
@ -703,11 +769,60 @@ export default {
}
})
}
// term
item.conditions && item.conditions.forEach(ele => {
// term field
item.conditions?.forEach(ele => {
ele.term = ''
if (item.field.groupType === 'q' && ele.field === '2') {
ele.field = '0'
}
if (item.field.groupType === 'd') {
if (this.chart.type === 'table-pivot' && ele.field === '1') {
ele.field = '0'
}
if (ele.field === '2') {
ele.enumValues?.splice(0)
this.getFieldEnumValues(item.field)
}
}
})
this.changeThreshold()
},
getFieldType(fieldId) {
let index = -1
index = JSON.parse(this.chart.xaxis).findIndex(i => i.id === fieldId)
if (index !== -1) {
return 'xaxis'
}
index = JSON.parse(this.chart.xaxisExt).findIndex(i => i.id === fieldId)
if (index !== -1) {
return 'xaxisExt'
}
},
getFieldTypeOptions(field, condition) {
if (field.groupType === 'q') {
return [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_dynamic'), value: '1' }
]
}
if (field.deType === 1 && !['eq', 'not_eq'].includes(condition.term)) {
if (this.chart.type === 'table-pivot') {
return [
{ label: this.$t('chart.field_fixed'), value: '0' }
]
}
return [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_dynamic'), value: '1' }
]
}
if (this.chart.type === 'table-pivot') {
return [
{ label: this.$t('chart.field_fixed'), value: '0' },
{ label: this.$t('chart.field_enum'), value: '2' }
]
}
return this.fieldTypeOptions
}
}
}