feat: 新增 chartRightBox

This commit is contained in:
zhangyu
2021-11-30 16:39:21 +08:00
parent 8bdfd769ec
commit a69105d783
17 changed files with 1159 additions and 10 deletions

View File

@@ -56,7 +56,7 @@
padding: 0 30px; padding: 0 30px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
box-sizing: border-box;
.el-textarea__inner { .el-textarea__inner {
padding: 5px 70px 4px 15px; padding: 5px 70px 4px 15px;
} }

View File

@@ -0,0 +1,16 @@
.right-box__container{
.chart-config{
.el-form {
padding-top: 0px;
}
.chart-title .nz-icon-arrow-down{
display: inline-block;
transition: transform .3s;
}
.chart-title .nz-icon-arrow-down.is-active{
transform: rotate(
-90deg
);
}
}
}

View File

@@ -43,6 +43,7 @@
@import './common/rightBox/locationCascader.scss'; @import './common/rightBox/locationCascader.scss';
@import './common/rightBox/menuBox.scss'; @import './common/rightBox/menuBox.scss';
@import './common/rightBox/moduleBox.scss'; @import './common/rightBox/moduleBox.scss';
@import './common/rightBox/chartRightBox/chartRightBox';
@import './common/table/alert/alertMessageTable.scss'; @import './common/table/alert/alertMessageTable.scss';
@import './common/table/alert/alertRuleTable.scss'; @import './common/table/alert/alertRuleTable.scss';
@import './common/table/alert/alertSilenceTable.scss'; @import './common/table/alert/alertSilenceTable.scss';
@@ -87,6 +88,7 @@
@import './page/dashboard/panel.scss'; @import './page/dashboard/panel.scss';
@import './page/monitor/project/project.scss'; @import './page/monitor/project/project.scss';
@import 'common/v-selectpagenew/selectpage.scss'; @import 'common/v-selectpagenew/selectpage.scss';
@import "common/paramBpx/paramBox.scss"; @import "common/paramBpx/paramBox.scss";

View File

@@ -8,6 +8,13 @@
:chart-info="chartInfo" :chart-info="chartInfo"
:chart-option="chartOption" :chart-option="chartOption"
></chart-time-series> ></chart-time-series>
<!-- <chartHexagon-->
<!-- :ref="'chart'+chartInfo.id"-->
<!-- v-if="isHexagonFigure(chartInfo.type)"-->
<!-- :chart-data="chartData"-->
<!-- :chart-info="chartInfo"-->
<!-- :chart-option="chartOption"-->
<!-- ></chartHexagon>-->
</template> </template>
</div> </div>
</template> </template>
@@ -30,7 +37,8 @@ import chartTimeSeries from './chart/chartTimeSeries'
import chartTreemap from './chart/chartTreemap' import chartTreemap from './chart/chartTreemap'
import chartUrl from './chart/chartUrl' import chartUrl from './chart/chartUrl'
import chartValue from './chart/chartValue' import chartValue from './chart/chartValue'
import { getOption, isTimeSeries } from './chart/tools' import chartHexagon from './chart/chartHexagon'
import { getOption, isTimeSeries, isHexagonFigure } from './chart/tools'
import lodash from 'lodash' import lodash from 'lodash'
export default { export default {
@@ -52,7 +60,8 @@ export default {
chartTimeSeries, chartTimeSeries,
chartTreemap, chartTreemap,
chartUrl, chartUrl,
chartValue chartValue,
chartHexagon
}, },
props: { props: {
chartInfo: Object, chartInfo: Object,
@@ -76,7 +85,11 @@ export default {
} }
}, },
methods: { methods: {
isTimeSeries isTimeSeries,
isHexagonFigure,
resize () {
this.$refs['chart' + this.chartInfo.id].resize()
}
}, },
mounted () { mounted () {
} }

View File

