This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
nezha-nezha-fronted/nezha-fronted/src/components/page/dashboard/overview/chart.vue

337 lines
10 KiB
Vue
Raw Normal View History

<template>
2020-04-22 19:45:10 +08:00
<div class="chart-room" @mouseenter="mouseEnterChart" @mouseleave="mouseLeaveChart">
<loading ref="loading"></loading>
<div class="chart-header">{{chartTitle}}</div>
<div class="chart-body" ref="chartBody" :id="chartId" ></div>
<div class="legend-container" id="legendArea" ref="legendArea" v-show="legend.length>0" v-scrollBar:legend>
<div v-for="(item, index) in legend" :title="item.alias?item.alias:item.name" @click="clickLegend(item.name,index)" class="legend-item" :class="{'ft-gr':item.isGray}" :key="'legend_' + item.name+'_'+index">
<span class="legend-shape" :style="{background:(item.isGray?'#D3D3D3':getBgColor(index))}"></span>{{item.alias?item.alias:item.name}}
<br/>
</div>
</div>
</div>
</template>
<script>
import echarts from 'echarts';
import chartDataFormat from "../../../charts/chartDataFormat";
import loading from "../../../common/loading";
import chartConfig from './chartConfig'
import bus from "../../../../libs/bus";
import EleResize from "../../../common/js/divResize";
import {randomcolor} from "../../../common/js/radomcolor/randomcolor";
export default {
name: "chart",
components:{
'loading':loading,
},
props:{
name: {type: String,default:'chart'},
2020-03-24 13:19:18 +08:00
chartTitle:{type:String},
2020-04-22 19:45:10 +08:00
showToolbox:{type:Boolean,default:true},
2020-03-24 13:19:18 +08:00
chartType:{type:String,default:'line'},
tooltipFormatter:Function,
yAxisFormatter:Function,
map:{}
},
data(){
return {
chart:null,
option:null,
chartId: this.name + '-'+this.guid()+'-'+new Date().getTime(),
legend:[],
colors:chartConfig.getBgColorList(),
}
},
created() {
2020-04-22 19:45:10 +08:00
this.option=chartConfig.getOption(this.chartType);
if(this.showToolbox == false){
this.option.grid.top=10;
}
},
methods:{
modifyOption:function(target,name,obj){
if(!this.option){
this.option=chartConfig.getOption(this.chartType);
}
this.$set(this.option[target],name,obj)
},
setLegend:function(legend){
this.legend=legend;
this.resize();
},
setSeries:function(series){
if(!this.chart){
2020-04-23 22:27:41 +08:00
this.chart = echarts.init(document.getElementById(this.chartId));
}
2020-04-23 22:27:41 +08:00
this.series = series;
2020-03-24 13:19:18 +08:00
if(this.chartType == 'map'){
if(this.map){
echarts.registerMap(this.map.name,this.map.geoJson);
chartConfig.setMap(this.map.name);
}else{
console.error('map chart need map data');
}
2020-03-24 13:19:18 +08:00
}
if(!this.option){
this.option=chartConfig.getOption(this.chartType);
}
this.modifyOption('tooltip','position',this.defaultTooltipPosition)
if (this.tooltipFormatter) {
this.modifyOption('tooltip', 'formatter', this.tooltipFormatter)
} else {
this.modifyOption('tooltip', 'formatter', this.defaultTooltipFormatter)
}
if(this.chartType == 'line'){
if(this.yAxisFormatter){
this.modifyOption('yAxis','formatter',this.yAxisFormatter)
}else{
this.modifyOption('yAxis','formatter',this.defaultYAxisFormatter)
}
}
console.log(this.option)
2020-03-24 20:25:16 +08:00
this.$set(this.option,'series',this.series);
this.chart.clear();
this.chart.setOption(this.option)
this.resize();
},
resizeChart:function(width,height){
if(this.chart){
this.chart.resize({width:width,height:height});
}
},
resize:function(){
if(this.chart){
2020-04-22 19:45:10 +08:00
let height=this.$el.clientHeight;
let width=this.$el.clientWidth;
if(this.chartTitle){
height = height - 20;
}
if(this.legend && this.legend.length>0){
height = height - 80;
}
this.chart.resize({width:width,height:height});
}
},
2020-04-22 19:45:10 +08:00
mouseEnterChart(){
if (this.chart&&this.showToolbox) {
this.chart.setOption({
toolbox: {
show:true,
}
})
}
},
mouseLeaveChart(){
if (this.chart) {
this.chart.setOption({
toolbox: {
show:false,
}
})
}
},
getBgColor:function(index){
let color=this.colors[index];
return color;
},
clickLegend(legendName,index){
let curIsGrey=this.legend[index].isGray;
if(this.chart){
this.legend.forEach((item,i)=>{
let isGrey = item.isGray;
if(index != i){ //不是当前点击的
if(!curIsGrey && !isGrey){
this.chart.dispatchAction({
type: 'legendUnSelect',
name: item.name
});
item.isGray=true;
}else if(!curIsGrey && isGrey){
this.chart.dispatchAction({
type: 'legendSelect',
name: item.name
});
item.isGray=false;
}else{
this.chart.dispatchAction({
type: 'legendUnSelect',
name: item.name
});
item.isGray=true
}
}else {//当前点击的
this.chart.dispatchAction({
type: 'legendSelect',
name: item.name
});
if(item.isGray === true){
item.isGray = false;
}
}
});
}
},
defaultTooltipPosition:function(point,params,dom,rect,size){
dom.style.transform = "translateZ(0)";
//提示框位置
var x=0;
var y=0;
//当前鼠标位置
var pointX = point[0];
var pointY = point[1];
//外层div大小
var viewWidth = size.viewSize[0];
var viewHeight = size.viewSize[1];
//提示框大小
var boxWidth = size.contentSize[0];
var boxHeight = size.contentSize[1];
let chartDom = document.getElementById(this.chartId);
if(chartDom){
let parTop = chartDom.offsetTop;
let parLeft = chartDom.offsetLeft;
let parent = chartDom.parentElement;
let parClientHeight = parent.clientHeight;//可视高度
let parClientWidth = parent.clientWidth;//可视宽度
let parScrollTop = parent.scrollTop;
if((parClientWidth-pointX-parLeft-20)>=boxWidth){//说明鼠标在左边放不下提示框
x=pointX+10;
}else{
x = pointX - boxWidth;
}
if((parClientHeight-pointY-(parTop-parScrollTop)-20)>=boxHeight){//说明鼠标上面放不下提示框
y = pointY+10;
}else {
y = pointY-boxHeight;
}
return [x,y];
}else {
x = pointX - boxWidth;
y = pointY+10;
return [x,y];
}
},
defaultTooltipFormatter:function(params){
let str = `<div>`;
params.forEach((item, i) => {
if(i===0){
let value=bus.computeTimezone(item.data[0])
let t_date = new Date(value);
str += [t_date.getFullYear(), t_date.getMonth() + 1, t_date.getDate()].join('-') + " "
+ [t_date.getHours(), t_date.getMinutes(),t_date.getSeconds()].join(':');
str +=`<br/>`;
}
let alias=this.queryAlias(item.seriesName)
let val = Number(item.data[1]);
str += `<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">`;
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${alias?alias:item.seriesName}: </div>`;
str += `<div style="padding-left: 10px;">`;
str += chartDataFormat.getUnit(5).compute(val,null,2);
str += `</div>`;
str += `</div>`;
});
str +=`</div>`;
return str;
},
queryAlias:function(seriesName){
let alias=null;
if(this.legend&&this.legend.length>0){
let tempLegend=this.legend.find((item)=>{return item.name == seriesName});
if(tempLegend){
alias=tempLegend.alias;
}
}
return alias;
},
defaultYAxisFormatter:function(value,index){
let unit=chartDataFormat.getUnit(5);
return unit.compute(value,index);
},
setRandomColors:function(num){//当线条过多,默认颜色数量不够时须使用此方法,num 颜色的数量通常传递series的length即可
let colors=[];
for(let i=0;i<num;i++){
colors.push(randomcolor())
}
this.colors=Object.assign([],colors)
this.$set(this.option,'color',colors)
console.log(this.option)
},
startLoading:function(){
this.$refs.loading.startLoading();
},
endLoading:function(){
this.$refs.loading.endLoading();
},
guid() {
function S4() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
}
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
},
},
mounted() {
this.chart=echarts.init(document.getElementById(this.chartId));
EleResize.on(this.$el,this.resize);
},
watch:{
},
destroyed() {
if(this.chart){
this.chart.clear();
}
}
}
</script>
<style scoped>
.chart-room{
2020-04-22 19:45:10 +08:00
width: 100%;
height: 100%;
position: relative;
}
.chart-room .legend-container{
width: calc(100% - 30px);
/*max-height:80px;*/
/*min-height:40px;*/
height: 80px;
font-size:12px;
text-align:left;
margin:0 auto;
line-height: 18px;
position: relative;
}
.chart-room .legend-container .legend-item{
text-overflow:ellipsis;
white-space:nowrap;
width:100%;
overflow-x:hidden;
cursor:pointer;
display:inline-block;
float:left;
line-height: 20px;
}
.chart-room .ft-gr{
color:lightgray;
}
.chart-room .legend-shape{
display:inline-block;
margin-right:5px;
border-radius:10px;
width:15px;
height:5px;
vertical-align: middle;
}
</style>