Merge branch 'dev-3.0' into dev-2.0
# Conflicts: # nezha-fronted/src/components/common/language/en.js # nezha-fronted/src/components/page/dashboard/explore/explore.vue # nezha-fronted/src/components/page/dashboard/explore/promqlInput.vue
This commit is contained in:
@@ -24,7 +24,7 @@
|
|||||||
"@topology/sequence-diagram": "^0.3.0",
|
"@topology/sequence-diagram": "^0.3.0",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
"cytoscape": "^3.15.2",
|
"cytoscape": "^3.15.2",
|
||||||
"echarts": "^5.0.1",
|
"echarts": "^5.1.2",
|
||||||
"element-ui": "^2.15.3",
|
"element-ui": "^2.15.3",
|
||||||
"file-saver": "^2.0.2",
|
"file-saver": "^2.0.2",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
|
|||||||
@@ -54,63 +54,63 @@
|
|||||||
.top-tool-left {
|
.top-tool-left {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.top-tool-btn-group {
|
}
|
||||||
display: flex;
|
.top-tool-btn-group {
|
||||||
.top-tool-btn:not(:last-of-type):not(:first-of-type) {
|
display: flex;
|
||||||
border-left: none;
|
.top-tool-btn:not(:last-of-type):not(:first-of-type) {
|
||||||
border-radius: 0;
|
border-left: none;
|
||||||
}
|
border-radius: 0;
|
||||||
.top-tool-btn:first-of-type:not(:last-of-type) {
|
|
||||||
border-radius: $--button-border-radius 0 0 $--button-border-radius;
|
|
||||||
}
|
|
||||||
.top-tool-btn:last-of-type:not(:first-of-type) {
|
|
||||||
border-radius: 0 $--button-border-radius $--button-border-radius 0;
|
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.top-tool-btn {
|
.top-tool-btn:first-of-type:not(:last-of-type) {
|
||||||
height: 32px;
|
border-radius: $--button-border-radius 0 0 $--button-border-radius;
|
||||||
width: 36px;
|
}
|
||||||
border: 1px solid $--primary-border-color;
|
.top-tool-btn:last-of-type:not(:first-of-type) {
|
||||||
outline: none;
|
border-radius: 0 $--button-border-radius $--button-border-radius 0;
|
||||||
border-radius: $--button-border-radius;
|
border-left: none;
|
||||||
background-color: $--button-gray-background-color;
|
}
|
||||||
transition: background-color linear .1s;
|
}
|
||||||
|
.top-tool-btn {
|
||||||
|
height: 32px;
|
||||||
|
width: 36px;
|
||||||
|
border: 1px solid $--primary-border-color;
|
||||||
|
outline: none;
|
||||||
|
border-radius: $--button-border-radius;
|
||||||
|
background-color: $--button-gray-background-color;
|
||||||
|
transition: background-color linear .1s;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: $--button-gray-color;
|
color: $--button-gray-color;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.top-tool-btn.top-tool-btn--text {
|
}
|
||||||
padding: 0 8px;
|
.top-tool-btn.top-tool-btn--text {
|
||||||
width: unset;
|
padding: 0 8px;
|
||||||
color: #666;
|
width: unset;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.top-tool-btn:hover:not(.nz-btn-disabled) {
|
||||||
|
background-color: $--button-gray-hover-background-color;
|
||||||
|
}
|
||||||
|
.top-tool-btn:focus:not(.nz-btn-disabled), .top-tool-btn.is-focus {
|
||||||
|
background-color: $--button-gray-hover-background-color;
|
||||||
|
border: 1px solid #FBCEA4 !important;
|
||||||
|
i {
|
||||||
|
color: $--button-gray-active-color;
|
||||||
}
|
}
|
||||||
.top-tool-btn:hover:not(.nz-btn-disabled) {
|
}
|
||||||
background-color: $--button-gray-hover-background-color;
|
.top-tool-btn--delete.top-tool-btn:focus:not(.nz-btn-disabled) {
|
||||||
}
|
background-color: $--button-gray-hover-background-color;
|
||||||
.top-tool-btn:focus:not(.nz-btn-disabled), .top-tool-btn.is-focus {
|
border-color: #FFC4B9;
|
||||||
background-color: $--button-gray-hover-background-color;
|
|
||||||
border: 1px solid #FBCEA4 !important;
|
|
||||||
i {
|
|
||||||
color: $--button-gray-active-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.top-tool-btn--delete.top-tool-btn:focus:not(.nz-btn-disabled) {
|
|
||||||
background-color: $--button-gray-hover-background-color;
|
|
||||||
border-color: #FFC4B9;
|
|
||||||
|
|
||||||
i {
|
i {
|
||||||
color: #F0745A;
|
color: #F0745A;
|
||||||
}
|
|
||||||
}
|
|
||||||
.top-tool-btn--dropdown {
|
|
||||||
position: relative;
|
|
||||||
width: auto;
|
|
||||||
min-width: 36px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.top-tool-btn--dropdown {
|
||||||
|
position: relative;
|
||||||
|
width: auto;
|
||||||
|
min-width: 36px;
|
||||||
|
}
|
||||||
.top-tools--sub {
|
.top-tools--sub {
|
||||||
.top-tool-left {
|
.top-tool-left {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -706,7 +706,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.top-tool-btn-group {
|
.top-tool-btn-group {
|
||||||
margin-left: 10px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
.top-tool-btn:not(:last-of-type):not(:first-of-type) {
|
.top-tool-btn:not(:last-of-type):not(:first-of-type) {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ export default {
|
|||||||
|
|
||||||
.chart-unit{
|
.chart-unit{
|
||||||
width: 100px;
|
width: 100px;
|
||||||
margin: 0 20px 0 0;
|
|
||||||
}
|
}
|
||||||
.chart-unit.el-cascader .el-input.is-focus .el-input__inner {
|
.chart-unit.el-cascader .el-input.is-focus .el-input__inner {
|
||||||
border-color: #FBCEA4;
|
border-color: #FBCEA4;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const cn = {
|
|||||||
oneDay: '1 天',
|
oneDay: '1 天',
|
||||||
twoDay: '2 天',
|
twoDay: '2 天',
|
||||||
week: '1 周',
|
week: '1 周',
|
||||||
|
time: '时间',
|
||||||
folder: '文件夹',
|
folder: '文件夹',
|
||||||
key: '键名',
|
key: '键名',
|
||||||
logs: '日志',
|
logs: '日志',
|
||||||
@@ -65,6 +66,7 @@ const cn = {
|
|||||||
other: '其他',
|
other: '其他',
|
||||||
about: '关于',
|
about: '关于',
|
||||||
query: '查询',
|
query: '查询',
|
||||||
|
logLabels: '日志标签',
|
||||||
account: '账号',
|
account: '账号',
|
||||||
back: '返回',
|
back: '返回',
|
||||||
unavailable: '不可用',
|
unavailable: '不可用',
|
||||||
@@ -115,6 +117,7 @@ const cn = {
|
|||||||
},
|
},
|
||||||
reset: '重置',
|
reset: '重置',
|
||||||
submit: '保存',
|
submit: '保存',
|
||||||
|
limit: '限制',
|
||||||
noData: '没有数据',
|
noData: '没有数据',
|
||||||
tag: '标签',
|
tag: '标签',
|
||||||
syncChart: '同步图表',
|
syncChart: '同步图表',
|
||||||
@@ -520,6 +523,10 @@ const cn = {
|
|||||||
down: 'down',
|
down: 'down',
|
||||||
prometheus: 'prometheus'
|
prometheus: 'prometheus'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
explore: {
|
||||||
|
descending: '降序',
|
||||||
|
wrapLines: '换行'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ const en = {
|
|||||||
oneDay: '1 day',
|
oneDay: '1 day',
|
||||||
twoDay: '2 days',
|
twoDay: '2 days',
|
||||||
week: '1 week',
|
week: '1 week',
|
||||||
|
time: 'Time',
|
||||||
folder: 'Folder',
|
folder: 'Folder',
|
||||||
key: 'Key',
|
key: 'Key',
|
||||||
logs: 'Logging',
|
logs: 'Logs',
|
||||||
state: 'State',
|
state: 'State',
|
||||||
projectName: 'Project name',
|
projectName: 'Project name',
|
||||||
startTime: 'Start time',
|
startTime: 'Start time',
|
||||||
@@ -70,6 +71,7 @@ const en = {
|
|||||||
about: 'About', // 关于
|
about: 'About', // 关于
|
||||||
detail: 'Detail', // 详情
|
detail: 'Detail', // 详情
|
||||||
query: 'Query', // 查询
|
query: 'Query', // 查询
|
||||||
|
logLabels: 'Log labels',
|
||||||
account: 'Account',
|
account: 'Account',
|
||||||
back: 'Back', // 返回
|
back: 'Back', // 返回
|
||||||
unavailable: 'Unavailable',
|
unavailable: 'Unavailable',
|
||||||
@@ -119,6 +121,7 @@ const en = {
|
|||||||
},
|
},
|
||||||
reset: 'Reset',
|
reset: 'Reset',
|
||||||
submit: 'Save',
|
submit: 'Save',
|
||||||
|
limit: 'Limit',
|
||||||
noData: 'No data',
|
noData: 'No data',
|
||||||
tag: 'Tag',
|
tag: 'Tag',
|
||||||
placeHolder: 'Please enter',
|
placeHolder: 'Please enter',
|
||||||
@@ -529,6 +532,10 @@ const en = {
|
|||||||
down: 'down',
|
down: 'down',
|
||||||
prometheus: 'prometheus'
|
prometheus: 'prometheus'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
explore: {
|
||||||
|
descending: 'Descending',
|
||||||
|
wrapLines: 'Wrap lines'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validate: { // 校验规则
|
validate: { // 校验规则
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="interval-refresh">
|
<div class="interval-refresh">
|
||||||
<time-picker v-if="showTimePicker" ref="timePicker" v-model="searchTime" :default-pick="defaultPick" :show-empty="showEmpty" class="time-picker margin-r-10" size="small" @change="dateChange"></time-picker>
|
<time-picker v-if="showTimePicker" ref="timePicker" v-model="searchTime" :default-pick="defaultPick" :show-empty="showEmpty" class="time-picker margin-r-10" size="small" @change="dateChange"></time-picker>
|
||||||
<multipleTime ref="multipleTime" v-if="showMultiple" :stepSearchTime="searchTime" @change="dateChange(searchTime)" class="multiple-time"/>
|
<multipleTime v-if="showMultiple" ref="multipleTime" :stepSearchTime="searchTime" class="multiple-time margin-r-10" @change="dateChange(searchTime)"/>
|
||||||
<chart-unit v-model="unit" v-if="useChartUnit" style="margin-left: 10px"></chart-unit>
|
<chart-unit v-if="useChartUnit" v-model="unit" class="margin-r-10"></chart-unit>
|
||||||
<div v-show="useRefresh" class="top-tool-btn-group margin-r-10">
|
<div v-show="useRefresh" class="top-tool-btn-group">
|
||||||
<button :id="id+'-refresh'" class="top-tool-btn top-tool-btn--text" @click="refreshDataFunc">
|
<button :id="id+'-refresh'" class="top-tool-btn top-tool-btn--text" @click="refreshDataFunc">
|
||||||
<i class="global-active-color nz-icon nz-icon-refresh" style="font-size: 14px"></i>
|
<i class="global-active-color nz-icon nz-icon-refresh" style="font-size: 14px"></i>
|
||||||
<span><slot name="added-text"></slot></span>
|
<span><slot name="added-text"></slot></span>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
1400
nezha-fronted/src/components/page/dashboard/explore/exploreItem.vue
Normal file
1400
nezha-fronted/src/components/page/dashboard/explore/exploreItem.vue
Normal file
File diff suppressed because it is too large
Load Diff
404
nezha-fronted/src/components/page/dashboard/explore/logTab.vue
Normal file
404
nezha-fronted/src/components/page/dashboard/explore/logTab.vue
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
<template>
|
||||||
|
<div class="log-detail">
|
||||||
|
<div id="logChart" class="log-chart">
|
||||||
|
<!-- <chart ref="logChart" :unit="unit" chart-type="logBar" :show-toolbox="false"></chart>-->
|
||||||
|
</div>
|
||||||
|
<div class="log-operations">
|
||||||
|
<div class="log-operation">
|
||||||
|
<span class="operation-label">{{$t('overall.time')}}</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="time"
|
||||||
|
:active-color="theme.themeColor"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</div>
|
||||||
|
<div class="log-operation">
|
||||||
|
<span class="operation-label">{{$t('dashboard.explore.descending')}}</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="operations.descending"
|
||||||
|
:active-color="theme.themeColor"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</div>
|
||||||
|
<div class="log-operation">
|
||||||
|
<span class="operation-label">{{$t('dashboard.explore.wrapLines')}}</span>
|
||||||
|
<el-switch
|
||||||
|
v-model="wrapLines"
|
||||||
|
:active-color="theme.themeColor"
|
||||||
|
>
|
||||||
|
</el-switch>
|
||||||
|
</div>
|
||||||
|
<div class="log-operation">
|
||||||
|
<span class="operation-label">{{$t('overall.limit')}}:</span>
|
||||||
|
<el-select v-model="operations.limit" size="small" style="width: 100px;">
|
||||||
|
<el-option v-for="option in limitOptions" :key="option" :value="option"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
<div class="log-operation">
|
||||||
|
<span class="operation-label">Result:</span>
|
||||||
|
<span>{{tableData.length}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="log-operation log-operation--right">
|
||||||
|
<button class="top-tool-btn" type="button" @click="exportLog"><i class="nz-icon nz-icon-download"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="log-table">
|
||||||
|
<el-table
|
||||||
|
:cell-class-name="wrapLines ? '': 'log-row-wrap--no-wrap'"
|
||||||
|
:data="tableData"
|
||||||
|
:show-header="false"
|
||||||
|
class="nz-table2"
|
||||||
|
size="mini"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
type="expand"
|
||||||
|
>
|
||||||
|
<template slot-scope="{ row }">
|
||||||
|
<pre>{{row.labels}}</pre>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-if="time"
|
||||||
|
prop="timestamp"
|
||||||
|
width="140"
|
||||||
|
>
|
||||||
|
<template slot-scope="{ row }">{{row.timestamp}}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="message"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
import axios from 'axios'
|
||||||
|
export default {
|
||||||
|
name: 'logTab',
|
||||||
|
props: {
|
||||||
|
unit: Number,
|
||||||
|
logData: Array
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tableTimeFormat () {
|
||||||
|
return this.timeFormat
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
operations: {
|
||||||
|
levels: [0, 1, 2, 3, 4, 5, 6],
|
||||||
|
limit: 1000,
|
||||||
|
descending: true
|
||||||
|
},
|
||||||
|
time: true, // 换行和时间不需要处理数据
|
||||||
|
wrapLines: true,
|
||||||
|
|
||||||
|
limitOptions: [300, 1000, 3000, 10000],
|
||||||
|
levelOptions: [
|
||||||
|
{
|
||||||
|
type: 'trace',
|
||||||
|
keywords: ['trace'],
|
||||||
|
color: '#6ed0e0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'debug',
|
||||||
|
keywords: ['debug', 'dbug'],
|
||||||
|
color: '#1f78c1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'info',
|
||||||
|
keywords: ['info', 'information', 'informational', 'notice'],
|
||||||
|
color: '#7eb26d'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'warn',
|
||||||
|
keywords: ['warn', 'warning'],
|
||||||
|
color: '#ff851b'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'error',
|
||||||
|
keywords: ['error', 'err'],
|
||||||
|
color: '#e24d42'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'fatal',
|
||||||
|
keywords: ['emerg', 'critical', 'fatal', 'crit'],
|
||||||
|
color: '#705da0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'unknown',
|
||||||
|
keywords: [],
|
||||||
|
color: '#dde4ed'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableData: [],
|
||||||
|
timeFormatData: [],
|
||||||
|
tableChartData: [],
|
||||||
|
myChart: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
exportLog () {
|
||||||
|
this.$emit('exportLog', this.operations)
|
||||||
|
},
|
||||||
|
timeFormat (timestamp) {
|
||||||
|
const timeLength = `${timestamp}`.length
|
||||||
|
// 判断时间是秒/毫秒/微秒/纳秒
|
||||||
|
let step = null
|
||||||
|
switch (timeLength) {
|
||||||
|
case 10:
|
||||||
|
step = 1000
|
||||||
|
break
|
||||||
|
case 13:
|
||||||
|
step = 1
|
||||||
|
break
|
||||||
|
case 16:
|
||||||
|
step = 0.001
|
||||||
|
break
|
||||||
|
case 19:
|
||||||
|
step = 0.000001
|
||||||
|
break
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
return this.utcTimeToTimezoneStr(timestamp * step)
|
||||||
|
},
|
||||||
|
loadChart () {
|
||||||
|
this.myChart = echarts.init(document.getElementById('logChart'))
|
||||||
|
if (this.tableChartData.length > 0) {
|
||||||
|
let series = this.tableChartData.map(d => ({
|
||||||
|
type: 'bar',
|
||||||
|
name: d.name,
|
||||||
|
stack: 'total',
|
||||||
|
barWidth: 6,
|
||||||
|
data: d.data.map(item => [item[0], item[1]]),
|
||||||
|
itemStyle: { color: this.levelOptions.find(l => l.type === d.name).color }
|
||||||
|
}))
|
||||||
|
series = series.sort((a, b) => {
|
||||||
|
return this.levelOptions.findIndex(l => a.name === l.type) - this.levelOptions.findIndex(l => b.name === l.type)
|
||||||
|
})
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 60,
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
bottom: 20,
|
||||||
|
left: 10
|
||||||
|
},
|
||||||
|
series,
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
axisTick: { show: false },
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 0,
|
||||||
|
fontSize: 13 * window.devicePixelRatio,
|
||||||
|
formatter: '{HH}:{mm}:{ss}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 13 * window.devicePixelRatio,
|
||||||
|
formatter (value, i) {
|
||||||
|
let y
|
||||||
|
if (value < 1000) {
|
||||||
|
y = value
|
||||||
|
} else if (value < 1000000) {
|
||||||
|
y = value / 1000 + ' K'
|
||||||
|
} else if (value >= 1000000) {
|
||||||
|
y = value / 1000000 + ' M'
|
||||||
|
} else {
|
||||||
|
y = value / 1000000000 + ' G'
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
useUTC: false // 使用本地时间
|
||||||
|
}
|
||||||
|
this.myChart.setOption(option)
|
||||||
|
/* 点击legend
|
||||||
|
* 1.当前如果是全高亮状态,则全部置灰,只留被点击的legend高亮
|
||||||
|
* 2.如果点击的是唯一高亮的legend,则变为全高亮状态
|
||||||
|
* 3.否则只改变被点击的legend状态
|
||||||
|
* */
|
||||||
|
this.myChart.on('legendselectchanged', ({ name, selected }) => {
|
||||||
|
const selectedLevel = []
|
||||||
|
const unselectedLevel = []
|
||||||
|
for (const n in selected) {
|
||||||
|
selected[n] ? selectedLevel.push(n) : unselectedLevel.push(n)
|
||||||
|
}
|
||||||
|
// 1.
|
||||||
|
if (selectedLevel.length + unselectedLevel.length > 1) {
|
||||||
|
if (unselectedLevel.length === 1 && unselectedLevel[0] === name) {
|
||||||
|
selectedLevel.forEach(l => {
|
||||||
|
this.myChart.dispatchAction({
|
||||||
|
type: 'legendInverseSelect'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else if (selectedLevel.length === 0) { // 2.
|
||||||
|
this.myChart.dispatchAction({
|
||||||
|
type: 'legendAllSelect'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
applyFilter (allTableData, filter) {
|
||||||
|
let data = [...allTableData]
|
||||||
|
// 过滤level
|
||||||
|
data = data.filter(d => {
|
||||||
|
const hit = filter.levels.some(l => {
|
||||||
|
return this.levelOptions[l].type === d.level.toLowerCase()
|
||||||
|
})
|
||||||
|
return hit
|
||||||
|
})
|
||||||
|
// limit
|
||||||
|
data = data.slice(0, filter.limit)
|
||||||
|
// 升降序
|
||||||
|
data = data.sort((a, b) => {
|
||||||
|
return filter.descending ? b.timestamp - a.timestamp : a.timestamp - b.timestamp
|
||||||
|
})
|
||||||
|
// logs内部上方的图表数据
|
||||||
|
const tableChartData = {}
|
||||||
|
data.forEach(d => {
|
||||||
|
tableChartData[d.level] || (tableChartData[d.level] = {})
|
||||||
|
tableChartData[d.level][`${d.timestamp}`] ? tableChartData[d.level][`${d.timestamp}`]++ : tableChartData[d.level][`${d.timestamp}`] = 1
|
||||||
|
})
|
||||||
|
const temp = []
|
||||||
|
for (const d in tableChartData) {
|
||||||
|
const level = { name: d, data: [] }
|
||||||
|
for (const time in tableChartData[d]) {
|
||||||
|
level.data.push([time, tableChartData[d][time]])
|
||||||
|
}
|
||||||
|
temp.push(level)
|
||||||
|
}
|
||||||
|
return { tableData: data, tableChartData: temp }
|
||||||
|
},
|
||||||
|
filterLogType (data) {
|
||||||
|
const logData = data.filter(l => l.resultType === 'streamsFormat')
|
||||||
|
let allTableData = []
|
||||||
|
// 合并
|
||||||
|
logData.forEach(d => {
|
||||||
|
allTableData = [...allTableData, ...d.result]
|
||||||
|
})
|
||||||
|
// 去重
|
||||||
|
const temp = []
|
||||||
|
allTableData = allTableData.reduce((cur, next) => {
|
||||||
|
if (temp.indexOf(next.uuid) === -1) {
|
||||||
|
temp.push(next.uuid)
|
||||||
|
cur.push(next)
|
||||||
|
}
|
||||||
|
return cur
|
||||||
|
}, [])
|
||||||
|
// 把时间调整为毫秒,并合并同毫秒的数据
|
||||||
|
allTableData = allTableData.map(d => ({
|
||||||
|
...d,
|
||||||
|
timestamp: this.timeFormat(d.timestamp)
|
||||||
|
}))
|
||||||
|
return { logData: allTableData }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
logData: {
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
handler (n, o) {
|
||||||
|
const { logData } = this.filterLogType(n) // 过滤出不同resultType,合并去重
|
||||||
|
const { tableData, tableChartData } = this.applyFilter(logData, this.operations) // 应用operation区域的过滤项
|
||||||
|
this.tableData = tableData
|
||||||
|
this.tableChartData = tableChartData
|
||||||
|
this.loadChart()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
operations: {
|
||||||
|
deep: true,
|
||||||
|
handler (n, o) {
|
||||||
|
const { logData } = this.filterLogType(this.logData)
|
||||||
|
const { tableData, tableChartData } = this.applyFilter(logData, this.operations) // 应用operation区域的过滤项
|
||||||
|
this.tableData = tableData
|
||||||
|
this.tableChartData = tableChartData
|
||||||
|
this.loadChart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.log-detail {
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.log-table .nz-table2 {
|
||||||
|
padding: 10px 0 0 0;
|
||||||
|
|
||||||
|
.el-table__body {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0 6px;
|
||||||
|
|
||||||
|
td {
|
||||||
|
vertical-align: top;
|
||||||
|
padding: 1px 0;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
td.el-table__expanded-cell {
|
||||||
|
padding: 0 0 0 60px;
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
// 左侧边框
|
||||||
|
td:first-child {
|
||||||
|
border-left: 3px solid $--right-box-border-color;
|
||||||
|
}
|
||||||
|
td.el-table__expanded-cell:first-child {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-chart {
|
||||||
|
height: 300px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.log-operations {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 50px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 10px 0 20px;
|
||||||
|
border: 1px solid #E4E8EB;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
.log-operation {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.log-operation--right {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-label {
|
||||||
|
padding-right: 10px;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -413,6 +413,7 @@ export default {
|
|||||||
defaultTooltipFormatter: function (params) {
|
defaultTooltipFormatter: function (params) {
|
||||||
let minusFlag = true
|
let minusFlag = true
|
||||||
let str = '<div>'
|
let str = '<div>'
|
||||||
|
params instanceof Array || (params = [params])
|
||||||
params.forEach((item, i) => {
|
params.forEach((item, i) => {
|
||||||
const alias = this.queryAlias(i)
|
const alias = this.queryAlias(i)
|
||||||
if (i === 0 && alias.indexOf('Previous ') === -1) {
|
if (i === 0 && alias.indexOf('Previous ') === -1) {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const commonOption = {
|
|||||||
tooltip: { // 和 option.tooltip 的配置项相同
|
tooltip: { // 和 option.tooltip 的配置项相同
|
||||||
show: true,
|
show: true,
|
||||||
position: 'top',
|
position: 'top',
|
||||||
formatter: function (param) {
|
formatter (param) {
|
||||||
return param.title // 自定义的 DOM 结构
|
return param.title // 自定义的 DOM 结构
|
||||||
},
|
},
|
||||||
backgroundColor: 'rgba(255,255,255,0)',
|
backgroundColor: 'rgba(255,255,255,0)',
|
||||||
@@ -103,7 +103,7 @@ const commonOption = {
|
|||||||
axisLabel: {
|
axisLabel: {
|
||||||
interval: 0,
|
interval: 0,
|
||||||
rotate: 0,
|
rotate: 0,
|
||||||
formatter: function (value, index) {
|
formatter (value, index) {
|
||||||
const tData = new Date(value)
|
const tData = new Date(value)
|
||||||
return [tData.getFullYear(), tData.getMonth() + 1, tData.getDate()].join('-') + '\n' +
|
return [tData.getFullYear(), tData.getMonth() + 1, tData.getDate()].join('-') + '\n' +
|
||||||
[tData.getHours(), tData.getMinutes()].join(':')
|
[tData.getHours(), tData.getMinutes()].join(':')
|
||||||
@@ -251,7 +251,7 @@ const alertMessageBarByRule = {
|
|||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: true,
|
show: true,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
formatter: function (value) {
|
formatter (value) {
|
||||||
if (value.length > 15) {
|
if (value.length > 15) {
|
||||||
return '...' + value.substring(value.length - 12, value.length)
|
return '...' + value.substring(value.length - 12, value.length)
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ const alertMessageBarByAsset = {
|
|||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: true,
|
show: true,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
formatter: function (value) {
|
formatter (value) {
|
||||||
let r = value
|
let r = value
|
||||||
if (r.length > 4) {
|
if (r.length > 4) {
|
||||||
r = value.substring(0, 3) + '...'
|
r = value.substring(0, 3) + '...'
|
||||||
@@ -316,7 +316,62 @@ const alertMessageBarByAsset = {
|
|||||||
triggerEvent: true
|
triggerEvent: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const logBar = {
|
||||||
|
title: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 0,
|
||||||
|
fontSize: 13 * window.devicePixelRatio
|
||||||
|
},
|
||||||
|
axisPointer: { // y轴上显示指针对应的值
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
splitLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 13 * window.devicePixelRatio,
|
||||||
|
formatter (value, i) {
|
||||||
|
let y
|
||||||
|
if (value < 1000) {
|
||||||
|
} else if (value < 1000000) {
|
||||||
|
y = value / 1000 + ' K'
|
||||||
|
} else if (value >= 1000000) {
|
||||||
|
y = value / 1000000 + ' M'
|
||||||
|
} else {
|
||||||
|
y = value / 1000000000 + ' G'
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
useUTC: false, // 使用本地时间
|
||||||
|
series: []
|
||||||
|
}
|
||||||
const overviewLine = {
|
const overviewLine = {
|
||||||
title: {
|
title: {
|
||||||
show: false
|
show: false
|
||||||
@@ -332,7 +387,7 @@ const overviewLine = {
|
|||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
confine: false,
|
confine: false,
|
||||||
extraCssText: 'z-index:1000;',
|
extraCssText: 'z-index:1000;',
|
||||||
formatter: function (v, i) {
|
formatter (v, i) {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -375,7 +430,7 @@ const overviewLine = {
|
|||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
fontSize: 13 * window.devicePixelRatio,
|
fontSize: 13 * window.devicePixelRatio,
|
||||||
formatter: function (value, i) {
|
formatter (value, i) {
|
||||||
let y
|
let y
|
||||||
if (value < 1000) {
|
if (value < 1000) {
|
||||||
y = value + ' Bs'
|
y = value + ' Bs'
|
||||||
@@ -524,22 +579,23 @@ const chartTypes = {
|
|||||||
bar: { name: 'alertMessage', option: alertMessageBarByAsset },
|
bar: { name: 'alertMessage', option: alertMessageBarByAsset },
|
||||||
ruleBar: { name: 'ruleMessage', option: alertMessageBarByRule },
|
ruleBar: { name: 'ruleMessage', option: alertMessageBarByRule },
|
||||||
assetBar: { name: 'assetMessage', option: alertMessageBarByAsset },
|
assetBar: { name: 'assetMessage', option: alertMessageBarByAsset },
|
||||||
|
logBar: { name: 'logBar', option: logBar },
|
||||||
noData: { name: 'noData', option: noDataOption },
|
noData: { name: 'noData', option: noDataOption },
|
||||||
tooltipPie: { option: tooltipPieOption },
|
tooltipPie: { option: tooltipPieOption },
|
||||||
topoPie: { option: topoPieOption }
|
topoPie: { option: topoPieOption }
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
getOption: function (type) {
|
getOption (type) {
|
||||||
return JSON.parse(JSON.stringify(chartTypes[type].option))
|
return JSON.parse(JSON.stringify(chartTypes[type].option))
|
||||||
},
|
},
|
||||||
getOptionNoData: function (type) {
|
getOptionNoData (type) {
|
||||||
chartTypes[type].option.xAxis.data = createTempTimes()
|
chartTypes[type].option.xAxis.data = createTempTimes()
|
||||||
return JSON.parse(JSON.stringify(chartTypes[type].option))
|
return JSON.parse(JSON.stringify(chartTypes[type].option))
|
||||||
},
|
},
|
||||||
setMap: function (map) {
|
setMap (map) {
|
||||||
mapOptions.geo.map = map
|
mapOptions.geo.map = map
|
||||||
},
|
},
|
||||||
getBgColorList: function () {
|
getBgColorList () {
|
||||||
return Object.assign([], bgColorList)
|
return Object.assign([], bgColorList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<pick-time id="panel" ref="pickTime" v-model="searchTime" :refresh-data-func="dateChange" :use-chart-unit="false"></pick-time>
|
<pick-time id="panel" ref="pickTime" v-model="searchTime" :refresh-data-func="dateChange" :use-chart-unit="false" class="margin-r-10"></pick-time>
|
||||||
|
|
||||||
<button id="panel-add-chart" v-has="'panel_chart_add'" :title="$t('overall.createChart')" class="top-tool-btn margin-r-10"
|
<button id="panel-add-chart" v-has="'panel_chart_add'" :title="$t('overall.createChart')" class="top-tool-btn margin-r-10"
|
||||||
type="button" @click="addChart">
|
type="button" @click="addChart">
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export default new Router({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/explore',
|
path: '/explore',
|
||||||
component: resolve => require(['../components/page/dashboard/explore/explore.vue'], resolve)
|
component: resolve => require(['@/components/page/dashboard/explore/explore'], resolve)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/overview',
|
path: '/overview',
|
||||||
|
|||||||
Reference in New Issue
Block a user