NEZ-3478 feat: dashboard 图表增加 legend 全选,反选按钮

This commit is contained in:
zyh
2024-05-23 16:36:29 +08:00
parent fa903c18bb
commit 53d57759f8
4 changed files with 216 additions and 192 deletions

View File

@@ -558,7 +558,7 @@ td .nz-icon-gear:before {
pointer-events: none;
}
.yAxis-icon{
margin-right: 4px;
margin-right: 5px;
background: transparent !important;
}

View File

@@ -274,11 +274,6 @@
&.nz-chart__component--left {
flex-direction: row-reverse;
}
&.nz-chart__component--right, &.nz-chart__component--left {
.legend-container {
flex-direction: column;
}
}
.legend-box{
width: 100%;
display: flex;
@@ -382,13 +377,20 @@
}
}
.legend-container {
flex: 1;
display: flex;
overflow: auto;
flex-direction: column;
overflow: hidden;
font-size: 12px;
text-align: left;
line-height: 18px;
box-sizing: border-box;
.legend-list{
display: flex;
overflow-y: auto;
}
.legend-item {
box-sizing: border-box;
padding: 0 8px;
@@ -396,7 +398,7 @@
cursor: pointer;
line-height: 20px;
color: $--color-text-primary;
width: 100%;
max-width: 100%;
display: flex;
align-items: center;
.legend-name{
@@ -404,9 +406,14 @@
text-overflow: ellipsis;
}
}
.legend--table-cell,.legend-item {
color: $--color-text-primary;
}
.legend-item, .legend--table-row {
&.legend-item--inactive, &.row--inactive {
color: $--color-text-secondary;
.legend--table-cell,.legend-item {
color: $--color-text-secondary !important;
}
.legend-shape {
background-color: $--background-color-1 !important;
}
@@ -425,7 +432,7 @@
vertical-align: middle;
color: $--color-text-regular !important;
}
.legend-item:hover {
.legend-item:not(.legendSelect):hover {
background-color: $--background-color-1;
cursor: pointer;
.nz-icon-override{
@@ -433,6 +440,24 @@
}
}
.legendSelect{
width: 100%;
cursor: unset;
overflow: unset;
span{
font-weight: bold;
cursor: pointer;
&:first-of-type{
margin-right: 6px;
}
&.legendSelect-disabled{
opacity: .6;
cursor: default;
color: $--color-text-secondary !important;
}
}
}
// 表格类型
.legend--table {
width: 100%;
@@ -461,11 +486,11 @@
position: sticky;
top: 0;
background-color: $--chart-background-color-base;
color:#33a2e5;
font-weight: bold;
font-size: 12px;
.legend--table-cell:not(:first-of-type) {
cursor: pointer;
color:#33a2e5;
font-size: 12px;
font-weight: bold;
}
.legend--table-cell{
white-space: nowrap;
@@ -1183,6 +1208,9 @@
width: 100%;
height: 2px;
}
.legend-list{
flex-wrap: wrap;
}
}
}
.panel-chart--fullscreen{
@@ -1205,8 +1233,9 @@
width: 2px;
height: 100%;
}
.legend-container{
.legend-list{
flex: 1;
flex-direction: column;
}
}
}
@@ -1222,8 +1251,9 @@
width: 2px;
height: 100%;
}
.legend-container{
.legend-list{
flex: 1;
flex-direction: column;
}
}
}

View File

