Merge branch 'dev-3.2' of git.mesalab.cn:nezha/nezha-fronted into dev-3.2

This commit is contained in:
zyh
2022-07-07 17:42:38 +08:00
11 changed files with 255 additions and 60 deletions

View File

@@ -1,5 +1,5 @@
<template>
<div v-my-loading="topologyLoading" class="overview">
<div v-loading="topologyLoading" class="overview">
<transition name = "el-zoom-in-center">
<div v-if="allProject&&allProject.length>0" style="width: 100%;height: 100%;position: relative">
<el-carousel :interval="5000" :trigger="'click'" arrow="hover">
@@ -8,6 +8,7 @@
<!-- <span class="project-name">{{item.name}}</span>-->
<topology
:fromOverView="true"
:from-chart="true"
:obj="item"
:ref="'topology' + index"
:topologyIndexF="isFullscreen?('screen'+chartInfo.id+'-'+index):(chartInfo.id+'-'+index)"

View File

@@ -28,6 +28,7 @@ import { formatScientificNotation, getMetricTypeValue } from '@/components/commo
import chartDataFormat from '@/components/chart/chartDataFormat'
import { initColor } from '@/components/chart/chart/tools'
import lodash from 'lodash'
import bus from "@/libs/bus";
export default {
name: 'chart-bar',
@@ -107,6 +108,13 @@ export default {
}
}
}
chartOption.yAxis.axisLabel.formatter = function (val, index) {
const value = formatScientificNotation(val, 6)
let chartUnit = self.chartInfo.unit
chartUnit = chartUnit || 2
const unit = chartDataFormat.getUnit(chartUnit)
return unit.compute(value, index, -1, 2)
}
chartOption.tooltip.formatter = this.formatterFunc
chartOption.tooltip.position = this.tooltipPosition
/* 使用setTimeout延迟渲染图表避免样式错乱 */

View File

