mirror of
https://github.com/dataease/dataease.git
synced 2026-05-14 21:12:33 +08:00
@@ -1,3 +1,5 @@
|
||||
import { SymbolicMap } from '@/views/chart/components/js/panel/charts/map/symbolic-map'
|
||||
|
||||
/**
|
||||
* 高级设置
|
||||
*/
|
||||
@@ -151,6 +153,8 @@ declare interface ChartThreshold {
|
||||
* 折线阈值
|
||||
*/
|
||||
lineThreshold: TableThreshold[]
|
||||
|
||||
symbolicBubbleThreshold: TableThreshold[]
|
||||
}
|
||||
declare interface TableThreshold {
|
||||
/**
|
||||
|
||||
@@ -790,6 +790,138 @@ init()
|
||||
</el-col>
|
||||
<!--折线-->
|
||||
<el-col v-show="showProperty('lineThreshold')">
|
||||
<el-col>
|
||||
<div class="inner-container">
|
||||
<span class="label" :class="'label-' + props.themes">{{
|
||||
$t('visualization.condition_style_set')
|
||||
}}</span>
|
||||
<span class="right-btns">
|
||||
<span
|
||||
class="set-text-info"
|
||||
:class="{ 'set-text-info-dark': themes === 'dark' }"
|
||||
v-if="state.thresholdForm?.tableThreshold?.length > 0"
|
||||
>
|
||||
$t('visualization.already_setting')
|
||||
</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 === 'eq'" :title="t('chart.filter_eq')">
|
||||
{{ t('chart.filter_eq') }}</span
|
||||
>
|
||||
<span v-else-if="item.term === 'not_eq'" :title="t('chart.filter_not_eq')">
|
||||
{{ t('chart.filter_not_eq') }}</span
|
||||
>
|
||||
<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>
|
||||
|
||||
<!-- symbolic map -->
|
||||
<el-col v-show="showProperty('symbolicBubbleThreshold')">
|
||||
<el-col>
|
||||
<div class="inner-container">
|
||||
<span class="label" :class="'label-' + props.themes">{{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
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 { computed, PropType, reactive } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { COLOR_PANEL } from '../../../util/chart'
|
||||
import { fieldType } from '@/utils/attr'
|
||||
@@ -34,30 +34,84 @@ const thresholdCondition = {
|
||||
max: '1',
|
||||
type: 'fixed'
|
||||
}
|
||||
const valueOptions = [
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
const valueOptions = computed(() => {
|
||||
if (props.chart.type === 'symbolic-map') {
|
||||
return [
|
||||
{
|
||||
value: 'lt',
|
||||
label: t('chart.filter_lt')
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'eq',
|
||||
label: t('chart.filter_eq')
|
||||
},
|
||||
{
|
||||
value: 'not_eq',
|
||||
label: t('chart.filter_not_eq')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'gt',
|
||||
label: t('chart.filter_gt')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'lt',
|
||||
label: t('chart.filter_lt')
|
||||
},
|
||||
{
|
||||
value: 'gt',
|
||||
label: t('chart.filter_gt')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
value: 'between',
|
||||
label: t('chart.filter_between')
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'le',
|
||||
label: t('chart.filter_le')
|
||||
},
|
||||
{
|
||||
value: 'ge',
|
||||
label: t('chart.filter_ge')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '',
|
||||
options: [
|
||||
{
|
||||
value: 'between',
|
||||
label: t('chart.filter_between')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
return [
|
||||
{
|
||||
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({
|
||||
@@ -76,21 +130,32 @@ const init = () => {
|
||||
}
|
||||
const initOptions = (item, fieldObj) => {
|
||||
if (fieldObj) {
|
||||
item.options = JSON.parse(JSON.stringify(valueOptions))
|
||||
item.options = JSON.parse(JSON.stringify(valueOptions.value))
|
||||
item.conditions &&
|
||||
item.conditions.forEach(ele => {
|
||||
ele.term = ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const isSymbolicMap = computed(() => {
|
||||
return props.chart.type === 'symbolic-map'
|
||||
})
|
||||
|
||||
const initFields = () => {
|
||||
let fields = []
|
||||
const yAxis = JSON.parse(JSON.stringify(props.chart.yAxis))
|
||||
fields = [...yAxis]
|
||||
if (isSymbolicMap.value) {
|
||||
const extBubble = JSON.parse(JSON.stringify(props.chart.extBubble))
|
||||
fields = [...extBubble]
|
||||
} else {
|
||||
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 => {
|
||||
item.options = JSON.parse(JSON.stringify(valueOptions.value))
|
||||
const fieldItemObj = state.fields.filter(ele => ele.id === item.fieldId)
|
||||
if (fieldItemObj.length === 0) {
|
||||
change = true
|
||||
@@ -327,7 +392,10 @@ init()
|
||||
</el-col>
|
||||
|
||||
<el-col :span="3">
|
||||
<el-form-item class="form-item" :label="t('chart.textColor')">
|
||||
<el-form-item
|
||||
class="form-item"
|
||||
:label="isSymbolicMap ? t('chart.color') : t('chart.textColor')"
|
||||
>
|
||||
<el-color-picker
|
||||
is-custom
|
||||
size="large"
|
||||
|
||||
@@ -6,7 +6,12 @@ import {
|
||||
L7Wrapper
|
||||
} from '@/views/chart/components/js/panel/types/impl/l7'
|
||||
import { MAP_EDITOR_PROPERTY_INNER } from '@/views/chart/components/js/panel/charts/map/common'
|
||||
import { hexColorToRGBA, parseJson, svgStrToUrl } from '@/views/chart/components/js/util'
|
||||
import {
|
||||
getColorFormAlphaColor,
|
||||
hexColorToRGBA,
|
||||
parseJson,
|
||||
svgStrToUrl
|
||||
} from '@/views/chart/components/js/util'
|
||||
import { deepCopy } from '@/utils/utils'
|
||||
import { GaodeMap } from '@antv/l7-maps'
|
||||
import { Scene } from '@antv/l7-scene'
|
||||
@@ -15,6 +20,7 @@ import { LayerPopup } from '@antv/l7'
|
||||
import { mapRendered, mapRendering } from '@/views/chart/components/js/panel/common/common_antv'
|
||||
import { configCarouselTooltip } from '@/views/chart/components/js/panel/charts/map/tooltip-carousel'
|
||||
import { DEFAULT_BASIC_STYLE } from '@/views/chart/components/editor/util/chart'
|
||||
import { filter } from 'lodash-es'
|
||||
const { t } = useI18n()
|
||||
|
||||
/**
|
||||
@@ -28,7 +34,8 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
'symbolic-style-selector',
|
||||
'title-selector',
|
||||
'label-selector',
|
||||
'tooltip-selector'
|
||||
'tooltip-selector',
|
||||
'threshold'
|
||||
]
|
||||
propertyInner: EditorPropertyInner = {
|
||||
...MAP_EDITOR_PROPERTY_INNER,
|
||||
@@ -52,7 +59,8 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
'show',
|
||||
'backgroundColor',
|
||||
'carousel'
|
||||
]
|
||||
],
|
||||
threshold: ['lineThreshold']
|
||||
}
|
||||
axis: AxisType[] = ['xAxis', 'xAxisExt', 'extBubble', 'filter', 'extLabel', 'extTooltip']
|
||||
axisConfig: AxisConfig = {
|
||||
@@ -228,8 +236,18 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
// 存储已分配的颜色
|
||||
const colorAssignments = new Map()
|
||||
const sizeKey = extBubble.length > 0 ? extBubble[0].dataeaseName : ''
|
||||
|
||||
//todo 条件颜色
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
let conditions = []
|
||||
if (threshold.enable) {
|
||||
conditions = threshold.lineThreshold ?? []
|
||||
}
|
||||
const extBubbleIds = chart.extBubble.map(i => i.id)
|
||||
conditions = filter(conditions, c => extBubbleIds.includes(c.fieldId))
|
||||
|
||||
const data = chart.data?.tableRow
|
||||
? chart.data.tableRow.map(item => {
|
||||
? chart.data.tableRow.map((item, index) => {
|
||||
// 颜色标识
|
||||
const identifier = item[xAxisExt[0]?.dataeaseName]
|
||||
// 检查该标识是否已有颜色分配,如果没有则分配
|
||||
@@ -239,6 +257,57 @@ export class SymbolicMap extends L7ChartView<Scene, L7Config> {
|
||||
// 记录分配的颜色
|
||||
colorAssignments.set(identifier, color)
|
||||
}
|
||||
if (conditions.length > 0) {
|
||||
for (let i = 0; i < conditions.length; i++) {
|
||||
const c = conditions[i]
|
||||
const value = item[c.field.dataeaseName]
|
||||
for (const t of c.conditions) {
|
||||
const v = t.value
|
||||
|
||||
//保存一下颜色到map
|
||||
const _color = getColorFormAlphaColor(t.color)
|
||||
|
||||
if (t.term === 'between') {
|
||||
const start = parseFloat(t.min)
|
||||
const end = parseFloat(t.max)
|
||||
if (start <= value && value <= end) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
} else if ('lt' === t.term) {
|
||||
if (value < v) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
} else if ('le' === t.term) {
|
||||
if (value <= v) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
} else if ('gt' === t.term) {
|
||||
if (value > v) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
} else if ('ge' === t.term) {
|
||||
if (value >= v) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
} else if ('eq' === t.term) {
|
||||
if (value === v) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
} else if ('not_eq' === t.term) {
|
||||
if (value !== v) {
|
||||
color = t.color
|
||||
colorsWithAlpha[index] = hexColorToRGBA(_color, alpha)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
color,
|
||||
|
||||
@@ -1373,7 +1373,8 @@ export const TOOLTIP_TPL =
|
||||
export function getConditions(chart: Chart) {
|
||||
const { threshold } = parseJson(chart.senior)
|
||||
const annotations = []
|
||||
if (!threshold.enable || chart.type === 'area-stack') return annotations
|
||||
if (!threshold.enable || chart.type === 'area-stack' || chart.type === 'symbolic-map')
|
||||
return annotations
|
||||
const conditions = threshold.lineThreshold ?? []
|
||||
const yAxisIds = chart.yAxis.map(i => i.id)
|
||||
for (const field of conditions) {
|
||||
|
||||
@@ -999,6 +999,19 @@ export function isAlphaColor(color: string): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
export function getColorFormAlphaColor(color: string): string {
|
||||
if (isAlphaColor(color)) {
|
||||
if (color.startsWith('#')) {
|
||||
return color.slice(0, 7)
|
||||
}
|
||||
if (color.startsWith('rgb') || color.startsWith('RGB')) {
|
||||
const list = color.split(',')
|
||||
return list[0] + ',' + list[1] + ',' + list[2] + ')'
|
||||
}
|
||||
}
|
||||
return color
|
||||
}
|
||||
|
||||
export function isTransparent(color: string): boolean {
|
||||
if (!color?.trim()) {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user