//点击函数挂在window上
function myalert(val) {
var obj = JSON.parse(val);
console.log(12121, obj);
}
window.myalert = myalert;
//以下是tooltip配置,部分判断语句是本公司业务需要,可自行删除
tooltip: {
trigger: 'axis',
triggerOn: 'click',//点击显示
enterable: true,//可以进入
formatter: function (params) {
let returnData = '';
if (params.length == 1) {
returnData = params[0].name + ':' + params[0].value;
} else {
returnData = params[0].name + '</br>';
for (let i = 0; i < params.length; i++) {
if (params[i].seriesName === 'traceId') {
continue;
}
let indexColor = params[i].color;
returnData += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background:' + indexColor + '"></span>';
returnData += params[i].seriesName + ':' + params[i].value + '</br>';
}
}
/* avg/p99展示跳转链接 */
if (params[0].seriesName === ('avgValue' || 'p99Value')) {
const val = {
name: params[params.length - 1].name,
value: params[params.length - 1].value,
};
return (
returnData +
'<hr style="border:1 dashed #987cb9;" width="98%" size=5><div onclick="myalert(\'' +
JSON.stringify(val).replace(/"/g, '"') +
'\')" style="color:#000;text-decoration: none" id="btn-tooltip">详情></div>'
);
} else {
return returnData;
}
},
},
封装了一个initCharts
如果需要点击折线点之后调接口再渲染浮层,上面的代码便行不通了,只能用echart提供的点击事件+js实现,一下代码通用性不高,仅提供思路
import moment from 'moment';
import api from '@/api/map';
import * as echarts from 'echarts';
class Option {
tooltip = {
trigger: 'axis',
triggerOn: 'click',
enterable: true,
formatter: function (params) {
let returnData = '';
returnData = params[0].name + '</br>';
for (let i = 0; i < params.length; i++) {
let indexColor = params[i].color;
returnData += '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background:' + indexColor + '"></span>';
returnData += params[i].seriesName + ':' + params[i].value + '</br>';
}
// }
/* qpsValue不展示跳转链接
或者没有traceId
*/
const __tracrId__ = localStorage.getItem('__tracrId__');
if (params[0].seriesName === 'qpsValue' || !__tracrId__) {
return returnData;
} else {
const val = {
name: params[params.length - 1].name,
value: params[params.length - 1].value,
// type: x_list[0],
};
return returnData + '<hr style="border:1 dashed #987cb9;" width="98%" size=5><div οnclick="_myalert_(\'' + JSON.stringify(val).replace(/"/g, '"') + '\')" style="color:#000;text-decoration: none" id="btn-tooltip">pinpoint></div>';
}
},
};
constructor(data, x_list) {
this.colors = ['#00acc1', '#03a9f4', '#90caf9', '#4db6ac', '#00e676', '#ffab40', '#ca8622', '#3d5afe'];
this.randomHexColor = () => {
//随机生成十六进制颜色
return '#' + ('00000' + ((Math.random() * 0x1000000) << 0).toString(16)).substr(-6);
};
return {
// color: this.colors.sort(() => Math.random() - 0.5),
color: this.randomHexColor(),
dataZoom: [
{
show: true,
realtime: true,
start: 0,
end: 50,
},
{
type: 'inside',
realtime: true,
start: 0,
end: 50,
},
],
// tooltip: this.tooltip,
legend: {
data: x_list,
},
xAxis: {
type: 'category',
data: data.map(item => moment(item.timestamp).format('YYYYY/MM/DD HH:mm:ss').slice(1)),
},
yAxis: {
type: 'value',
},
series: x_list.map(name => {
return {
name: name,
type: 'line',
symbol: 'circle',
symbolSize: 5, //设定实心点的大小
data: data.map(item => item[name]),
};
}),
};
}
}
class Layer {
constructor(point) {
this.layer = null;
this.traceId = '';
this.setPosition(point);
this.initLayerStyle = `
width: 200px;
height: 100px;
position:absolute;top:${this._y - 50}px;
left:${this._x - 100}px;
background:#fff;
box-shadow:0 0 5px #666;
border-radius: 4px;
padding:10px;
color:#666`;
}
htmlContent() {
return `
<style>
.layer-time-point{
display:inline-block;
margin-right:5px;
border-radius:10px;
width:9px;
height:9px;
background:${this.color}
}
.layer-key-value{
margin:10px 0
}
.tracrId-none{
display:none
}
.tracrId-link-style{
text-decoration: underline;
color:blue
}
.tracrId-link-style:hover{
text-decoration: underline;
color:blue
}
</style>
<div><span class='layer-time-point' style="background:${this.color}"></span>${this.time}</div>
<div class='layer-key-value'>${this.key}:${this.value}</div>
<a class="${this.traceId ? 'tracrId-link-style' : 'tracrId-none'}"
href="https://pinpoint.lx.netease.com/transactionDetail/${this.traceId}/0/${this.traceId.split('^')[0]}/-1"
target="_blank">
pinpoint
</a>
`;
}
setPosition(point) {
this.time = point.name;
this.key = point.seriesName;
this.value = point.value;
this.color = point.color;
this._x = point.event.offsetX;
this._y = point.event.offsetY;
}
move(point, traceId) {
this.traceId = traceId;
this.setPosition(point);
this.layer.style.display = 'block';
this.layer.style.top = this._y - 50 + 'px';
this.layer.style.left = this._x - 100 + 'px';
this.layer.innerHTML = this.htmlContent();
}
create(chartId, traceId) {
this.traceId = traceId;
const layer = document.createElement('div');
console.log(this._x, this._y);
layer.style.cssText = this.initLayerStyle;
layer.innerHTML = this.htmlContent();
this.layer = layer;
layer.addEventListener('mouseleave', function () {
this.style.display = 'none';
});
document.getElementById(chartId).appendChild(layer);
}
}
export class InitCharts {
constructor() {
this.layerMap = {};
this.nameMap = {
qpsValue: 'qps',
avgValue: 'avg',
p99Value: 'p99',
failedCount: 'failed',
_4xxCount: '4xx',
_5xxCount: '5xx',
};
}
delObjectKey(obj, keys) {
const copy = Object.assign({}, obj);
for (let key in copy) {
for (let item of keys) {
if (item === key) {
delete copy[key];
}
}
}
return copy;
}
/**
* 初始化echart
*
* @param {string} selector 包含echart的容器
* @param {Array} data 数据
* @param {Array} chartsIds 展示的echart,对应data中的字段
* @param {Object} queryTraceParams 查询traceId所需参数:上下游,时间等
* @param {*} clickType 查询traceId所需参数:线段点击or节点点击
*/
init(selector, data, chartsIds, queryTraceParams, clickType) {
const chartBox = document.querySelector(selector);
chartBox.innerHTML = '';
for (let i = 0, len = chartsIds.length; i < len; i++) {
const dom = document.createElement('div');
dom.setAttribute('id', chartsIds[i]);
dom.style.cssText = 'margin:10px 0;border: 1px solid #b0bec5;width: 680px;height: 200px; position: relative;';
chartBox.appendChild(dom);
const myChart = echarts.init(dom);
const option = new Option(data, [chartsIds[i]]);
myChart.setOption(option);
/* 折线点击出layer */
myChart.on('click', point => {
const type = this.nameMap[point.seriesName];
const params = this.delObjectKey(queryTraceParams, ['fromTime', 'toTime']);
const time = moment(point.name).valueOf();
const value = String(point.value);
api.getTraceId({ ...params, time, value, type }, clickType).then(res => {
const traceId = res?.data?.data || '';
/* 有则移动,无则创建 */
if (this.layerMap[chartsIds[i]]) {
this.layerMap[chartsIds[i]].move(point, traceId);
return;
}
this.layerMap[chartsIds[i]] = new Layer(point);
this.layerMap[chartsIds[i]].create(chartsIds[i], traceId);
});
});
}
}
}