@@ -0,0 +1,329 @@
<template>
<div style="width: 100%;height: 100%" v-loading="loading">
<hexagonBox
ref="hexagonBox"
:hexData="hexData"
:col="col"
:length="length"
:colorFrom="'level'"
:colorSet="colorSet"
:infoSet="infoSet"
:infoShow="infoShow"
:infoHide="infoHide"
:hexagonEdge="hexagonEdge"
:from="from"
:hexagonSvgID="hexagonSvgID"
:showTooltip="showTooltip"
@changeAsset="changeAsset"
@assetMove="assetMove"
@closeAsset="closeAsset"
/>
<alertLabel
v-if="showTooltip&&assetData.show"
v-loading="assetData.loading"
ref="alertLabel"
:id="assetData.id"
:that="assetData"
:type="fromType"
:LRTriangle="LRTriangle"
:style="{
'transform-origin': `0px 300px`,
transform:`scale(${assetData.rate})`
}"
></alertLabel>
</div>
</template>
<script>
import hexagonBox from '@/components/common/honeycomb/hexagonFigureSvg'
import alertLabel from '@/components/common/alert/alertLabel2'
function textMouseDown (e) {
window.event ? window.event.cancelBubble = true : e.stopPropagation()
}
// eslint-disable-next-line no-unused-vars
function textMouseEnter (e) {
window.event ? window.event.cancelBubble = true : e.stopPropagation()
}
// eslint-disable-next-line no-unused-vars
function textMouseLeave (e) {
window.event ? window.event.cancelBubble = true : e.stopPropagation()
}
export default {
name: 'chartHexagon',
components: {
hexagonBox,
alertLabel
},
props: {
chartData: {},
chartInfo: {}
},
watch: {
chartData: {
immediate: true,
deep: true,
handler () {
console.log(this.chartData)
}
},
chartInfo: {
immediate: true,
deep: true,
handler () {
this.initHexagon()
}
},
length: {
immediate: false,
deep: true,
handler () {
}
}
},
data () {
return {
hexData: [],
hexagonEdge: 90,
loading: false,
assetData: {
id: '',
loading: false,
show: false,
rate: 1,
position: {
top: 0,
left: 0,
mt: 0
}
},
boxWidth: '',
LRTriangle: true, // true 左三角 false 右
timer: null,
col: 8,
length: 48,
from: '',
hexagonSvgID: '',
showTooltip: false,
fromType: ''
}
},
methods: {
initHexagon () {
const param = this.chartInfo.param
if (param) {
this.col = param.col
this.length = param.length
this.from = param.from
this.hexagonSvgID = 'hexagonSvg' + this.chartInfo.id
this.showTooltip = param.showTooltip
this.fromType = param.from
}
this.$nextTick(() => {
this.hexData = this.chartData
})
},
colorSet (item) { // 设置方块颜色
const alert = item.alert[0]
if (alert.P1 > 0) {
return {
color: '#DA4D4D',
hoverColor: '#E87F7F'
}
} else if (alert.P2 > 0) {
return {
color: '#FFAB99',
hoverColor: '#FABEB2'
}
} else if (alert.P3 > 0) {
return {
color: '#FFCF92',
hoverColor: '#FFE0B8'
}
} else {
return { color: '#99D7C2', hoverColor: '#B2ECD9' }
}
},
infoSet (group, allHexagonRect, allHexagonText, data, item, fontSize, that) {
// 设置内部文本
// group 对应六边形所在的组。allHexagonRect吧所有文本框放入方便控制显示隐藏。data 六边形的相关数 data.center 中心点。that 子组件实例
const rgbColor = '0,0,0'
let str = ''
let textPaddingWidth = ''
let textPaddingHeight = ''
const rect0 = group.rect(that.hexagonEdge + 20, that.hexagonEdge / 3)
.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10,
y: data.center[1] - that.hexagonEdge,
rx: 5,
ry: 5
}).fill({ color: `rgba(${rgbColor},0)` }).data({ color: rgbColor })
str = this.from === 'asset' ? item.name : item.name
str += ''
if (str.length >= 15) {
str = str.slice(0, 12) + '...'
}
const text0 = group.text(str).attr({ x: 0, y: 0, style: 'cursor:text' }).font({ size: fontSize }).fill({ opacity: 0, color: '#fff', weight: 600, cursor: 'text' })
textPaddingWidth = (that.hexagonEdge + 20) - (text0.bbox().width)
textPaddingHeight = (that.hexagonEdge / 3) - (text0.bbox().height)
text0.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10 + textPaddingWidth / 2,
y: data.center[1] - that.hexagonEdge + textPaddingHeight / 2 - 4
}).hide()
allHexagonRect.push(rect0)
allHexagonText.push(text0)
text0.on('mousedown', textMouseDown)
const rect1 = group.rect(that.hexagonEdge + 20, that.hexagonEdge / 3)
.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10,
y: data.center[1] - that.hexagonEdge / 2 - 7.5,
rx: 6,
ry: 6
}).fill({ color: `rgba(${rgbColor},0)` }).data({ color: rgbColor })
str = 'P1 : ' + item.alert[0].P1
if (str.length >= 15) {
str = str.slice(0, 12) + '...'
}
const text1 = group.text(str).attr({ x: 0, y: 0, style: 'cursor:default' }).font({ size: fontSize }).fill({ opacity: 0, color: '#fff', weight: 600, cursor: 'default' })
textPaddingWidth = (that.hexagonEdge + 20) - (text1.bbox().width)
textPaddingHeight = (that.hexagonEdge / 3) - (text1.bbox().height)
text1.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10 + textPaddingWidth / 2,
y: data.center[1] - that.hexagonEdge / 2 - 7.5 + textPaddingHeight / 2 - 4
}).hide()
allHexagonRect.push(rect1)
allHexagonText.push(text1)
const rect2 = group.rect(that.hexagonEdge + 20, that.hexagonEdge / 3).attr({
x: data.center[0] - that.hexagonEdge / 2 - 10,
y: data.center[1] - that.hexagonEdge / 2 + that.hexagonEdge / 3 + 0.5,
rx: 6,
ry: 6
}).fill({ color: `rgba(${rgbColor},0)` }).data({ color: rgbColor })
str = 'P2 : ' + item.alert[0].P2
if (str.length >= 15) {
str = str.slice(0, 12) + '...'
}
const text2 = group.text(str).attr({ x: 0, y: 0, style: 'cursor:default' }).font({ size: fontSize }).fill({ opacity: 0, color: '#fff', weight: 600, cursor: 'default' })
textPaddingWidth = (that.hexagonEdge + 20) - (text2.bbox().width)
textPaddingHeight = (that.hexagonEdge / 3) - (text2.bbox().height)
text2.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10 + textPaddingWidth / 2,
y: data.center[1] - that.hexagonEdge / 2 + that.hexagonEdge / 3 + 0.5 + textPaddingHeight / 2 - 4
}).hide()
allHexagonRect.push(rect2)
allHexagonText.push(text2)
const rect3 = group.rect(that.hexagonEdge + 20, that.hexagonEdge / 3)
.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10,
y: data.center[1] - that.hexagonEdge / 2 + that.hexagonEdge / 3 * 2 + 5.5,
rx: 6,
ry: 6
}).fill({ color: `rgba(${rgbColor},0)` }).data({ color: rgbColor })
str = 'P3 : ' + item.alert[0].P3
if (str.length >= 15) {
str = str.slice(0, 12) + '...'
}
const text3 = group.text(str).attr({ x: 0, y: 0, style: 'cursor:default' }).font({ size: fontSize }).fill({ opacity: 0, color: '#fff', weight: 600, cursor: 'default' })
textPaddingWidth = (that.hexagonEdge + 20) - (text3.bbox().width)
textPaddingHeight = (that.hexagonEdge / 3) - (text3.bbox().height)
text3.attr({
x: data.center[0] - that.hexagonEdge / 2 - 10 + textPaddingWidth / 2,
y: data.center[1] - that.hexagonEdge / 2 + that.hexagonEdge / 3 * 2 + 5.5 + textPaddingHeight / 2 - 4
}).hide()
allHexagonRect.push(rect3)
allHexagonText.push(text3)
},
infoShow (allHexagonRect, allHexagonText) {
allHexagonRect.forEach(item => {
const rgbColor = item.data('color')
item.fill({ color: `rgba(${rgbColor},0.2)` })
})
allHexagonText.forEach(item => {
item.fill({ opacity: 1 }).show()
})
},
infoHide (allHexagonRect, allHexagonText) {
allHexagonRect.forEach(item => {
const rgbColor = item.data('color')
item.fill({ color: `rgba(${rgbColor},0)` })
})
allHexagonText.forEach(item => {
item.fill({ opacity: 0 }).hide()
})
},
changeAsset (data, e) {
if (this.timer) {
clearTimeout(this.timer)
}
this.assetData.id = data
const boxWidth = document.getElementsByClassName('list-page')[0].offsetWidth
this.boxWidth = boxWidth
// this.assetData.rate=window.screen.height/1297;
this.$nextTick(() => {
this.assetData.show = true
this.$nextTick(() => {
this.calcPosition(e)
})
})
},
assetMove (e) {
if (!this.assetData.show) { return }
this.calcPosition(e)
},
calcPosition (e) {
const boxWidth = this.boxWidth
const distance = this.fromType === 'asset' ? 300 : 50
const minus = (e.pageY - distance) + this.$refs.alertLabel.$el.offsetHeight - window.innerHeight
// window.innerHeight
if (minus <= 0) {
this.assetData.position.top = e.pageY - distance
this.assetData.position.mt = distance
} else if (minus > 0) {
this.assetData.position.top = window.innerHeight - this.$refs.alertLabel.$el.offsetHeight
this.assetData.position.mt = e.pageY - (window.innerHeight - this.$refs.alertLabel.$el.offsetHeight)
}
if (boxWidth / 2 > e.pageX - 200) {
this.assetData.position.left = e.pageX + 35
this.assetData.position.right = 0
this.LRTriangle = true
} else {
this.assetData.position.right = window.innerWidth - (e.pageX - 35)
this.assetData.position.left = 0
this.LRTriangle = false
}
},
closeAsset () {
if (!this.timer) {
this.timer = setTimeout(() => {
this.assetData.show = false
this.timer = null
}, 100)
} else {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.assetData.show = false
this.timer = null
}, 100)
}
},
endLoading () {
this.loading = false
},
startLoading () {
this.loading = true
},
resize () {
this.hexData = [...this.chartData]
}
}
}
</script>
<style scoped>
</style>