@@ -43,7 +43,12 @@ const chartBarOption = {
}
},
yAxis: {
type: 'value'
type: 'value',
axisLabel: {
show: true,
fontSize: 10
// formatter: 动态生成
}
},
series: [
{

View File

@@ -304,6 +304,7 @@ export default {
}
const chartData = []
const params = {
t: this.chartInfo.id,
q: encodeURIComponent(JSON.stringify(q)),
stat: startTime,
end: endTime,
@@ -319,6 +320,16 @@ export default {
this.chartData = chartData
this.loading = false
})
// this.sendAjax('/stat', params).then(res => {
// if (res.code === 200) {
// chartData.push(res.data.result)
// } else {
// chartData.push({ error: res.msg || res.error || res })
// this.isError = true
// }
// this.chartData = chartData
// this.loading = false
// })
break
}
case 'misc': {
@@ -462,6 +473,41 @@ export default {
this.$message.error(res.msg)
}
})
},
sendAjax (url, params) {
// 构造表单数据
return new Promise(resolve => {
let nowUrl = url
Object.keys(params).forEach((key, index) => {
if (index == 0) {
nowUrl += '?' + key + '=' + params[key]
} else {
nowUrl += '&' + key + '=' + params[key]
}
})
const formData = new FormData()
formData.append('username', 'johndoe')
formData.append('id', 123456)
// 创建xhr对象
const xhr = new XMLHttpRequest()
// 设置xhr请求的超时时间
xhr.timeout = 3000
// 设置响应返回的数据格式
xhr.responseType = ''
// 创建一个 post 请求,采用异步
xhr.open('get', 'http://192.168.44.100/' + nowUrl, true)
xhr.setRequestHeader('Authorization', localStorage.getItem('nz-token'));
// 注册相关事件回调处理函数
xhr.onload = function (e) {
if (this.status == 200 || this.status == 304) {
// alert(this.responseText)
resolve(JSON.parse(this.responseText))
}
}
xhr.onerror = function(e) { console.log(e) };
// 发送数据
xhr.send()
})
}
},
watch: {

View File

@@ -327,7 +327,7 @@ import {
myCubec,
myCubeAnchors
} from '../project/L5/services/canvas.js'
import { getTopology, setTopology } from '../js/common'
import {getTopology, getTopologyImg, setTopology, setTopologyImg} from '../js/common'
import CanvasProps from '../project/L5/CanvasProps'
import topologyTopTool from '../project/L5/topologyTopTool'
import popDataMain from '../project/popData/Main'
@@ -1744,13 +1744,27 @@ export default {
res.data.list.forEach((item, index) => {
item.imageName = item.name
delete item.name
const nowImage = getTopologyImg(item.id) ? JSON.parse(getTopologyImg(item.id)) : ''
if (nowImage && nowImage.data) {
console.log(nowImage)
promiseArr.push(nowImage)
} else {
promiseArr.push(this.dealImg(`monitor/project/topo/icon/${item.id}/1`))
}
imgArr.push({ ...item })
})
Promise.all(promiseArr).then((res2, header) => {
this.iconArray = [...res.data.list]
this.iconArray.forEach((item, index) => {
item.image = res2[index].data
const nowImage = getTopologyImg(item.id) ? JSON.parse(getTopologyImg(item.id)) : ''
if (!nowImage || (nowImage && !nowImage.data)) {
setTopologyImg(item.id, JSON.stringify({
data: res2[index].data,
width: res2[index].width,
height: res2[index].height
}))
}
const group = this.tools.find(tool => tool.group === item.unit)
if (group) {
group.children.push({
@@ -1801,7 +1815,12 @@ export default {
}
imgidList.forEach((item, index) => {
if (item.data.imageId && imageAllId.data.list.find(image => item.data.imageId === image.id)) {
const nowImage = getTopologyImg(item.data.imageId) ? JSON.parse(getTopologyImg(item.data.imageId)) : ''
if (nowImage && nowImage.data) {
promiseArr.push(nowImage)
} else {
promiseArr.push(this.dealImg(`monitor/project/topo/icon/${item.data.imageId}/1`))
}
} else if (item.data.imageId) {
promiseArr.push(imgDefault)
} else {
@@ -1817,6 +1836,14 @@ export default {
this.iconArray.forEach((item, index) => {
if (item.id) {
item.image = res2[index].data
const nowImage = getTopologyImg(item.id) ? JSON.parse(getTopologyImg(item.id)) : ''
if (!nowImage || (nowImage && !nowImage.image)) {
setTopologyImg(item.id, JSON.stringify({
data: res2[index].data,
width: res2[index].width,
height: res2[index].height
}))
}
}
})
this.imgInit = true

View File

@@ -761,7 +761,6 @@ export default {
document.body.style.height = 'auto'
// document.getElementsByTagName('html')[0].style.overflow = 'visible'
const position = dom.getBoundingClientRect()
console.log(position)
this.getPdf(dom, -1 * position.left, -1 * position.top,this.searchTime)
// this.getPdf(dom, 0, 0)
}, 2000)

View File

@@ -34,6 +34,7 @@ export function getHexagon (key) {
const topologyCache = {}
export function getTopology (key) {
// console.log(topologyCache, 'topologyCache')
return topologyCache[`topology${key}`]
}
@@ -41,6 +42,18 @@ export function setTopology (key, value) {
topologyCache[`topology${key}`] = value
}
// const topologyImgList = localStorage.getItem('nz-imgList') ? JSON.parse(localStorage.getItem('nz-imgList')) : {}
export function getTopologyImg (key) {
// console.log(topologyCache, 'topologyCache')
// console.log(localStorage.getItem('nz-img-' + key), !localStorage.getItem('nz-img-' + key))
return localStorage.getItem('nz-img-' + key)
}
export function setTopologyImg (key, img) {
localStorage.setItem('nz-img-' + key, img)
}
export function setHexagon (key, value) {
hexagonCache[`hexagon${key}`] = value
}

View File

@@ -31,7 +31,6 @@ export default {
// a4纸的尺寸[595.28,841.89]html页面生成的canvas在pdf中图片的宽高
const imgWidth = 595.28
const imgHeight = 592.28 / contentWidth * contentHeight
console.log(canvas)
// canvas.paddingTop = '30px'
const pageDataImg = canvas.toDataURL('image/jpeg', 1.0)
const img = new Image()

View File

@@ -157,7 +157,7 @@
<!--画布部分-->
<div :id="'topology-canvas' + topologyIndexF" :ref="'topology-canvas'+ topologyIndexF" class="full" @contextmenu="onContextMenu($event)"></div>
<!--设置属性-->
<div v-if="editTopologyFlag&&toolShow.attr" class="props">
<div v-if="editTopologyFlag&&toolShow.attr && !fromOverView" class="props">
<canvas-props ref="CanvasProps"
:index="topologyIndex"
:imgArr = 'tools'
@@ -170,7 +170,7 @@
@notModuleIDArrChange="notModuleIDArrChange">
</canvas-props>
</div>
<div class="context-menu" v-if="contextmenu.left && editTopologyFlag && 0" :style="this.contextmenu">
<div class="context-menu" v-if="contextmenu.left && editTopologyFlag && 0 && !fromOverView" :style="this.contextmenu">
<CanvasContextMenu :index="topologyIndexF" :props.sync="props"></CanvasContextMenu>
</div>
<!--所有节点上的小图标-->
@@ -351,7 +351,7 @@ import {
myCubec,
myCubeAnchors
} from './L5/services/canvas.js'
import { getTopology, setTopology } from '../js/common'
import { getTopology, setTopology, getTopologyImg, setTopologyImg } from '../js/common'
import CanvasProps from './L5/CanvasProps'
import topologyTopTool from './L5//topologyTopTool'
import CanvasContextMenu from './L5/CanvasContextMenu'
@@ -439,6 +439,7 @@ export default {
timer: null, // 处理project短时间呢频繁变更的定时器
timer2: null, // 处理平移画布显示iconState的定时器
timer3: null, // 处理tooltip的显示定时器
timer4: null,
nodesArr: [],
notModuleIDArr: [],
popData: [
@@ -660,10 +661,10 @@ export default {
this.chartGetData = []
const axiosArr = []
const promiseArr = []
const pensPromise = (pen, arr, index) => {
let pensPromise = (pen, arr, index) => {
return new Promise((resolve, reject) => {
Promise.all(arr).then((res) => {
this.chartGetData[index].res = this.computeData(res, pen.data.aggregation, pen)
this.chartGetData[index].res = JSON.parse(JSON.stringify(this.computeData(res, pen.data.aggregation, pen)))
this.setAnimation(pen, this.chartGetData[index].res)
resolve()
})
@@ -734,6 +735,7 @@ export default {
// getTopology(this.topologyIndex).fitView();
this.oldTopologyData = JSON.stringify(getTopology(this.topologyIndex).data)
this.getNodesArr()
pensPromise = null
})
},
dateChange () {
@@ -821,9 +823,10 @@ export default {
}
this.projectInfoShow = true
this.projectAlertShow = true
this.saveData = { ...data }
this.saveData = JSON.parse(JSON.stringify(data))
this.topologyInfo.name = this.obj.name
resolve(data)
data = null
} else {
if (data.data) {
this.topologyInfo = {
@@ -846,7 +849,7 @@ export default {
const arr = data.pens.filter(item => !item.type)
this.addNodeInit(arr)
}
let timer = setInterval(() => {
this.timer4 = setInterval(() => {
if (!this.imgInit) {
return
}
@@ -866,13 +869,13 @@ export default {
item.image = img ? img.image : imgDefault
}
if (item.type === 0) {
promiseArr.push(this.$get('stat/module/abnormal', { moduleId: item.data.moduleId }))
// promiseArr.push(this.$get('stat/module/abnormal', { moduleId: item.data.moduleId }))
item.data.state = {}
item.data.state.asset = false
item.data.state.endpoint = false
item.data.state.alert = false
} else {
promiseArr.push({ type: 1 })
// promiseArr.push({ type: 1 })
item.data.state = {}
item.data.state.asset = false
item.data.state.endpoint = false
@@ -897,13 +900,13 @@ export default {
data.bkColor = '#FFFFFF00'
}
Promise.all(promiseArr).then(res => {
res.forEach((response, index) => {
const item = data.pens[index]
res[0].data.list.forEach((module, index) => {
const item = data.pens.find(pens => module.id === pens.data.moduleId)
if (item.type === 0 && item.data.state && res[index].data.list.length) {
item.data.state.error = item.data.error = !res[index].data.list[0].state
item.data.state.asset = !!res[index].data.list[0].asset
item.data.state.alert = !!res[index].data.list[0].alert
item.data.state.endpoint = !!res[index].data.list[0].endpoint
item.data.state.error = item.data.error = !module.state
item.data.state.asset = !!module.asset
item.data.state.alert = !!module.alert
item.data.state.endpoint = !!module.endpoint
} else {
item.data.state = {
error: false,
@@ -913,17 +916,17 @@ export default {
}
}
})
this.saveData = { ...data }
this.saveData = JSON.parse(JSON.stringify(data))
resolve(data)
clearInterval(timer)
timer = null
clearInterval(this.timer4)
this.timer4 = null
}).catch(res => {
this.saveData = { ...data }
this.saveData = JSON.parse(JSON.stringify(data))
resolve(data)
clearInterval(timer)
timer = null
clearInterval(this.timer4)
this.timer4 = null
})
}, 100)
}, 2000)
}
})
})
@@ -1056,7 +1059,7 @@ export default {
this.$get('/monitor/module?pageSize=-1&projectIds=' + this.obj.id).then(response => {
if (response.code === 200) {
this.projectInfo.loading = false
this.allModules = response.data.list
this.allModules = JSON.parse(JSON.stringify(response.data.list))
this.modulesDiff()
}
})
@@ -1064,9 +1067,10 @@ export default {
getNodesArr () {
if (!getTopology(this.topologyIndex)) return
let arr = []
this.offsetX = getTopology(this.topologyIndex).data.x
this.offsetY = getTopology(this.topologyIndex).data.y
this.nodesArr = getTopology(this.topologyIndex).data.pens.filter(item => {
arr = getTopology(this.topologyIndex).data.pens.filter(item => {
if (!item.data) {
item.data = {
moduleId: '',
@@ -1081,7 +1085,14 @@ export default {
return item.type === 0
})
// 打开动画 是否更新顶部图标
this.nodesArr = arr.map(item => {
return {
rect: item.rect,
data: item.data
}
})
this.nodesArr = JSON.parse(JSON.stringify(this.nodesArr))
arr = null
},
modelTopClick (item, index) {
@@ -1288,9 +1299,9 @@ export default {
this.tooltipPosition.show = false
setTimeout(() => {
this.tooltipPosition.show = true
const ePosition = window.ePosition
const boxWidth = document.getElementsByClassName('page')[0].offsetWidth
const boxHeight = document.getElementsByClassName('page')[0].offsetHeight
let ePosition = window.ePosition
let boxWidth = document.getElementsByClassName('page')[0].offsetWidth
let boxHeight = document.getElementsByClassName('page')[0].offsetHeight
this.tooltipPosition.left = ePosition.layerX + 20
this.tooltipPosition.top = ePosition.layerY
this.$nextTick(() => {
@@ -1306,6 +1317,9 @@ export default {
this.tooltipPosition.top = ePosition.layerY - this.$refs.topoTooltip.offsetHeight
}
}
ePosition = null
boxWidth = null
boxHeight = null
})
}, 100)
break
@@ -1432,22 +1446,26 @@ export default {
}
break
case 'resize': {
const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
let dom = document.getElementById('topology-canvas' + this.topologyIndexF)
let domRect = dom ? dom.getBoundingClientRect() : {}
if (getTopology(this.topologyIndex)) {
getTopology(this.topologyIndex).canvasPos = domRect
}
dom = null
domRect = null
break
}
case 'scale': {
if (this.$refs.topTool) {
this.$refs.topTool.scaleNum = parseInt(data * 100)
}
const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
let dom = document.getElementById('topology-canvas' + this.topologyIndexF)
let domRect = dom ? dom.getBoundingClientRect() : {}
if (getTopology(this.topologyIndex)) {
getTopology(this.topologyIndex).canvasPos = domRect
}
dom = null
domRect = null
break
}
case 'locked': {
@@ -1718,18 +1736,33 @@ export default {
this.$get('monitor/project/topo/icon').then(res => {
this.imgageLoading = true
this.tools = [...Tools]
const imgArr = []
const promiseArr = []
let imgArr = []
let promiseArr = []
res.data.list.forEach((item, index) => {
item.imageName = item.name
delete item.name
const nowImage = getTopologyImg(item.id) ? JSON.parse(getTopologyImg(item.id)) : ''
if (nowImage && nowImage.data) {
console.log(nowImage)
promiseArr.push(nowImage)
} else {
promiseArr.push(this.dealImg(`monitor/project/topo/icon/${item.id}/1`))
}
imgArr.push({ ...item })
})
Promise.all(promiseArr).then((res2, header) => {
console.log(res2, 'Promise')
this.iconArray = [...res.data.list]
this.iconArray.forEach((item, index) => {
item.image = res2[index].data
const nowImage = getTopologyImg(item.id) ? JSON.parse(getTopologyImg(item.id)) : ''
if (!nowImage || (nowImage && !nowImage.data)) {
setTopologyImg(item.id, JSON.stringify({
data: res2[index].data,
width: res2[index].width,
height: res2[index].height
}))
}
const group = this.tools.find(tool => tool.group === item.unit)
if (group) {
group.children.push({
@@ -1769,18 +1802,25 @@ export default {
this.imgInit = true
this.imgageLoading = false
imgArr = null
promiseArr = null
})
})
} else {
this.imgageLoading = true
this.$get('monitor/project/topo/icon').then((imageAllId) => {
const promiseArr = []
let promiseArr = []
if (!imageAllId || !imageAllId.data) {
return
}
imgidList.forEach((item, index) => {
if (item.data.imageId && imageAllId.data.list.find(image => item.data.imageId === image.id)) {
const nowImage = getTopologyImg(item.data.imageId) ? JSON.parse(getTopologyImg(item.data.imageId)) : ''
if (nowImage && nowImage.data) {
promiseArr.push(nowImage)
} else {
promiseArr.push(this.dealImg(`monitor/project/topo/icon/${item.data.imageId}/1`))
}
} else if (item.data.imageId) {
promiseArr.push(imgDefault)
} else {
@@ -1796,10 +1836,20 @@ export default {
this.iconArray.forEach((item, index) => {
if (item.id) {
item.image = res2[index].data
const nowImage = getTopologyImg(item.id) ? JSON.parse(getTopologyImg(item.id)) : ''
if (!nowImage || (nowImage && !nowImage.image)) {
setTopologyImg(item.id, JSON.stringify({
data: res2[index].data,
width: res2[index].width,
height: res2[index].height
}))
}
}
})
this.imgInit = true
this.imgageLoading = false
imgidList = null
promiseArr = null
})
})
}
@@ -2037,10 +2087,12 @@ export default {
this.editTopologyFlag = false
this.$nextTick(() => {
getTopology(this.topologyIndex).lock(1)
const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
let dom = document.getElementById('topology-canvas' + this.topologyIndexF)
let domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect
this.$store.commit('setShowTopoScreen', this.topoScreenState)
dom = null
domRect = null
})
this.reload()
},
@@ -2112,7 +2164,7 @@ export default {
winResize () {
setTimeout(() => {
const domRect = document.getElementById('topology-canvas' + this.topologyIndex).getBoundingClientRect()
let domRect = document.getElementById('topology-canvas' + this.topologyIndex).getBoundingClientRect()
getTopology(this.topologyIndex).canvasPos = domRect
if (this.fromOverView) {
getTopology(this.topologyIndex).open(this.oldTopologyData)
@@ -2135,6 +2187,7 @@ export default {
getTopology(this.topologyIndex).resize()
getTopology(this.topologyIndex).centerView()
this.getNodesArr()
domRect = null
}, 500)
},
contextmenuNone () {
@@ -2183,18 +2236,6 @@ export default {
}
return flag
},
modelPopError (pen, state) {
if (item.id === 'asset' && this.activeModelItem.assetError) {
return true
}
if (item.id === 'alert' && this.activeModelItem.alertError) {
return true
}
if (item.id === 'endpoint' && this.activeModelItem.endpointError) {
return true
}
return false
},
redoIndexChange (index) {
this.redoIndex = index
},
@@ -2254,9 +2295,20 @@ export default {
clearInterval(this.timer)
this.timer = null
}
if (this.timer4) {
clearInterval(this.timer4)
this.timer4 = null
}
if (getTopology(this.topologyIndex)) {
window.topology = null
window.Le5leTopologyPoint = null
window.topologyPoint = null
window.topologyRect = null
getTopology(this.topologyIndex).off('contextmenu', this.onContextMenu)
getTopology(this.topologyIndex).destroy()
Object.keys(getTopology(this.topologyIndex)).forEach(key => {
getTopology(this.topologyIndex)[key] = null
})
setTopology(this.topologyIndex, null)
}
if (document.getElementById('topology-canvas' + this.topologyIndexF)) {

View File

@@ -42,6 +42,16 @@
@click="saveChart">
{{$t('dashboard.metric.saveChart')}}
</button>
<button v-else
id="explore-save-chart-logs"
v-has="'main_add'"
:class="{'nz-btn-disabled btn-disabled-cursor-not-allowed' : saveDisabled}"
:disabled="saveDisabled"
class="top-tool-btn top-tool-btn--text"
type="button"
@click="saveChartLogs">
{{$t('dashboard.metric.saveChart')}}
</button>
</div>
</div>
<div id="explore-promql-box" class="top-tools" style="padding-top: 0; flex-wrap: wrap">
@@ -981,6 +991,43 @@ export default {
this.chartData = chart
this.rightBox.show = true
},
saveChartLogs () {
const chart = {
id: '',
name: '',
panelName: '',
span: 4,
height: 4,
unit: 2,
groupId: -1,
updateBy: 1,
updateAt: '2022-05-18 07:51:45',
type: 'log',
weight: 6,
param: { limit: 100 },
pid: null,
buildIn: 0,
seq: null,
x: 0,
y: 1.93,
elements: [],
children: null,
chartNums: null,
asset: null,
varType: null,
varId: null,
varName: null,
datasource: 'logs',
enable: { thresholds: false, legend: true, valueMapping: false },
sync: 0,
remark: ''
}
this.expressions.forEach((exp, index) => {
chart.elements.push({ expression: exp, legend: '', type: 'expert', id: '', name: 'A' })
})
this.chartData = chart
this.rightBox.show = true
},
createSuccess (panel) { // 添加chart成功
this.$confirm(this.$t('dashboard.metric.goPanelTip'), this.$t('tip.saveSuccess'), {
confirmButtonText: this.$t('tip.yes'),

View File

@@ -822,7 +822,6 @@ export default {
this.htmlTitle = this.showPanel.name
this.scrollbarWrap.scrollTop = this.scrollbarWrap.scrollHeight
this.$refs.chartList.onScroll(this.scrollbarWrap.scrollTop)
console.log(dom.children)
// const div = document.createElement('div')
// div.setAttribute('class', 'el-loading-spinner')
// div.innerText = '12321312312312321'
@@ -848,7 +847,6 @@ export default {
document.getElementsByClassName('left-menu')[0].style.height = '100vh'
// document.getElementsByTagName('html')[0].style.overflow = 'visible'
const position = dom.getBoundingClientRect()
console.log(position)
this.getPdf(dom, -1 * position.left, -1 * position.top, this.searchTime)
// this.getPdf(dom, 0, 0)
}, 2000)