feat: 阈值/辅助线开关

This commit is contained in:
wisonic-s 2023-10-24 19:39:07 +08:00
parent b2144a4678
commit a6012476b0
15 changed files with 130 additions and 78 deletions

View File

@ -821,9 +821,11 @@ public class ChartDataManage {
return list; return list;
} }
String assistLine = (String) JsonUtil.toJSONString(senior.get("assistLine")); var assistLineCfg = JsonUtil.parseObject((String) JsonUtil.toJSONString(senior.get("assistLineCfg")), ChartSeniorAssistCfgDTO.class);
List<ChartSeniorAssistDTO> assistLines = JsonUtil.parseList(assistLine, new TypeReference<>() { if (null == assistLineCfg || !assistLineCfg.isEnable()) {
}); return list;
}
List<ChartSeniorAssistDTO> assistLines = assistLineCfg.getAssistLine();
if (ObjectUtils.isEmpty(assistLines)) { if (ObjectUtils.isEmpty(assistLines)) {
return list; return list;

View File

@ -9,7 +9,7 @@ declare interface ChartSenior {
/** /**
* 线 * 线
*/ */
assistLine: AssistLine[] assistLineCfg: ChartAssistLineCfg
/** /**
* *
*/ */
@ -61,6 +61,19 @@ declare interface ChartFunctionCfg {
/** /**
* 线 * 线
*/ */
declare interface ChartAssistLineCfg {
/**
*
*/
enable: boolean
/**
* 线
*/
assistLine: AssistLine[]
}
/**
* 线
*/
declare interface AssistLine { declare interface AssistLine {
/** /**
* 线 * 线
@ -100,6 +113,10 @@ declare interface AssistLine {
* *
*/ */
declare interface ChartThreshold { declare interface ChartThreshold {
/**
*
*/
enable: boolean
/** /**
* 仪表盘阈值: x,y,z * 仪表盘阈值: x,y,z
*/ */

View File

@ -5,7 +5,7 @@ import ScrollCfg from '@/views/chart/components/editor/editor-senior/components/
import AssistLine from '@/views/chart/components/editor/editor-senior/components/AssistLine.vue' import AssistLine from '@/views/chart/components/editor/editor-senior/components/AssistLine.vue'
import Threshold from '@/views/chart/components/editor/editor-senior/components/Threshold.vue' import Threshold from '@/views/chart/components/editor/editor-senior/components/Threshold.vue'
import CollapseSwitchItem from '@/components/collapse-switch-item/src/CollapseSwitchItem.vue' import CollapseSwitchItem from '@/components/collapse-switch-item/src/CollapseSwitchItem.vue'
import { computed, PropType, ref, toRefs } from 'vue' import { computed, PropType, ref, toRefs, watch } from 'vue'
import LinkJumpSet from '@/components/visualization/LinkJumpSet.vue' import LinkJumpSet from '@/components/visualization/LinkJumpSet.vue'
import LinkageSet from '@/components/visualization/LinkageSet.vue' import LinkageSet from '@/components/visualization/LinkageSet.vue'
import { canvasSave } from '@/utils/canvasUtils' import { canvasSave } from '@/utils/canvasUtils'
@ -15,6 +15,8 @@ import { updateLinkageActive } from '@/api/visualization/linkage'
import { includesAny } from '../util/StringUtils' import { includesAny } from '../util/StringUtils'
import { ElIcon, ElMessage } from 'element-plus-secondary' import { ElIcon, ElMessage } from 'element-plus-secondary'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { BASE_VIEW_CONFIG } from '../util/chart'
import { cloneDeep, defaultsDeep } from 'lodash-es'
const dvMainStore = dvMainStoreWithOut() const dvMainStore = dvMainStoreWithOut()
const { dvInfo } = storeToRefs(dvMainStore) const { dvInfo } = storeToRefs(dvMainStore)
@ -70,7 +72,12 @@ const props = defineProps({
}) })
const { chart, themes, properties, propertyInnerAll } = toRefs(props) const { chart, themes, properties, propertyInnerAll } = toRefs(props)
watch(
() => chart.value?.senior,
() => {
chart.value.senior = defaultsDeep(chart.value?.senior || {}, cloneDeep(BASE_VIEW_CONFIG.senior))
}
)
const seniorCounts = computed(() => { const seniorCounts = computed(() => {
let linkageCount = 0 let linkageCount = 0
let jumpCount = 0 let jumpCount = 0
@ -187,11 +194,14 @@ const linkageActiveChange = () => {
/> />
</el-collapse-item> </el-collapse-item>
<el-collapse-item <collapse-switch-item
:effect="themes" :effect="themes"
v-if="showProperties('assist-line')"
name="analyse"
:title="t('chart.assist_line')" :title="t('chart.assist_line')"
:change-model="chart.senior.assistLineCfg"
v-if="showProperties('assist-line')"
v-model="chart.senior.assistLineCfg.enable"
name="analyse"
@modelChange="val => onAssistLineChange({ data: val })"
> >
<assist-line <assist-line
:chart="props.chart" :chart="props.chart"
@ -200,13 +210,13 @@ const linkageActiveChange = () => {
:property-inner="propertyInnerAll['assist-line']" :property-inner="propertyInnerAll['assist-line']"
@onAssistLineChange="onAssistLineChange" @onAssistLineChange="onAssistLineChange"
/> />
</el-collapse-item> </collapse-switch-item>
<collapse-switch-item <collapse-switch-item
v-if="showProperties('scroll-cfg')"
:effect="themes" :effect="themes"
:title="t('chart.scroll_cfg')" :title="t('chart.scroll_cfg')"
:change-model="chart.senior.scrollCfg" :change-model="chart.senior.scrollCfg"
v-if="showProperties('scroll-cfg')"
v-model="chart.senior.scrollCfg.open" v-model="chart.senior.scrollCfg.open"
name="scroll" name="scroll"
@modelChange="onScrollCfgChange" @modelChange="onScrollCfgChange"
@ -219,11 +229,14 @@ const linkageActiveChange = () => {
/> />
</collapse-switch-item> </collapse-switch-item>
<el-collapse-item <collapse-switch-item
:effect="themes" :effect="themes"
:title="t('chart.threshold')"
:change-model="chart.senior.threshold"
v-model="chart.senior.threshold.enable"
v-if="showProperties('threshold')" v-if="showProperties('threshold')"
name="threshold" name="threshold"
:title="t('chart.threshold')" @modelChange="onThresholdChange"
> >
<threshold <threshold
:themes="themes" :themes="themes"
@ -231,7 +244,7 @@ const linkageActiveChange = () => {
:property-inner="propertyInnerAll['threshold']" :property-inner="propertyInnerAll['threshold']"
@onThresholdChange="onThresholdChange" @onThresholdChange="onThresholdChange"
/> />
</el-collapse-item> </collapse-switch-item>
<collapse-switch-item <collapse-switch-item
v-if="showProperties('linkage')" v-if="showProperties('linkage')"

View File

@ -3,7 +3,8 @@ import { onMounted, reactive, watch, computed, PropType } from 'vue'
import { useI18n } from '@/hooks/web/useI18n' import { useI18n } from '@/hooks/web/useI18n'
import { ElIcon, ElMessage } from 'element-plus-secondary' import { ElIcon, ElMessage } from 'element-plus-secondary'
import AssistLineEdit from '@/views/chart/components/editor/editor-senior/components/dialog/AssistLineEdit.vue' import AssistLineEdit from '@/views/chart/components/editor/editor-senior/components/dialog/AssistLineEdit.vue'
import _ from 'lodash' import { defaultsDeep, find } from 'lodash-es'
import { DEFAULT_ASSIST_LINE_CFG } from '../../util/chart'
const { t } = useI18n() const { t } = useI18n()
@ -11,7 +12,7 @@ const emit = defineEmits(['onAssistLineChange'])
const props = defineProps({ const props = defineProps({
chart: { chart: {
type: Object, type: Object as PropType<ChartObj>,
required: true required: true
}, },
quotaData: { quotaData: {
@ -32,28 +33,26 @@ const quotaFields = computed<Array<any>>(() => {
}) })
const state = reactive({ const state = reactive({
assistLine: [], assistLineCfg: {
enable: false,
assistLine: []
},
editLineDialog: false, editLineDialog: false,
lineArr: [], lineArr: [],
quotaFields: [] quotaFields: []
}) })
watch( watch(
() => props.chart, () => props.chart.senior.assistLineCfg,
() => { () => {
init() init()
} },
{ deep: true }
) )
const changeAssistLine = () => { const changeAssistLine = () => {
let flag = false const flag = state.assistLineCfg.assistLine.findIndex(ele => ele.field === '1') !== -1
const arr = state.assistLine.filter(ele => { emit('onAssistLineChange', { data: state.assistLineCfg, requestData: flag })
return ele.field === '1'
})
if (arr && arr.length > 0) {
flag = true
}
emit('onAssistLineChange', { data: state.assistLine, requestData: flag })
} }
const lineChange = val => { const lineChange = val => {
@ -68,7 +67,6 @@ const closeEditLine = () => {
} }
const changeLine = () => { const changeLine = () => {
console.log(state.lineArr)
// check line config // check line config
for (let i = 0; i < state.lineArr.length; i++) { for (let i = 0; i < state.lineArr.length; i++) {
const ele = state.lineArr[i] const ele = state.lineArr[i]
@ -96,35 +94,29 @@ const changeLine = () => {
} }
} }
} }
state.assistLine = JSON.parse(JSON.stringify(state.lineArr)) state.assistLineCfg.assistLine = JSON.parse(JSON.stringify(state.lineArr))
changeAssistLine() changeAssistLine()
closeEditLine() closeEditLine()
} }
function existField(line) { function existField(line) {
return !!_.find(quotaFields.value, d => d.id === line.id) return !!find(quotaFields.value, d => d.id === line.id)
} }
const init = () => { const init = () => {
const chart = JSON.parse(JSON.stringify(props.chart)) const chart = JSON.parse(JSON.stringify(props.chart))
if (chart.senior) { if (chart.senior) {
let senior = null const senior = chart.senior
if (Object.prototype.toString.call(chart.senior) === '[object Object]') { if (senior.assistLineCfg?.assistLine) {
senior = JSON.parse(JSON.stringify(chart.senior)) const assistLine = senior.assistLineCfg.assistLine
} else { for (let i = 0; i < assistLine.length; i++) {
senior = JSON.parse(chart.senior) if (!assistLine[i].fontSize) {
} assistLine[i].fontSize = 10
if (senior.assistLine) {
for (let i = 0; i < senior.assistLine.length; i++) {
if (!senior.assistLine[i].fontSize) {
senior.assistLine[i].fontSize = '10'
} }
} }
state.assistLine = senior.assistLine state.assistLineCfg = defaultsDeep(senior.assistLineCfg, DEFAULT_ASSIST_LINE_CFG)
} else {
state.assistLine = []
} }
state.lineArr = JSON.parse(JSON.stringify(state.assistLine)) state.lineArr = JSON.parse(JSON.stringify(state.assistLineCfg.assistLine))
} }
} }
@ -141,16 +133,17 @@ onMounted(() => {
<span <span
class="set-text-info" class="set-text-info"
:class="{ 'set-text-info-dark': themes === 'dark' }" :class="{ 'set-text-info-dark': themes === 'dark' }"
v-if="state.assistLine.length > 0" v-if="state.assistLineCfg.assistLine.length > 0"
> >
已设置 已设置
</span> </span>
<el-button <el-button
class="circle-button font14"
:class="'label-' + props.themes" :class="'label-' + props.themes"
:style="{ width: '24px', marginLeft: '6px' }"
:disabled="!state.assistLineCfg.enable"
class="circle-button font14"
text text
size="small" size="small"
:style="{ width: '24px', marginLeft: '6px' }"
@click="editLine" @click="editLine"
> >
<template #icon> <template #icon>
@ -162,7 +155,7 @@ onMounted(() => {
</span> </span>
</div> </div>
<el-row v-for="(item, index) in state.assistLine" :key="index" class="line-style"> <el-row v-for="(item, index) in state.assistLineCfg.assistLine" :key="index" class="line-style">
<el-col :span="8"> <el-col :span="8">
<span :title="item.name">{{ item.name }}</span> <span :title="item.name">{{ item.name }}</span>
</el-col> </el-col>
@ -199,7 +192,7 @@ onMounted(() => {
class="dialog-css" class="dialog-css"
> >
<assist-line-edit <assist-line-edit
:line="state.assistLine" :line="state.assistLineCfg.assistLine"
:quota-fields="quotaFields" :quota-fields="quotaFields"
@onAssistLineChange="lineChange" @onAssistLineChange="lineChange"
/> />

View File

@ -7,12 +7,13 @@ import TableThresholdEdit from '@/views/chart/components/editor/editor-senior/co
import TextLabelThresholdEdit from '@/views/chart/components/editor/editor-senior/components/dialog/TextLabelThresholdEdit.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 TextThresholdEdit from '@/views/chart/components/editor/editor-senior/components/dialog/TextThresholdEdit.vue'
import { fieldType } from '@/utils/attr' import { fieldType } from '@/utils/attr'
import { defaultsDeep } from 'lodash-es'
const { t } = useI18n() const { t } = useI18n()
const props = defineProps({ const props = defineProps({
chart: { chart: {
type: Object, type: Object as PropType<ChartObj>,
required: true required: true
}, },
themes: { themes: {
@ -28,14 +29,15 @@ const showProperty = prop => props.propertyInner?.includes(prop)
const emit = defineEmits(['onThresholdChange']) const emit = defineEmits(['onThresholdChange'])
watch( watch(
() => props.chart, () => props.chart.senior.threshold,
() => { () => {
init() init()
} },
{ deep: true }
) )
const state = reactive({ const state = reactive({
thresholdForm: JSON.parse(JSON.stringify(DEFAULT_THRESHOLD)), thresholdForm: {} as ChartThreshold,
editTextLabelThresholdDialog: false, editTextLabelThresholdDialog: false,
textThresholdArr: [], textThresholdArr: [],
editLabelThresholdDialog: false, editLabelThresholdDialog: false,
@ -47,14 +49,9 @@ const state = reactive({
const init = () => { const init = () => {
const chart = JSON.parse(JSON.stringify(props.chart)) const chart = JSON.parse(JSON.stringify(props.chart))
if (chart.senior) { if (chart.senior) {
let senior = null const senior = chart.senior
if (Object.prototype.toString.call(chart.senior) === '[object Object]') {
senior = JSON.parse(JSON.stringify(chart.senior))
} else {
senior = JSON.parse(chart.senior)
}
if (senior.threshold) { if (senior.threshold) {
state.thresholdForm = senior.threshold state.thresholdForm = defaultsDeep(senior.threshold, DEFAULT_THRESHOLD)
} }
state.textThresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.textLabelThreshold)) state.textThresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.textLabelThreshold))
state.thresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.labelThreshold)) state.thresholdArr = JSON.parse(JSON.stringify(state.thresholdForm.labelThreshold))
@ -243,9 +240,10 @@ init()
<span>0,</span> <span>0,</span>
<el-input <el-input
:effect="themes" :effect="themes"
:placeholder="t('chart.threshold_range')"
:disabled="!state.thresholdForm.enable"
v-model="state.thresholdForm.gaugeThreshold" v-model="state.thresholdForm.gaugeThreshold"
style="width: 100px; margin: 0 10px" style="width: 100px; margin: 0 10px"
:placeholder="t('chart.threshold_range')"
size="small" size="small"
clearable clearable
@change="gaugeThresholdChange" @change="gaugeThresholdChange"
@ -409,11 +407,12 @@ init()
</span> </span>
<el-button <el-button
:title="t('chart.edit')" :title="t('chart.edit')"
class="circle-button"
:class="'label-' + props.themes" :class="'label-' + props.themes"
:style="{ width: '24px', marginLeft: '6px' }"
:disabled="!state.thresholdForm.enable"
class="circle-button"
text text
size="small" size="small"
:style="{ width: '24px', marginLeft: '6px' }"
@click="editTableThreshold" @click="editTableThreshold"
> >
<template #icon> <template #icon>

View File

@ -562,7 +562,7 @@ span {
.series-select-option { .series-select-option {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: start; justify-content: flex-start;
padding: 0 11px; padding: 0 11px;
} }
</style> </style>

View File

@ -814,7 +814,7 @@ onMounted(() => {
.series-select-option { .series-select-option {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: start; justify-content: flex-start;
padding: 0 11px; padding: 0 11px;
} }
.m-divider { .m-divider {

View File

@ -863,12 +863,12 @@ onMounted(() => {
.series-select-option { .series-select-option {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: start; justify-content: flex-start;
padding: 0 11px; padding: 0 11px;
} }
.invalid-field { .invalid-field {
::v-deep(.ed-input__wrapper) { :deep(.ed-input__wrapper) {
box-shadow: 0 0 0 1px rgb(245, 74, 69) inset !important; box-shadow: 0 0 0 1px rgb(245, 74, 69) inset !important;
} }
} }

View File

@ -666,7 +666,7 @@ const onBackgroundChange = val => {
} }
const onAssistLineChange = val => { const onAssistLineChange = val => {
view.value.senior.assistLine = val.data view.value.senior.assistLineCfg = val.data
if (val.requestData) { if (val.requestData) {
calcData(view.value) calcData(view.value)
} else { } else {

View File

@ -604,7 +604,12 @@ export const DEFAULT_FUNCTION_CFG: ChartFunctionCfg = {
emptyDataStrategy: 'breakLine', emptyDataStrategy: 'breakLine',
emptyDataFieldCtrl: [] emptyDataFieldCtrl: []
} }
export const DEFAULT_ASSIST_LINE_CFG: ChartAssistLineCfg = {
enable: false,
assistLine: []
}
export const DEFAULT_THRESHOLD: ChartThreshold = { export const DEFAULT_THRESHOLD: ChartThreshold = {
enable: false,
gaugeThreshold: '', gaugeThreshold: '',
labelThreshold: [], labelThreshold: [],
tableThreshold: [], tableThreshold: [],
@ -1268,7 +1273,7 @@ export const BASE_VIEW_CONFIG = {
}, },
senior: { senior: {
functionCfg: DEFAULT_FUNCTION_CFG, functionCfg: DEFAULT_FUNCTION_CFG,
assistLine: [], assistLineCfg: DEFAULT_ASSIST_LINE_CFG,
threshold: DEFAULT_THRESHOLD, threshold: DEFAULT_THRESHOLD,
scrollCfg: DEFAULT_SCROLL scrollCfg: DEFAULT_SCROLL
} }

View File

@ -143,7 +143,7 @@ export class Gauge extends G2PlotChartView<GaugeOptions, G2Gauge> {
if (chart.senior) { if (chart.senior) {
const senior = parseJson(chart.senior) const senior = parseJson(chart.senior)
const threshold = senior.threshold ?? DEFAULT_THRESHOLD const threshold = senior.threshold ?? DEFAULT_THRESHOLD
if (threshold.gaugeThreshold) { if (threshold.enable && threshold.gaugeThreshold) {
hasThreshold = true hasThreshold = true
const arr = threshold.gaugeThreshold.split(',') const arr = threshold.gaugeThreshold.split(',')
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {

View File

@ -534,7 +534,11 @@ export function getSlider(chart: Chart) {
export function getAnalyse(chart: Chart) { export function getAnalyse(chart: Chart) {
const assistLine = [] const assistLine = []
const senior = parseJson(chart.senior) const senior = parseJson(chart.senior)
if (senior.assistLine?.length > 0) { if (!senior.assistLineCfg?.enable) {
return assistLine
}
const assistLineArr = senior.assistLineCfg.assistLine
if (assistLineArr?.length > 0) {
const customStyle = parseJson(chart.customStyle) const customStyle = parseJson(chart.customStyle)
let yAxisPosition, axisFormatterCfg let yAxisPosition, axisFormatterCfg
if (customStyle.yAxis) { if (customStyle.yAxis) {
@ -545,8 +549,8 @@ export function getAnalyse(chart: Chart) {
: DEFAULT_YAXIS_STYLE.axisLabelFormatter : DEFAULT_YAXIS_STYLE.axisLabelFormatter
} }
const fixedLines = senior.assistLine.filter(ele => ele.field === '0') const fixedLines = assistLineArr.filter(ele => ele.field === '0')
const dynamicLineFields = senior.assistLine const dynamicLineFields = assistLineArr
.filter(ele => ele.field === '1') .filter(ele => ele.field === '1')
.map(item => item.fieldId) .map(item => item.fieldId)
const quotaFields = _.filter(chart.yAxis, ele => ele.summary !== '' && ele.id !== '-1') const quotaFields = _.filter(chart.yAxis, ele => ele.summary !== '' && ele.id !== '-1')
@ -589,7 +593,11 @@ export function getAnalyse(chart: Chart) {
export function getAnalyseHorizontal(chart: Chart) { export function getAnalyseHorizontal(chart: Chart) {
const assistLine = [] const assistLine = []
const senior = parseJson(chart.senior) const senior = parseJson(chart.senior)
if (senior.assistLine?.length > 0) { if (!senior.assistLineCfg?.enable) {
return assistLine
}
const assistLineArr = senior.assistLineCfg.assistLine
if (assistLineArr?.length > 0) {
const customStyle = parseJson(chart.customStyle) const customStyle = parseJson(chart.customStyle)
let xAxisPosition, axisFormatterCfg let xAxisPosition, axisFormatterCfg
if (customStyle.xAxis) { if (customStyle.xAxis) {
@ -600,8 +608,8 @@ export function getAnalyseHorizontal(chart: Chart) {
: DEFAULT_XAXIS_STYLE.axisLabelFormatter : DEFAULT_XAXIS_STYLE.axisLabelFormatter
} }
const fixedLines = senior.assistLine.filter(ele => ele.field === '0') const fixedLines = assistLineArr.filter(ele => ele.field === '0')
const dynamicLineFields = senior.assistLine const dynamicLineFields = assistLineArr
.filter(ele => ele.field === '1') .filter(ele => ele.field === '1')
.map(item => item.fieldId) .map(item => item.fieldId)
const quotaFields = _.filter(chart.yAxis, ele => ele.summary !== '' && ele.id !== '-1') const quotaFields = _.filter(chart.yAxis, ele => ele.summary !== '' && ele.id !== '-1')

View File

@ -329,11 +329,15 @@ export function getCurrentField(valueFieldList: Axis[], field: ChartViewField) {
} }
export function getConditions(chart: Chart) { export function getConditions(chart: Chart) {
const { threshold } = parseJson(chart.senior)
if (!threshold.enable) {
return
}
const res = { const res = {
text: [], text: [],
background: [] background: []
} }
const conditions = parseJson(chart.senior).threshold.tableThreshold ?? [] const conditions = threshold.tableThreshold ?? []
if (conditions?.length > 0) { if (conditions?.length > 0) {
const { tableCell, basicStyle } = parseJson(chart.customAttr) const { tableCell, basicStyle } = parseJson(chart.customAttr)

View File

@ -290,7 +290,7 @@ onBeforeUnmount(() => {
.canvas-content { .canvas-content {
width: 100% !important; width: 100% !important;
height: 100% !important; height: 100% !important;
::v-deep(.g2-tooltip) { :deep(.g2-tooltip) {
position: fixed !important; position: fixed !important;
} }
} }

View File

@ -0,0 +1,11 @@
package io.dataease.api.chart.dto;
import lombok.Data;
import java.util.List;
@Data
public class ChartSeniorAssistCfgDTO {
private boolean enable;
private List<ChartSeniorAssistDTO> assistLine;
}