View File

@@ -51,6 +51,10 @@ export function isTimeSeries (type) {
return type === chartType.line || type === chartType.area || type === chartType.point return type === chartType.line || type === chartType.area || type === chartType.point
} }
export function isHexagonFigure (type) {
return type === chartType.hexagonFigure
}
export function initColor (colorNum = 20) { export function initColor (colorNum = 20) {
const colorList = [ const colorList = [
'#FF5200', '#3685FF', '#FF8D00', '#00DCA2', '#FF5200', '#3685FF', '#FF8D00', '#00DCA2',

View File

@@ -91,6 +91,7 @@ export default {
}, },
containerResizedEvent (i, newH, newW, newHPx, newWPx) { containerResizedEvent (i, newH, newW, newHPx, newWPx) {
// TODO 重新渲染图表 // TODO 重新渲染图表
// this.$refs['chart' + i].resize()
} }
}, },
mounted () { mounted () {

View File

@@ -8,6 +8,7 @@
<!-- chart --> <!-- chart -->
<!-- 数据查询后传入chart组件chart组件内不查询只根据接传递的数据来渲染 --> <!-- 数据查询后传入chart组件chart组件内不查询只根据接传递的数据来渲染 -->
<chart <chart
ref="chart"
:chart-data="chartData" :chart-data="chartData"
:chart-info="chartInfo" :chart-info="chartInfo"
></chart> ></chart>
@@ -106,7 +107,43 @@ export default {
case 4: { case 4: {
break break
} }
case 'hexagonFigure': {
this.getHexagonFigureData().then(res => {
this.chartData = res
})
break
}
} }
},
getHexagonFigureData () {
return new Promise(resolve => {
this.$get('stat/alertMessage/topN', { size: 48, dimension: 'module' }).then(response => {
if (response.code === 200) {
const moduleData = response.data.list
moduleData.sort((a, b) => b.alertNum - a.alertNum)
const alertTopModules = moduleData.slice(0, 48)
const requests = alertTopModules.map(a => axios.get(`stat/alertMessage/severity?moduleId=${a.id}`))
const moduleStateData = []
axios.all(requests).then(result => {
result.forEach((alert, i) => {
const severityData = {}
alert.data.data.list && alert.data.data.list.forEach(a => {
severityData[a.name] = a.num
})
!severityData.P1 && (severityData.P1 = 0)
!severityData.P2 && (severityData.P2 = 0)
!severityData.P3 && (severityData.P3 = 0)
moduleStateData.push({ ...alertTopModules[i], alert: [severityData] })
})
console.log(moduleStateData)
resolve(moduleStateData)
})
}
})
})
},
resize() {
this.$refs.chart.resize()
} }
}, },
mounted () { mounted () {

View File

@@ -444,6 +444,219 @@ const chartData = {
varType: null, varType: null,
varId: null, varId: null,
varName: null varName: null
},
{
id: 690502,
name: '324',
panelId: 1243,
groupId: 0,
span: 6,
height: 4,
updateBy: 1,
updateAt: '2021-11-10 09:51:06',
type: 'hexagonFigure',
unit: 2,
weight: 2,
dataSource: 'hexagonFigure',
param: '{' +
' "from":"module",' +
' "length":"48",' +
' "showTooltip": true ,' +
' "col":"8"' +
'}',
pid: null,
buildIn: 0,
remark: '123',
seq: null,
x: 6,
y: 4,
w: 6,
h: 4,
i: 690502,
elements: [
{
id: 68527,
chartId: 690483,
expression: 'up{asset="44.37"}',
type: 'expert',
legend: '',
buildIn: 0,
seq: null
},
{
id: 68528,
chartId: 690483,
expression: 'Hadoop_HBase_Healthy',
type: 'expert',
legend: '',
buildIn: 0,
seq: null
}
],
sync: null,
panel: {
id: 1243,
name: 'test',
createBy: null,
type: null,
link: null,
pid: null,
weight: null,
buildIn: null,
seq: null,
children: null,
parent: null,
chartNum: null
},
group: {
id: 0,
name: null,
panelId: null,
groupId: null,
span: null,
height: null,
updateBy: null,
updateAt: null,
type: null,
unit: null,
weight: null,
param: null,
pid: null,
buildIn: null,
remark: null,
seq: null,
x: null,
y: null,
elements: null,
sync: null,
panel: null,
group: null,
children: null,
chartNums: null,
asset: null,
varType: null,
varId: null,
varName: null
},
children: [
{
id: 690502,
name: '123',
panelId: 1243,
groupId: 690501,
span: 12,
height: 4,
updateBy: 1,
updateAt: '2021-11-10 09:51:15',
type: 'line',
unit: 2,
weight: 3,
param: {
last: 0,
legendValue: {
total: 'off',
min: 'off',
avg: 'off',
last: 'off',
max: 'off'
},
threshold: '123',
valueMapping: {
mapping: [
{
color: {
bac: '#fff',
text: '#000'
},
text: '',
value: ''
}
],
type: 'text'
},
url: '',
nullType: 'null'
},
pid: null,
buildIn: 0,
remark: '',
seq: null,
x: 0,
y: 0,
w: 12,
h: 4,
i: 690489,
elements: [
{
id: 68543,
chartId: 690502,
expression: '123',
type: 'expert',
legend: '',
buildIn: 0,
seq: null
}
],
sync: null,
panel: {
id: 1243,
name: 'test',
createBy: null,
type: null,
link: null,
pid: null,
weight: null,
buildIn: null,
seq: null,
children: null,
parent: null,
chartNum: null
},
group: {
id: 690501,
name: '123',
panelId: null,
groupId: null,
span: null,
height: null,
updateBy: null,
updateAt: null,
type: null,
unit: null,
weight: null,
param: null,
pid: null,
buildIn: null,
remark: null,
seq: null,
x: null,
y: null,
elements: null,
sync: null,
panel: null,
group: null,
children: null,
chartNums: null,
asset: null,
varType: null,
varId: null,
varName: null
},
children: [
],
chartNums: null,
asset: null,
varType: null,
varId: null,
varName: null
}
],
chartNums: null,
asset: null,
varType: null,
varId: null,
varName: null
} }
] ]
}, },