@@ -94,16 +94,6 @@
height: calc(100% - 60px);
flex: 1;
background-color: $--background-color-empty;
.legend--table-cell,.legend-item {
color: $--color-text-primary;
}
.legend-container {
.legend--table-row.table-header {
.legend--table-cell {
color: #33a2e5;
}
}
}
}
.table-list-box {
height: 100%;

View File

@@ -6,7 +6,10 @@
<template v-if="isStatistics">
<div class="legend--table">
<div class="legend--table-row table-header">
<div class="legend--table-cell"></div>
<div class="legend--table-cell legendSelect">
<span @click="legendAll" :title="$t('dashboard.legendAll')">{{$t('dashboard.legendAll')}}</span><!--
--><span @click="legendInvert" :title="$t('dashboard.legendInvert')" :class="{'legendSelect-disabled':isGrey.every(item=>!item),}">{{$t('dashboard.legendInvert')}}</span>
</div>
<div v-for="statistics in chartInfo.param.legend.values" :key="statistics" class="legend--table-cell">
<span v-if="statisticsList.find(key=>key.value === statistics)" :title="$t(statisticsList.find(key=>key.value === statistics).label)">{{$t(statisticsList.find(key=>key.value === statistics).label)}}</span>
<span v-else>--</span>
@@ -66,39 +69,45 @@
</template>
<!-- 否则是普通形式 -->
<template v-else>
<!-- 左y轴legend -->
<div
v-for="(item, index) in legends"
:key="index"
v-show="!isTimeSeries||series[index].yAxisIndex!=1"
:class="{'legend-item--inactive': isGrey[index]}"
:title="item.alias ? item.alias : item.name"
class="legend-item"
@click="clickLegend(item.name, index)"
@mouseenter="hoverLegend(item.name, index,'highlight')"
@mouseleave="hoverLegend(item.name, index,'downplay')"
>
<i v-if="isTimeSeries&&series[index].yAxisIndex==0" :style="{color: item.color}" class="yAxis-icon nz-icon nz-icon-zuozongzhou"></i>
<span v-else :style="{background: item.color}" class="legend-shape"></span>
<span class="legend-name">{{item.alias ? item.alias : item.name.split('-')[0]}}</span>
<i class="nz-icon nz-icon-override" @click.stop="onCopy(item.alias ? item.alias : item.name.split('-')[0])" :title="$t('overall.copyText')"></i>
<div class="legend-item legendSelect">
<span @click="legendAll" :title="$t('dashboard.legendAll')">{{$t('dashboard.legendAll')}}</span><!--
--><span @click="legendInvert" :title="$t('dashboard.legendInvert')" :class="{'legendSelect-disabled':isGrey.every(item=>!item),}">{{$t('dashboard.legendInvert')}}</span>
</div>
<!-- y轴legend -->
<div
v-for="(item, index) in legends"
:key="index+'right'"
v-show="isTimeSeries&&series[index].yAxisIndex==1"
:class="{'legend-item--inactive': isGrey[index]}"
:title="item.alias ? item.alias : item.name"
class="legend-item"
@click="clickLegend(item.name, index)"
@mouseenter="hoverLegend(item.name, index,'highlight')"
@mouseleave="hoverLegend(item.name, index,'downplay')"
>
<i v-if="isTimeSeries&&series[index].yAxisIndex==1" :style="{color: item.color}" class="yAxis-icon nz-icon nz-icon-youzongzhou"></i>
<span v-else :style="{background: item.color}" class="legend-shape"></span>
<span class="legend-name">{{item.alias ? item.alias : item.name.split('-')[0]}}</span>
<i class="nz-icon nz-icon-override" @click.stop="onCopy(item.alias ? item.alias : item.name.split('-')[0])" :title="$t('overall.copyText')"></i>
<!-- y轴legend -->
<div class="legend-list">
<div
v-for="(item, index) in legends"
:key="index"
v-show="!isTimeSeries||series[index].yAxisIndex!=1"
:class="{'legend-item--inactive': isGrey[index]}"
:title="item.alias ? item.alias : item.name"
class="legend-item"
@click="clickLegend(item.name, index)"
@mouseenter="hoverLegend(item.name, index,'highlight')"
@mouseleave="hoverLegend(item.name, index,'downplay')"
>
<i v-if="isTimeSeries&&series[index].yAxisIndex==0" :style="{color: item.color}" class="yAxis-icon nz-icon nz-icon-zuozongzhou"></i>
<span v-else :style="{background: item.color}" class="legend-shape"></span>
<span class="legend-name">{{item.alias ? item.alias : item.name.split('-')[0]}}</span>
<i class="nz-icon nz-icon-override" @click.stop="onCopy(item.alias ? item.alias : item.name.split('-')[0])" :title="$t('overall.copyText')"></i>
</div>
<!-- 右y轴legend -->
<div
v-for="(item, index) in legends"
:key="index+'right'"
v-show="isTimeSeries&&series[index].yAxisIndex==1"
:class="{'legend-item--inactive': isGrey[index]}"
:title="item.alias ? item.alias : item.name"
class="legend-item"
@click="clickLegend(item.name, index)"
@mouseenter="hoverLegend(item.name, index,'highlight')"
@mouseleave="hoverLegend(item.name, index,'downplay')"
>
<i v-if="isTimeSeries&&series[index].yAxisIndex==1" :style="{color: item.color}" class="yAxis-icon nz-icon nz-icon-youzongzhou"></i>
<span v-else :style="{background: item.color}" class="legend-shape"></span>
<span class="legend-name">{{item.alias ? item.alias : item.name.split('-')[0]}}</span>
<i class="nz-icon nz-icon-override" @click.stop="onCopy(item.alias ? item.alias : item.name.split('-')[0])" :title="$t('overall.copyText')"></i>
</div>
</div>
</template>
</div>
@@ -144,6 +153,26 @@ export default {
}
},
methods: {
// 全选
legendAll () {
if (this.isGrey.every(item => !item)) {
return
}
this.isGrey = this.isGrey.map(() => {
return false
})
this.clickLegend(undefined, undefined, this.isGrey)
},
// 反选
legendInvert () {
if (this.isGrey.every(item => !item)) {
return
}
this.isGrey = this.isGrey.map((item) => {
return !item
})
this.clickLegend(undefined, undefined, this.isGrey)
},
legendResize (e) {
const placement = this.$lodash.get(this.chartInfo, 'param.legend.placement', 'bottom')
if (placement === 'bottom') {
@@ -152,6 +181,115 @@ export default {
this.horizontalResize(e, placement)
}
},
clickLegend (legendName, index, isGrey) {
/* 点击legend
* 1.当前如果是全高亮状态则全部置灰只留被点击的legend高亮
* 2.如果点击的是唯一高亮的legend则变为全高亮状态
* 3.否则只改变被点击的legend状态
* */
let highlightNum = 0 // 高亮数量
this.isGrey.forEach(g => {
if (!g) {
highlightNum++
}
})
const hasGrey = highlightNum < this.isGrey.length // 是否有置灰的
const curIsGrey = this.isGrey[index] // 当前legend的状态
const currentIsTheOnlyOneHighlight = !curIsGrey && highlightNum === 1 // 当前legend是否是目前唯一高亮的
if (this.chartInfo.type === 'treemap') {
this.clickLegendTreemap(legendName, index, hasGrey, currentIsTheOnlyOneHighlight, isGrey)
return
}
if (this.chartInfo.type === 'pie' || this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') {
this.clickLegendD3(legendName, index, hasGrey, currentIsTheOnlyOneHighlight, isGrey)
return
}
if (this.isTimeSeries) {
this.clickcTimeSeries(legendName, index, hasGrey, currentIsTheOnlyOneHighlight, isGrey)
}
},
clickcTimeSeries (legendName, index, hasGrey, currentIsTheOnlyOneHighlight, isGrey) {
const echarts = getChart(this.chartId)
if (echarts) {
if (isGrey) {
this.isGrey.forEach((item, index) => {
echarts.setSeries(index + 1, { show: !item, focus: false })
})
} else if (!hasGrey) { // 1.除当前legend外全置灰
echarts.series.forEach((seriesItem, sindex) => {
if (sindex > 0) {
echarts.setSeries(sindex, { show: false, focus: false })
}
})
echarts.setSeries(index + 1, { show: true, focus: false })
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
echarts.series.forEach((seriesItem, sindex) => {
if (sindex > 0) {
echarts.setSeries(sindex, { show: true, focus: false })
}
})
this.isGrey = this.isGrey.map(() => false)
} else {
echarts.setSeries(index + 1, { show: this.isGrey[index], focus: false })
this.$set(this.isGrey, index, !this.isGrey[index])
}
this.$emit('legendChange', this.isGrey)
}
},
clickLegendTreemap (legendName, index, hasGrey, currentIsTheOnlyOneHighlight, isGrey) {
const echarts = getChart(this.chartId)
if (echarts) {
let data = []
data = lodash.cloneDeep(this.series)
if (isGrey) {
this.isGrey = isGrey
} else if (!hasGrey) { // 1.除当前legend外全置灰
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
this.isGrey = this.isGrey.map(() => false)
} else { // 对应高亮
this.$set(this.isGrey, index, !this.isGrey[index])
}
data[0].data = data[0].data.filter((item, i) => !this.isGrey[i])
echarts.setOption({
series: data
})
}
},
clickLegendD3 (legendName, index, hasGrey, currentIsTheOnlyOneHighlight, isGrey) {
if (isGrey) {
this.isGrey = isGrey
} else if (!hasGrey) { // 1.除当前legend外全置灰
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
this.isGrey = this.isGrey.map(() => false)
} else { // 对应高亮
this.$set(this.isGrey, index, !this.isGrey[index])
}
this.$emit('clickLegendD3', this.isGrey)
},
hoverLegend (legendName, index, type) {
// legend 已经取消显示,鼠标悬浮,不开启 高亮效果
if (this.isGrey[index]) {
return false
}
if (this.chartInfo.type === 'pie' || this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') {
this.$emit('hoverLegendD3', legendName, index, type)
} else if (this.isTimeSeries) {
const echarts = getChart(this.chartId)
if (type == 'highlight') {
echarts.setSeries(index + 1, { focus: true })
} else {
echarts.setSeries(null, { focus: true })
}
} else {
getChart(this.chartId) && getChart(this.chartId).dispatchAction({
type: type,
name: legendName
})
}
},
verticalResize (e) {
const legendDom = this.$refs.legendDom
// 得到点击时dom的初始高度
@@ -212,140 +350,6 @@ export default {
document.onmousemove = null
}
},
clickLegend (legendName, index) {
/* 点击legend
* 1.当前如果是全高亮状态则全部置灰只留被点击的legend高亮
* 2.如果点击的是唯一高亮的legend则变为全高亮状态
* 3.否则只改变被点击的legend状态
* */
let highlightNum = 0 // 高亮数量
this.isGrey.forEach(g => {
if (!g) {
highlightNum++
}
})
const hasGrey = highlightNum < this.isGrey.length // 是否有置灰的
const curIsGrey = this.isGrey[index] // 当前legend的状态
const currentIsTheOnlyOneHighlight = !curIsGrey && highlightNum === 1 // 当前legend是否是目前唯一高亮的
const echarts = getChart(this.chartId)
if (this.chartInfo.type === 'bar') {
this.clickLegendBar(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight)
return
}
if (this.chartInfo.type === 'treemap') {
this.clickLegendTreemap(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight)
return
}
if (this.chartInfo.type === 'pie' || this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') {
this.clickLegendD3(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight)
return
}
if (echarts) {
if (!hasGrey) { // 1.除当前legend外全置灰
echarts.series.forEach((seriesItem, sindex) => {
if (sindex > 0) {
echarts.setSeries(sindex, { show: false, focus: false })
}
})
echarts.setSeries(index + 1, { show: true, focus: false })
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
echarts.series.forEach((seriesItem, sindex) => {
if (sindex > 0) {
echarts.setSeries(sindex, { show: true, focus: false })
}
})
this.isGrey = this.isGrey.map(() => false)
} else {
echarts.setSeries(index + 1, { show: this.isGrey[index], focus: false })
this.$set(this.isGrey, index, !this.isGrey[index])
}
this.$emit('legendChange', this.isGrey)
}
},
clickLegendBar (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) {
const echarts = getChart(this.chartId)
if (echarts) {
let data = []
const xAxis = {
data: []
}
data = lodash.cloneDeep(this.series)
if (!hasGrey) { // 1.除当前legend外全置灰
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
this.isGrey = this.isGrey.map(() => false)
} else { // 对应高亮
this.$set(this.isGrey, index, !this.isGrey[index])
}
data[0].data = data[0].data.filter((item, i) => !this.isGrey[i])
xAxis.data = data[0].data.map(item => {
if (this.chartInfo.param.text == 'all' || this.chartInfo.param.text == 'legend') {
return item.name
} else {
return ''
}
})
echarts.setOption({
series: data,
xAxis: {
data: xAxis.data
}
})
}
},
clickLegendTreemap (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) {
const echarts = getChart(this.chartId)
if (echarts) {
let data = []
const xAxis = {
data: []
}
data = lodash.cloneDeep(this.series)
if (!hasGrey) { // 1.除当前legend外全置灰
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
this.isGrey = this.isGrey.map(() => false)
} else { // 对应高亮
this.$set(this.isGrey, index, !this.isGrey[index])
}
data[0].data = data[0].data.filter((item, i) => !this.isGrey[i])
echarts.setOption({
series: data
})
}
},
clickLegendD3 (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) {
if (!hasGrey) { // 1.除当前legend外全置灰
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
this.isGrey = this.isGrey.map(() => false)
} else { // 对应高亮
this.$set(this.isGrey, index, !this.isGrey[index])
}
this.$emit('clickLegendD3', this.isGrey)
},
hoverLegend (legendName, index, type) {
// legend 已经取消显示,鼠标悬浮,不开启 高亮效果
if (this.isGrey[index]) {
return false
}
if (this.chartInfo.type === 'pie' || this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') {
this.$emit('hoverLegendD3', legendName, index, type)
} else if (this.isTimeSeries) {
const echarts = getChart(this.chartId)
if (type == 'highlight') {
echarts.setSeries(index + 1, { focus: true })
} else {
echarts.setSeries(null, { focus: true })
}
} else {
getChart(this.chartId) && getChart(this.chartId).dispatchAction({
type: type,
name: legendName
})
}
},
// 四舍五入保留2位小数不够位数则用0替补
keepTwoDecimalFull (num, type = 'left') {
let chartUnit = this.chartInfo.unit