Merge pull request #13466 from dataease/pr@dev-v2@chart-line-add-condition-style
feat(图表): 折线图支持条件样式
This commit is contained in:
commit
3563dcf625
@ -147,6 +147,10 @@ declare interface ChartThreshold {
|
||||
* 文本卡阈值
|
||||
*/
|
||||
textLabelThreshold: Threshold[]
|
||||
/**
|
||||
* 折线阈值
|
||||
*/
|
||||
lineThreshold: TableThreshold[]
|
||||
}
|
||||
declare interface TableThreshold {
|
||||
/**
|
||||
|
||||
@ -7,6 +7,7 @@ import { DEFAULT_THRESHOLD } from '@/views/chart/components/editor/util/chart'
|
||||
import TableThresholdEdit from '@/views/chart/components/editor/editor-senior/components/dialog/TableThresholdEdit.vue'
|
||||
import TextLabelThresholdEdit from '@/views/chart/components/editor/editor-senior/components/dialog/TextLabelThresholdEdit.vue'
|
||||
import TextThresholdEdit from '@/views/chart/components/editor/editor-senior/components/dialog/TextThresholdEdit.vue'
|
||||
import LineThresholdEdit from '@/views/chart/components/editor/editor-senior/components/dialog/LineThresholdEdit.vue'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
import { defaultsDeep } from 'lodash-es'
|
||||
import { iconFieldMap } from '@/components/icon-group/field-list'
|
||||
@ -50,7 +51,9 @@ const state = reactive({
|
||||
editLabelThresholdDialog: false,
|
||||
thresholdArr: [],
|
||||
editTableThresholdDialog: false,
|
||||
tableThresholdArr: []
|
||||
tableThresholdArr: [],
|
||||
editLineThresholdDialog: false,
|
||||
lineThresholdArr: []
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
@ -63,6 +66,7 @@ const init = () => {
|
||||
state.textThresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.textLabelThreshold))
|
||||
state.thresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.labelThreshold))
|
||||
state.tableThresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.tableThreshold))
|
||||
state.lineThresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.lineThreshold ?? []))
|
||||
}
|
||||
}
|
||||
const changeThreshold = () => {
|
||||
@ -257,6 +261,77 @@ const changeTableThreshold = () => {
|
||||
changeThreshold()
|
||||
closeTableThreshold()
|
||||
}
|
||||
|
||||
const lineThresholdChange = val => {
|
||||
state.lineThresholdArr = val
|
||||
}
|
||||
const editLineThreshold = () => {
|
||||
state.editLineThresholdDialog = true
|
||||
}
|
||||
const closeLineThreshold = () => {
|
||||
state.editLineThresholdDialog = false
|
||||
}
|
||||
const changeLineThreshold = () => {
|
||||
// check line config
|
||||
for (let i = 0; i < state.lineThresholdArr?.length; i++) {
|
||||
const field = state.lineThresholdArr[i]
|
||||
if (!field.fieldId) {
|
||||
ElMessage.error(t('chart.field_can_not_empty'))
|
||||
return
|
||||
}
|
||||
if (!field.conditions || field.conditions.length === 0) {
|
||||
ElMessage.error(t('chart.conditions_can_not_empty'))
|
||||
return
|
||||
}
|
||||
for (let j = 0; j < field.conditions.length; j++) {
|
||||
const ele = field.conditions[j]
|
||||
if (!ele.term || ele.term === '') {
|
||||
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
|
||||
}
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state.thresholdForm.lineThreshold = JSON.parse(JSON.stringify(state.lineThresholdArr ?? []))
|
||||
changeThreshold()
|
||||
closeLineThreshold()
|
||||
}
|
||||
|
||||
const getFieldName = field => (field.chartShowName ? field.chartShowName : field.name)
|
||||
|
||||
const getDynamicStyleLabel = (item, fieldObj) => {
|
||||
@ -713,6 +788,129 @@ init()
|
||||
</div>
|
||||
</el-col>
|
||||
</el-col>
|
||||
<!--折线-->
|
||||
<el-col v-show="showProperty('lineThreshold')">
|
||||
<el-col>
|
||||
<div class="inner-container">
|
||||
<span class="label" :class="'label-' + props.themes">条件样式设置</span>
|
||||
<span class="right-btns">
|
||||
<span
|
||||
class="set-text-info"
|
||||
:class="{ 'set-text-info-dark': themes === 'dark' }"
|
||||
v-if="state.thresholdForm?.tableThreshold?.length > 0"
|
||||
>
|
||||
已设置
|
||||
</span>
|
||||
<el-button
|
||||
:title="t('chart.edit')"
|
||||
:class="'label-' + props.themes"
|
||||
:style="{ width: '24px', marginLeft: '6px' }"
|
||||
:disabled="!state.thresholdForm.enable"
|
||||
class="circle-button"
|
||||
text
|
||||
size="small"
|
||||
@click="editLineThreshold"
|
||||
>
|
||||
<template #icon>
|
||||
<el-icon size="14px">
|
||||
<Icon name="icon_edit_outlined"><icon_edit_outlined class="svg-icon" /></Icon>
|
||||
</el-icon>
|
||||
</template>
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="threshold-container"
|
||||
:class="{ 'threshold-container-dark': themes === 'dark' }"
|
||||
v-if="state.thresholdForm.lineThreshold?.length > 0"
|
||||
>
|
||||
<el-row
|
||||
v-for="(fieldItem, fieldIndex) in state.thresholdForm.lineThreshold"
|
||||
:key="fieldIndex"
|
||||
style="flex-direction: column"
|
||||
>
|
||||
<div class="field-style" :class="{ 'field-style-dark': themes === 'dark' }">
|
||||
<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>
|
||||
</div>
|
||||
<div v-for="(item, index) in fieldItem.conditions" :key="index" class="line-style">
|
||||
<div style="flex: 1">
|
||||
<span v-if="item.term === 'lt'" :title="t('chart.filter_lt')">
|
||||
{{ t('chart.filter_lt') }}
|
||||
</span>
|
||||
<span v-else-if="item.term === 'gt'" :title="t('chart.filter_gt')">
|
||||
{{ t('chart.filter_gt') }}
|
||||
</span>
|
||||
<span v-else-if="item.term === 'le'" :title="t('chart.filter_le')">
|
||||
{{ t('chart.filter_le') }}
|
||||
</span>
|
||||
<span v-else-if="item.term === 'ge'" :title="t('chart.filter_ge')">
|
||||
{{ t('chart.filter_ge') }}
|
||||
</span>
|
||||
<span v-else-if="item.term === 'between'" :title="t('chart.filter_between')">
|
||||
{{ t('chart.filter_between') }}
|
||||
</span>
|
||||
<span v-else-if="item.term === 'default'" title="默认"> 默认 </span>
|
||||
</div>
|
||||
<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') &&
|
||||
!item.term.includes('default') &&
|
||||
!item.term.includes('empty') &&
|
||||
item.term !== 'between'
|
||||
"
|
||||
:title="item.value + ''"
|
||||
>{{ item.value }}</span
|
||||
>
|
||||
<span
|
||||
v-else-if="
|
||||
!item.term.includes('null') &&
|
||||
!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>
|
||||
<template v-if="chart.type !== 'picture-group'">
|
||||
<div
|
||||
:title="t('chart.color')"
|
||||
:style="{
|
||||
backgroundColor: item.color
|
||||
}"
|
||||
class="color-div"
|
||||
:class="{ 'color-div-dark': themes === 'dark' }"
|
||||
></div>
|
||||
</template>
|
||||
</div>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-col>
|
||||
|
||||
<!--编辑文本卡阈值-->
|
||||
<el-dialog
|
||||
@ -794,6 +992,30 @@ init()
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!--编辑折线阈值-->
|
||||
<el-dialog
|
||||
v-if="state.editLineThresholdDialog"
|
||||
v-model="state.editLineThresholdDialog"
|
||||
:title="t('chart.threshold')"
|
||||
:visible="state.editLineThresholdDialog"
|
||||
width="1050px"
|
||||
class="dialog-css"
|
||||
append-to-body
|
||||
>
|
||||
<line-threshold-edit
|
||||
:threshold="state.thresholdForm.lineThreshold"
|
||||
:chart="chart"
|
||||
@onLineThresholdChange="lineThresholdChange"
|
||||
/>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="closeLineThreshold">{{ t('chart.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="changeLineThreshold">{{
|
||||
t('chart.confirm')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@ -0,0 +1,499 @@
|
||||
<script lang="tsx" setup>
|
||||
import icon_info_filled from '@/assets/svg/icon_info_filled.svg'
|
||||
import icon_deleteTrash_outlined from '@/assets/svg/icon_delete-trash_outlined.svg'
|
||||
import icon_add_outlined from '@/assets/svg/icon_add_outlined.svg'
|
||||
import { PropType, reactive } from 'vue'
|
||||
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'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const props = defineProps({
|
||||
chart: {
|
||||
type: Object as PropType<ChartObj>,
|
||||
required: true
|
||||
},
|
||||
threshold: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['onLineThresholdChange'])
|
||||
|
||||
const thresholdCondition = {
|
||||
term: 'lt',
|
||||
field: '0',
|
||||
value: '0',
|
||||
color: '#ff0000ff',
|
||||
backgroundColor: '#ffffff00',
|
||||
min: '0',
|
||||
max: '1',
|
||||
type: 'fixed'
|
||||
}
|
||||
const valueOptions = [
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'lt',
|
||||
label: t('chart.filter_lt')
|
||||
},
|
||||
{
|
||||
value: 'gt',
|
||||
label: t('chart.filter_gt')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'between',
|
||||
label: t('chart.filter_between')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
const predefineColors = COLOR_PANEL
|
||||
|
||||
const state = reactive({
|
||||
thresholdArr: [] as LineThreshold[],
|
||||
fields: [],
|
||||
thresholdObj: {
|
||||
fieldId: '',
|
||||
field: {},
|
||||
conditions: []
|
||||
} as LineThreshold
|
||||
})
|
||||
|
||||
const init = () => {
|
||||
state.thresholdArr = JSON.parse(JSON.stringify(props.threshold)) as LineThreshold[]
|
||||
initFields()
|
||||
}
|
||||
const initOptions = (item, fieldObj) => {
|
||||
if (fieldObj) {
|
||||
item.options = JSON.parse(JSON.stringify(valueOptions))
|
||||
item.conditions &&
|
||||
item.conditions.forEach(ele => {
|
||||
ele.term = ''
|
||||
})
|
||||
}
|
||||
}
|
||||
const initFields = () => {
|
||||
let fields = []
|
||||
const yAxis = JSON.parse(JSON.stringify(props.chart.yAxis))
|
||||
fields = [...yAxis]
|
||||
state.fields.splice(0, state.fields.length, ...fields)
|
||||
// 字段不存在时
|
||||
let change = false
|
||||
state.thresholdArr.forEach(item => {
|
||||
const fieldItemObj = state.fields.filter(ele => ele.id === item.fieldId)
|
||||
if (fieldItemObj.length === 0) {
|
||||
change = true
|
||||
item.fieldId = null
|
||||
}
|
||||
})
|
||||
if (change) {
|
||||
changeThreshold()
|
||||
}
|
||||
}
|
||||
const addThreshold = () => {
|
||||
state.thresholdArr.push(JSON.parse(JSON.stringify(state.thresholdObj)))
|
||||
changeThreshold()
|
||||
}
|
||||
const removeThreshold = index => {
|
||||
state.thresholdArr.splice(index, 1)
|
||||
changeThreshold()
|
||||
}
|
||||
|
||||
const changeThreshold = () => {
|
||||
emit('onLineThresholdChange', state.thresholdArr)
|
||||
}
|
||||
|
||||
const addConditions = item => {
|
||||
const newCondition = JSON.parse(JSON.stringify(thresholdCondition))
|
||||
item.conditions.push(newCondition)
|
||||
changeThreshold()
|
||||
}
|
||||
const removeCondition = (item, index) => {
|
||||
item.conditions.splice(index, 1)
|
||||
changeThreshold()
|
||||
}
|
||||
|
||||
const addField = item => {
|
||||
// get field
|
||||
if (state.fields && state.fields.length > 0) {
|
||||
state.fields.forEach(ele => {
|
||||
if (item.fieldId === ele.id) {
|
||||
item.field = JSON.parse(JSON.stringify(ele))
|
||||
initOptions(item, item.field)
|
||||
}
|
||||
})
|
||||
}
|
||||
changeThreshold()
|
||||
}
|
||||
|
||||
const fieldOptions = [{ label: t('chart.field_fixed'), value: 'fixed' }]
|
||||
|
||||
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 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>
|
||||
|
||||
<template>
|
||||
<el-col>
|
||||
<div class="tip">
|
||||
<Icon name="icon_info_filled" class="icon-style"
|
||||
><icon_info_filled class="svg-icon icon-style"
|
||||
/></Icon>
|
||||
<span style="padding-left: 10px">{{ t('chart.table_threshold_tip') }}</span>
|
||||
</div>
|
||||
|
||||
<div @keydown.stop @keyup.stop style="max-height: 50vh; overflow-y: auto">
|
||||
<div
|
||||
v-for="(fieldItem, fieldIndex) in state.thresholdArr"
|
||||
:key="fieldIndex"
|
||||
class="field-item"
|
||||
>
|
||||
<el-row style="margin-top: 6px; align-items: center; justify-content: space-between">
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="fieldItem.fieldId" @change="addField(fieldItem)">
|
||||
<el-option
|
||||
class="series-select-option"
|
||||
v-for="fieldOption in state.fields"
|
||||
:key="fieldOption.id"
|
||||
:label="fieldOption.name"
|
||||
:value="fieldOption.id"
|
||||
:disabled="chart.type === 'table-info' && fieldOption.deType === 7"
|
||||
>
|
||||
<el-icon style="margin-right: 8px">
|
||||
<Icon
|
||||
><component
|
||||
:class="`field-icon-${
|
||||
fieldType[[2, 3].includes(fieldOption.deType) ? 2 : 0]
|
||||
}`"
|
||||
class="svg-icon"
|
||||
:is="iconFieldMap[fieldType[fieldOption.deType]]"
|
||||
></component
|
||||
></Icon>
|
||||
</el-icon>
|
||||
{{ fieldOption.name }}
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-button
|
||||
class="circle-button m-icon-btn"
|
||||
text
|
||||
:style="{ float: 'right' }"
|
||||
@click="removeThreshold(fieldIndex)"
|
||||
>
|
||||
<el-icon size="20px" style="color: #646a73">
|
||||
<Icon name="icon_delete-trash_outlined"
|
||||
><icon_deleteTrash_outlined class="svg-icon"
|
||||
/></Icon>
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</el-row>
|
||||
|
||||
<el-row :style="{ marginTop: '16px', borderTop: '1px solid #d5d6d8' }">
|
||||
<el-row
|
||||
v-for="(item, index) in fieldItem.conditions"
|
||||
:key="index"
|
||||
class="line-item"
|
||||
:gutter="12"
|
||||
>
|
||||
<el-col :span="4">
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.term" @change="changeThreshold">
|
||||
<el-option-group
|
||||
v-for="(group, idx) in fieldItem.options"
|
||||
:key="idx"
|
||||
:label="group.label"
|
||||
>
|
||||
<el-option
|
||||
v-for="opt in group.options"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="4" v-if="isNotEmptyAndNull(item)" style="padding-left: 0 !important">
|
||||
<el-form-item class="form-item">
|
||||
<el-select v-model="item.type" class="select-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="isNotEmptyAndNull(item) && !isBetween(item) && !isDynamic(item)"
|
||||
:span="12"
|
||||
style="text-align: center"
|
||||
>
|
||||
<el-form-item class="form-item">
|
||||
<el-input-number
|
||||
v-model="item.value"
|
||||
v-if="[2, 3].includes(fieldItem.field.deType)"
|
||||
:placeholder="t('chart.drag_block_label_value')"
|
||||
controls-position="right"
|
||||
class="value-item"
|
||||
clearable
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
<el-input
|
||||
v-model="item.value"
|
||||
v-else
|
||||
:placeholder="t('chart.drag_block_label_value')"
|
||||
controls-position="right"
|
||||
clearable
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!--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"
|
||||
controls-position="right"
|
||||
class="between-item"
|
||||
:placeholder="t('chart.axis_value_min')"
|
||||
clearable
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<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>
|
||||
<!--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"
|
||||
controls-position="right"
|
||||
class="between-item"
|
||||
:placeholder="t('chart.axis_value_max')"
|
||||
clearable
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
</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"
|
||||
v-model="item.color"
|
||||
show-alpha
|
||||
class="color-picker-style"
|
||||
:predefine="predefineColors"
|
||||
@change="changeThreshold"
|
||||
/>
|
||||
</el-form-item>
|
||||
</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>
|
||||
|
||||
<el-button
|
||||
style="margin-top: 10px"
|
||||
class="circle-button"
|
||||
type="primary"
|
||||
text
|
||||
@click="addConditions(fieldItem)"
|
||||
>
|
||||
<template #icon>
|
||||
<Icon name="icon_add_outlined"><icon_add_outlined class="svg-icon" /></Icon>
|
||||
</template>
|
||||
{{ t('chart.add_style') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-button
|
||||
class="circle-button"
|
||||
text
|
||||
type="primary"
|
||||
style="margin-top: 10px"
|
||||
@click="addThreshold"
|
||||
>
|
||||
<template #icon>
|
||||
<Icon name="icon_add_outlined"><icon_add_outlined class="svg-icon" /></Icon>
|
||||
</template>
|
||||
{{ t('chart.add_condition') }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.field-item {
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
padding: 10px 16px;
|
||||
margin-top: 10px;
|
||||
background: #f5f6f7;
|
||||
}
|
||||
|
||||
.line-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
height: 28px !important;
|
||||
:deep(.el-form-item__label) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.value-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.between-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.select-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.el-select-dropdown__item {
|
||||
padding: 0 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.color-picker-style {
|
||||
cursor: pointer;
|
||||
z-index: 1003;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.color-picker-style :deep(.el-color-picker__trigger) {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.color-title {
|
||||
color: #646a73;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 22px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 12px;
|
||||
background: #d6e2ff;
|
||||
border-radius: 4px;
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.ed-form-item) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.icon-style {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
color: var(--ed-color-primary);
|
||||
}
|
||||
|
||||
.m-icon-btn {
|
||||
&:hover {
|
||||
background: rgba(31, 35, 41, 0.1) !important;
|
||||
}
|
||||
&:focus {
|
||||
background: rgba(31, 35, 41, 0.1) !important;
|
||||
}
|
||||
&:active {
|
||||
background: rgba(31, 35, 41, 0.2) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.series-select-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding: 0 11px;
|
||||
}
|
||||
</style>
|
||||
@ -761,7 +761,8 @@ export const DEFAULT_THRESHOLD: ChartThreshold = {
|
||||
liquidThreshold: '',
|
||||
labelThreshold: [],
|
||||
tableThreshold: [],
|
||||
textLabelThreshold: []
|
||||
textLabelThreshold: [],
|
||||
lineLabelThreshold: []
|
||||
}
|
||||
export const DEFAULT_SCROLL: ScrollCfg = {
|
||||
open: false,
|
||||
|
||||
@ -281,7 +281,8 @@ export class Area extends G2PlotChartView<AreaOptions, G2Area> {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.configConditions
|
||||
)(chart, options, {}, this)
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,8 @@ export const LINE_EDITOR_PROPERTY: EditorProperty[] = [
|
||||
'assist-line',
|
||||
'function-cfg',
|
||||
'jump-set',
|
||||
'linkage'
|
||||
'linkage',
|
||||
'threshold'
|
||||
]
|
||||
export const LINE_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
'background-overall-component': ['all'],
|
||||
@ -59,7 +60,8 @@ export const LINE_EDITOR_PROPERTY_INNER: EditorPropertyInner = {
|
||||
'fontShadow'
|
||||
],
|
||||
'legend-selector': ['icon', 'orient', 'fontSize', 'color', 'hPosition', 'vPosition'],
|
||||
'function-cfg': ['slider', 'emptyDataStrategy']
|
||||
'function-cfg': ['slider', 'emptyDataStrategy'],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
|
||||
export const LINE_AXIS_TYPE: AxisType[] = [
|
||||
|
||||
@ -358,7 +358,8 @@ export class Line extends G2PlotChartView<LineOptions, G2Line> {
|
||||
this.configXAxis,
|
||||
this.configYAxis,
|
||||
this.configSlider,
|
||||
this.configAnalyse
|
||||
this.configAnalyse,
|
||||
this.configConditions
|
||||
)(chart, options)
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { hexColorToRGBA, parseJson } from '../../util'
|
||||
import { hexColorToRGBA, isAlphaColor, isTransparent, parseJson } from '../../util'
|
||||
import {
|
||||
DEFAULT_BASIC_STYLE,
|
||||
DEFAULT_XAXIS_STYLE,
|
||||
@ -1328,3 +1328,53 @@ export const TOOLTIP_TPL =
|
||||
'<span class="g2-tooltip-name">{name}</span>:' +
|
||||
'<span class="g2-tooltip-value">{value}</span>' +
|
||||
'</li>'
|
||||
|
||||
export function getConditions(chart: Chart) {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
const annotations = []
|
||||
if (!threshold.enable) return annotations
|
||||
const conditions = threshold.lineThreshold ?? []
|
||||
|
||||
for (const field of conditions) {
|
||||
for (const t of field.conditions) {
|
||||
if ([2, 3, 4].includes(field.field.deType)) {
|
||||
const annotation = {
|
||||
type: 'regionFilter',
|
||||
start: ['start', 'median'],
|
||||
end: ['end', 'min'],
|
||||
color: t.color
|
||||
}
|
||||
// 加中线
|
||||
const annotationLine = {
|
||||
type: 'line',
|
||||
start: ['start', t.value],
|
||||
end: ['end', t.value],
|
||||
style: {
|
||||
stroke: t.color,
|
||||
lineDash: [2, 2]
|
||||
}
|
||||
}
|
||||
if (t.term === 'between') {
|
||||
annotation.start = ['start', parseFloat(t.min)]
|
||||
annotation.end = ['end', parseFloat(t.max)]
|
||||
annotationLine.start = ['start', parseFloat(t.min)]
|
||||
annotationLine.end = ['end', parseFloat(t.min)]
|
||||
annotations.push(JSON.parse(JSON.stringify(annotationLine)))
|
||||
annotationLine.start = ['start', parseFloat(t.max)]
|
||||
annotationLine.end = ['end', parseFloat(t.max)]
|
||||
annotations.push(annotationLine)
|
||||
} else if (['lt', 'le'].includes(t.term)) {
|
||||
annotation.start = ['start', t.value]
|
||||
annotation.end = ['end', 'min']
|
||||
annotations.push(annotationLine)
|
||||
} else if (['gt', 'ge'].includes(t.term)) {
|
||||
annotation.start = ['start', t.value]
|
||||
annotation.end = ['end', 'max']
|
||||
annotations.push(annotationLine)
|
||||
}
|
||||
annotations.push(annotation)
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations
|
||||
}
|
||||
|
||||
@ -10,7 +10,8 @@ import {
|
||||
getTheme,
|
||||
getTooltip,
|
||||
getXAxis,
|
||||
getYAxis
|
||||
getYAxis,
|
||||
getConditions
|
||||
} from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import {
|
||||
AntVAbstractChartView,
|
||||
@ -171,6 +172,14 @@ export abstract class G2PlotChartView<
|
||||
return undefined
|
||||
}
|
||||
|
||||
protected configConditions(chart: Chart, options: O) {
|
||||
const annotations = getConditions(chart)
|
||||
return {
|
||||
...options,
|
||||
annotations: [...annotations, ...((options as unknown as Options).annotations || [])]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式配置公共参数,处理常用的配置,后续如果有其他通用配置也可以放进来,需要单独配置的属性在各个图表自行实现。
|
||||
* @param chart 数据库图表对象。
|
||||
|
||||
Loading…
Reference in New Issue
Block a user