View File

@@ -173,6 +173,7 @@ export default {
deep: true, deep: true,
handler (n) { handler (n) {
this.init() this.init()
console.log(n)
} }
}, },
col: { // 列数 col: { // 列数

View File

@@ -404,7 +404,8 @@ export const chartType = {
assetInfo: 'assetInfo', assetInfo: 'assetInfo',
endpointInfo: 'endpointInfo', endpointInfo: 'endpointInfo',
topology: 'topology', topology: 'topology',
map: 'map' map: 'map',
hexagonFigure: 'hexagonFigure'
} }
export const chartLegendPlacement = { export const chartLegendPlacement = {

View File

@@ -0,0 +1,271 @@
<template>
<div v-clickoutside="{obj:editChart, func:clickOutside}" :class="boxClass" class="right-box right-box-chart">
<transition v-if="from !== 'chartTemp'" name="right-box">
<panel-box v-if="!showPanel.type" ref="panelBox2" :panel="panel" @reload="panelReload"></panel-box>
</transition>
<div class="right-box__header">
<div class="header__title" v-if="from !== 'chartTemp'">{{editChart.id ? $t("dashboard.panel.editChartTitle") : $t("dashboard.panel.createChartTitle")}}</div>
<div class="header__title" v-if="from === 'chartTemp'">{{editChart.id ? $t("dashboard.panel.editChartTempTitle") : $t("dashboard.panel.createChartTempTitle")}}</div>
<div class="header__operation">
<span v-cancel="{obj: editChart, func: clickOutside}"><i class="nz-icon nz-icon-close"></i></span>
</div>
</div>
<!-- begin--表单-->
<div class="right-box-form-box right-box__container" style="overflow: hidden">
<el-form ref="chartForm" :model="editChart" :rules="rules" label-position= "top" label-width="120px">
<el-form-item :label='$t("dashboard.panel.chartForm.name")' prop="title">
<el-input maxlength="64" show-word-limit size="small" v-model="editChart.name" id="chart-box-title"></el-input>
</el-form-item>
<div class="form-items--half-width-group">
<!--panel-->
<el-form-item
class="form-item--half-width"
v-if="showPanel.type !== fromRoute.project && showPanel.type !== fromRoute.asset && showPanel.type !== fromRoute.endpoint && showPanel.type !== fromRoute.model && from!=='chartTemp'"
:label="$t('dashboard.panel.title')"
prop="panelName"
>
<select-panel ref="selectPanel" :disabled="showPanel.type === 'dashboard'" :filter-panel="filterPanel" :chart-box="true" :panel-lock="true" :panelData="panelData" :placement="'bottom-start'" @selectPanel="selectPanel">
<template v-slot:header>
<div class="panel-select-header">
<el-input id="chart-box-panelname" v-model="filterPanel" :placeholder="$t('overall.search')" clearable size="small" style="width: 596px"></el-input>
</div>
</template>
<template v-slot:trigger>
<el-input placeholder="" readonly="readonly" size="small" v-model="editChart.panelName" :disabled="showPanel.type==='dashboard'"></el-input>
</template>
</select-panel>
</el-form-item>
<!--group-->
<el-form-item :label="$t('dashboard.panel.chartForm.group')" class="form-item--half-width" prop="group">
<el-select id="chart-box-group" v-model="editChart.groupId" :disabled="editChart.type==='group'" clearable placeholder="" popper-class="right-box-select-top prevent-clickoutside" size="small" value-key="chartType">
<el-option v-for="item in groupArr" :key="item.id" :label="item.name" :value="item.id">
<span class="panel-dropdown-label-txt" >{{item.name}}</span>
</el-option>
</el-select>
</el-form-item>
</div>
<!--remark-->
<el-form-item :label="$t('overall.remark')">
<el-input maxlength="256" show-word-limit v-model="editChart.remark" :autosize="{ minRows: 1, maxRows: 6}" type="textarea"/>
</el-form-item>
<!--title-->
<div class="form__sub-title">
<span>{{$t('dashboard.panel.chartForm.dataConfig')}}</span>
</div>
<el-tabs v-model="editChart.datasource" @tab-click="datasourceChange">
<el-tab-pane label="Metrics" name="1">
<metrics-chart-config v-if="editChart.datasource == 1" :params.sync="editChart"/>
</el-tab-pane>
<el-tab-pane label="Logs" name="2">
<logs-chart-config v-if="editChart.datasource == 2" :params.sync="editChart"/>
</el-tab-pane>
<el-tab-pane label="System" name="3">
<system-chart-config v-if="editChart.datasource == 3" :params.sync="editChart"/>
</el-tab-pane>
<el-tab-pane label="Other" name="4">
<other-chart-config v-if="editChart.datasource == 4" :params.sync="editChart"/>
</el-tab-pane>
</el-tabs>
</el-form>
</div>
<!--底部按钮-->
<div class="right-box__footer">
<button id="chart-box-esc" v-cancel="{obj:editChart,func:esc}" class="footer__btn footer__btn--light">
<span>{{$t('overall.cancel')}}</span>
</button>
<button v-if="showPanel.type && showPanel.type == 'model'" id="chart-box-Sync" v-has="'panel_chart_edit'" class="footer__btn">
<span>{{$t('overall.SyncSave')}}</span>
</button>
<button v-else-if="from!=='chartTemp'" id="chart-box-preview" class="footer__btn">
<span>{{$t('overall.preview')}}</span>
</button>
<button id="chart-box-save" v-has="'panel_chart_add'" :class="{'nz-btn-disabled':prevent_opt.save}" :disabled="prevent_opt.save" class="footer__btn">
<span>{{$t('overall.save')}}</span>
</button>
</div>
</div>
</template>
<script>
import { fromRoute } from '@/components/common/js/constants'
import editRigthBox from '@/components/common/mixin/editRigthBox'
import { resetZIndex } from '@/components/common/js/common'
import chartPreview from '@/components/charts/chartPreview'
import alertChartParam from '@/components/page/dashboard/alertChartParam'
import promqlInput from '@/components/page/dashboard/explore/promqlInput'
import richTextEditor from '@/components/charts/richTextEditor'
import selectPanel from '@/components/common/popBox/selectPanel'
import nezhaColor from '@/components/common/nezhaColor'
import diagram from '@/components/common/ChartDiagram/diagram'
import metricsChartConfig from '@/components/common/rightBox/chart/metricsChartConfig'
import logsChartConfig from '@/components/common/rightBox/chart/logsChartConfig'
import otherChartConfig from '@/components/common/rightBox/chart/otherChartConfig'
import systemChartConfig from '@/components/common/rightBox/chart/systemChartConfig'
const rz = {
methods: {
rz (e) {
resetZIndex(e)
}
}
}
export default {
name: 'chartRightBox',
props: {
boxClass: String,
panelData: Array,
showPanel: Object,
chart: Object,
from: { type: String },
fromEndpoint: {
type: Boolean,
default: false
}
},
mixins: [rz, editRigthBox],
components: {
System,
'chart-preview': chartPreview,
'alert-chart-param': alertChartParam,
'promql-input': promqlInput,
'rich-text-editor': richTextEditor,
selectPanel,
nezhaColor,
diagram,
metricsChartConfig,
logsChartConfig,
systemChartConfig,
otherChartConfig
},
data () {
return {
fromRoute,
editChart: {
name: '',
remark: ''
},
panel: {
id: '',
name: ''
},
filterPanel: '',
groupArr: [],
panelName: '',
rules: {
}
}
},
methods: {
clickOutside () {
this.esc(false)
},
/* 关闭弹框 */
esc (refresh) {
this.prevent_opt.save = false
this.$emit('close', refresh)
},
// 保存endpoint
save () {
if (this.prevent_opt.save) { return } ;
this.prevent_opt.save = true
// 对endpointList进行处理避免携带过多无用数据
const endpointList = []
this.endpointTableData.forEach((item, index) => {
const endpoint = {
moduleId: item.moduleId,
assetId: item.assetId,
name: item.name,
configs: JSON.stringify(item.configs),
id: item.id
}
endpointList.push(endpoint)
})
this.$refs.addEndpoint.validate((valid) => {
if (valid) {
this.$put('monitor/endpoint', endpointList).then(response => {
this.prevent_opt.save = false
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.esc(true)
} else {
this.$message.error(response.msg)
}
})
} else {
this.prevent_opt.save = false
return false
}
})
},
selectPanel (panel) {
this.panelName = panel.name
this.panelId = panel.id
this.editChart.groupId = ''
this.$get('visual/panel/chart?panelId=' + this.panelId + '&pageSize=-1').then(response => {
if (response.code === 200) {
this.groupArr = []
response.data.list.forEach((item, index) => {
if (item.type === 'group') {
this.groupArr.push({ id: item.id, name: item.name })
}
})
}
})
},
panelReload (panelName) { // 刷新panel下拉框
if (panelName) {
this.panelName = panelName
}
this.$emit('reloadOnlyPanel')
},
getGroupList () {
this.$get('visual/panel/chart?panelId=' + this.panelId + '&pageSize=-1').then(response => {
if (response.code === 200) {
this.groupArr = []
response.data.list.forEach((item, index) => {
if (item.type === 'group') {
this.groupArr.push({ id: item.id, name: item.name })
}
})
}
})
},
datasourceChange (val, e) {
console.log(val, e, this.editChart.datasource)
}
},
created () {
},
mounted () {
this.getGroupList()
},
watch: {
showPanel: {
immediate: true,
deep: true,
handler () {
if (this.showPanel.id || this.from === 'chartTemp') {
this.panelId = this.showPanel.id
this.panelName = this.showPanel.name
this.editChart.panelName = this.showPanel.name
}
}
},
chart: {
deep: true,
immediate: true,
handler (n) {
this.editChart = JSON.parse(JSON.stringify(n))
if (this.editChart.groupId === -1) {
this.editChart.groupId = ''
}
}
}
}
}
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div>
logs
</div>
</template>
<script>
export default {
name: 'metricsChartConfig'
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,183 @@
<template>
<div class="chart-config">
<el-form ref="metricschartForm" :model="chartConfig" :rules="rules" label-position= "top" label-width="120px">
<div v-if="chartConfig.elements">
<el-row
:key="'ele' + index" class="element-item form-row-item" style="" v-for="index of chartConfig.elements.length"
>
<div class="chart-title">
<span class="endpoint-title-content">
<i class="nz-icon nz-icon-arrow-down" :class="expressionsShow[index-1]?'':'is-active'" @click="showExpression(index)"></i>
</span>
</div>
<transition name="el-zoom-in-top">
<el-row v-show="expressionsShow[index-1]">
<promql-input
:from-father-data="true"
:metricOptionsParent="metricOptions"
:expression-list="expressions"
:id="promqlKeys[index-1]"
:index="index-1"
:required = 'true'
:type="promqlType"
:key="promqlKeys[index-1]"
:plugins="['metric-selector', 'metric-input', 'remove']"
:ref="'promql-'+(index-1)"
:showRemove="false"
:styleType="2"
@change="expressionChange"
@removeExpression="removeExpression"
></promql-input>
<el-row style="margin-top: 18px">
<el-col class="legend-title">
<span class="legend-title__span">{{$t('dashboard.panel.chartForm.legend')}}&nbsp;</span>
<el-popover placement="top" trigger="hover" width="211" popper-class="prevent-clickoutside">
<div :style="{'word-break':language!=='cn'?'keep-all':'break-all'}">{{$t('dashboard.panel.chartForm.legendTip')}}</div>
<i @mouseover="rz" class="nz-icon nz-icon-info-normal" slot="reference" style="font-size: 14px; -webkit-transform:scale(0.75);display:inline-block;"></i>
</el-popover>
</el-col>
<el-col style="width: calc(100% - 160px);">
<el-input maxlength="512" show-word-limit size="small" type="text" v-model="legends[index-1]" ></el-input>
</el-col>
</el-row>
</el-row>
</transition>
</el-row>
</div>
</el-form>
</div>
</template>
<script>
import promqlInput from '@/components/page/dashboard/explore/promqlInput'
import promqlInputMixin from '@/components/common/mixin/promqlInput'
import { getUUID, resetZIndex } from '@/components/common/js/common'
const rz = {
methods: {
rz (e) {
resetZIndex(e)
}
}
}
export default {
name: 'metricsChartConfig',
props: {
params: {}
},
components: {
promqlInput
},
mixins: [rz, promqlInputMixin],
computed: {},
data () {
return {
language: localStorage.getItem('nz-language'),
chartConfig: {},
rules: {},
promqlType: 'metrics',
promqlCount: 0,
promqlKeys: [],
elementIds: [],
expressions: [],
expressionsShow: [],
legends: []
}
},
methods: {
init () {
this.chartConfig = JSON.parse(JSON.stringify(this.params))
// 重置相关属性
this.promqlCount = 0
this.promqlKeys = []
this.elementIds = []
this.expressions = []
this.expressionsShow = []
this.legends = []
if (!this.chartConfig.elements.length) {
this.addExpression()
} else {
this.chartConfig.elements.forEach(item => {
this.addExpression(item)
})
}
},
expressionChange: function () {
if (this.expressions[0]) {
this.chartConfig.elements = []
this.expressions.forEach((expr, i) => {
this.chartConfig.elements.push({ id: this.elementIds[i], expression: expr, type: 'expert', legend: this.legends[i] })
})
} else {
this.chartConfig.elements = []
}
this.change()
},
addExpression (item) {
if (!item) {
this.expressions.push('')
this.legends.push('')
this.promqlKeys.push(getUUID())
this.elementIds.push('')
this.expressionsShow.push(true)
this.promqlCount++
this.expressionChange()
} else {
this.expressions.push(item.expression)
this.legends.push(item.legend)
this.promqlKeys.push(getUUID())
this.elementIds.push(item.id)
this.expressionsShow.push(true)
this.promqlCount++
}
},
removeExpression (index) {
if (this.promqlCount > 1) {
this.expressions.splice(index, 1)
this.legends.splice(index, 1)
this.promqlKeys.splice(index, 1)
this.expressionsShow.splice(index, 1)
this.elementIds.splice(index, 1)
this.promqlCount--
this.$nextTick(() => {
this.expressions.forEach((ex, index) => {
if (ex) {
this.$refs[`promql-${index}`][0].metricChange(ex)
}
})
})
}
},
copyExpression (index) {
this.expressions.push(this.expressions[index])
this.legends.push(this.legends[index])
this.promqlKeys.push(getUUID())
this.elementIds.push('')
this.expressionsShow.push(true)
this.promqlCount++
this.$nextTick(() => {
this.expressions.forEach((ex, index) => {
if (ex) {
this.$refs[`promql-${index}`][0].metricChange(ex)
}
})
})
},
showExpression (index) {
console.log(index, this.expressionsShow[index - 1])
this.$set(this.expressionsShow, index - 1, !this.expressionsShow[index - 1])
},
change () {
this.$nextTick(() => {
this.$emit('change', this.chartConfig)
})
}
},
created () {
this.init()
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
other
</div>
</template>
<script>
export default {
name: 'otherChartConfig'
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<div>
system
</div>
</template>
<script>
export default {
name: 'systemChartConfig'
}
</script>
<style scoped>
</style>

View File

@@ -105,7 +105,34 @@
<button :class="{'to-top-is-hover': tableHover}" @click="toTop(scrollbarWrap)" class="to-top" style="bottom: 0;" v-show="showTopBtn"><i class="nz-icon nz-icon-top"></i></button> <button :class="{'to-top-is-hover': tableHover}" @click="toTop(scrollbarWrap)" class="to-top" style="bottom: 0;" v-show="showTopBtn"><i class="nz-icon nz-icon-top"></i></button>
<transition name="right-box"> <transition name="right-box">
<chart-box v-if="rightBox.chart.show" ref="addChartModal" :chart="chart" :from="fromRoute.panel" :panel-data="panelData" :show-panel="showPanel" @close="closeChartBox" @reload="panelReload" @reloadOnlyPanel="panelReloadOnlyPanel" @delete-chart="delChart" @on-create-success="createSuccess" @on-delete-success="delChartOk"></chart-box> <chart-box
v-if="rightBox.chart.show"
ref="addChartModal"
:chart="chart"
:from="fromRoute.panel"
:panel-data="panelData"
:show-panel="showPanel"
@close="closeChartBox"
@reload="panelReload"
@reloadOnlyPanel="panelReloadOnlyPanel"
@delete-chart="delChart"
@on-create-success="createSuccess"
@on-delete-success="delChartOk"
></chart-box>
<!-- <chart-right-box-->
<!-- v-if="rightBox.chart.show"-->
<!-- ref="addChartModal"-->
<!-- :chart="chart"-->
<!-- :from="fromRoute.panel"-->
<!-- :panel-data="panelData"-->
<!-- :show-panel="showPanel"-->
<!-- @close="closeChartBox"-->
<!-- @reload="panelReload"-->
<!-- @reloadOnlyPanel="panelReloadOnlyPanel"-->
<!-- @delete-chart="delChart"-->
<!-- @on-create-success="createSuccess"-->
<!-- @on-delete-success="delChartOk"-->
<!-- ></chart-right-box>-->
</transition> </transition>
<transition name="right-box"> <transition name="right-box">
<chart-temp-box v-if="rightBox.chartTemp.show" :from="fromRoute.panel" :obj="chart" :panel-data="panelData" :show-panel="showPanel" @close="closeChartTempBox" @on-create-success="createSuccess"></chart-temp-box> <chart-temp-box v-if="rightBox.chartTemp.show" :from="fromRoute.panel" :obj="chart" :panel-data="panelData" :show-panel="showPanel" @close="closeChartTempBox" @on-create-success="createSuccess"></chart-temp-box>
@@ -118,6 +145,7 @@
<script> <script>
import ChartBox from './chartBox' import ChartBox from './chartBox'
import chartRightBox from '@/components/common/rightBox/chart/chartRightBox'
import ChartList from '../../chart/chartList' import ChartList from '../../chart/chartList'
import bus from '../../../libs/bus' import bus from '../../../libs/bus'
import pickTime from '../../common/pickTime' import pickTime from '../../common/pickTime'
@@ -164,6 +192,7 @@ export default {
name: '', name: '',
type: 'line', type: 'line',
span: 12, span: 12,
datasource: '1',
height: '400', height: '400',
unit: 2, unit: 2,
param: { url: '', threshold: '' }, param: { url: '', threshold: '' },
@@ -239,7 +268,8 @@ export default {
'panel-box': panelBox, 'panel-box': panelBox,
topToolMoreOptions, topToolMoreOptions,
selectPanel, selectPanel,
chartTempBox chartTempBox,
chartRightBox
}, },
methods: { methods: {
// 刷新 // 刷新
@@ -414,12 +444,12 @@ export default {
this.rightBox.chart.show = false this.rightBox.chart.show = false
const chartList = this.$refs.chartList.dataList const chartList = this.$refs.chartList.dataList
for (let i = 0; i < chartList.length; i++) { for (let i = 0; i < chartList.length; i++) {
/*if (chartList[i].id === data.id) { /* if (chartList[i].id === data.id) {
chartList.splice(i, 1) chartList.splice(i, 1)
} }
if (chartList[i].type === 'group') { if (chartList[i].type === 'group') {
chartList[i].children = chartList[i].children.filter((item) => item.id !== data.id) chartList[i].children = chartList[i].children.filter((item) => item.id !== data.id)
}*/ } */
// if(data.next != -1){ // if(data.next != -1){
// if(chartList[i].id === data.next){ // if(chartList[i].id === data.next){
// nextChart = chartList[i] // nextChart = chartList[i]
@@ -431,7 +461,7 @@ export default {
// } // }
// } // }
} }
//this.$refs.chartList.loadChartData(this.scrollbarWrap.scrollTop) // this.$refs.chartList.loadChartData(this.scrollbarWrap.scrollTop)
// if(nextChart&&prevChart){ //删除图表为中间位置 // if(nextChart&&prevChart){ //删除图表为中间位置
// prevChart.next = nextChart.id; // prevChart.next = nextChart.id;
// nextChart.prev = prevChart.id; // nextChart.prev = prevChart.id;
@@ -702,6 +732,9 @@ export default {
wrap.scrollTop = currentTop wrap.scrollTop = currentTop
} }
}, 20) }, 20)
},
load () {
} }
}, },
created () { created () {