NEZ-2550 feat: endpoint 故障诊断页面开发
This commit is contained in:
106
nezha-fronted/src/assets/css/components/common/diagnosisTab.scss
Normal file
106
nezha-fronted/src/assets/css/components/common/diagnosisTab.scss
Normal file
@@ -0,0 +1,106 @@
|
||||
#diagnosisTab{
|
||||
.el-dialog__header{
|
||||
padding: 16px 20px;
|
||||
.el-dialog__title{
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
border-bottom: 1px solid $--border-color-light;
|
||||
}
|
||||
.el-dialog__body{
|
||||
padding: 0;
|
||||
.dialog-header{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-left: 30px;
|
||||
padding-right: 38px;
|
||||
border-bottom: 1px solid $--border-color-light;
|
||||
background: $--background-color-base;
|
||||
font-size: 12px;
|
||||
color:$--color-text-regular;
|
||||
.dialog-header-l{
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
i.nz-icon{
|
||||
font-size: 72px;
|
||||
color: #AEB8C2;
|
||||
margin-right: 11px;
|
||||
}
|
||||
.dialog-header-name{
|
||||
font-size: 14px;
|
||||
letter-spacing: 0;
|
||||
line-height: 22px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.dialog-header-item{
|
||||
text-transform: uppercase;
|
||||
color: $--color-text-secondary;
|
||||
span{
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.diagnosis-table{
|
||||
padding-left: 20px;
|
||||
#diagnosisTable{
|
||||
&::before{
|
||||
display: none;
|
||||
}
|
||||
.has-gutter{
|
||||
display: none;
|
||||
}
|
||||
.el-table__expand-icon{
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.el-table__expand-icon--expanded{
|
||||
color: $--color-primary;
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
td.el-table__expanded-cell {
|
||||
padding: 15px 0 15px 45px;
|
||||
background-color: $--background-color-empty !important;
|
||||
}
|
||||
td.el-table__expanded-cell:hover {
|
||||
padding: 15px 0 15px 45px;
|
||||
background-color: $--background-color-base !important;
|
||||
}
|
||||
.expand-details{
|
||||
color: $--color-primary;
|
||||
}
|
||||
.el-table__body {
|
||||
tr{
|
||||
background: $--background-color-empty;
|
||||
td{
|
||||
border-color: $--border-color-light;
|
||||
}
|
||||
&:nth-last-of-type(1){
|
||||
td{
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.el-table--enable-row-hover .el-table__body tr:hover>td{
|
||||
background-color: $--background-color-base !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.my-loading-box{
|
||||
opacity: 1 !important;
|
||||
}
|
||||
}
|
||||
.el-dialog__footer{
|
||||
border-top: 1px solid $--border-color-light;
|
||||
padding: 13px 20px;
|
||||
margin-top: 0;
|
||||
#diagnosis-cancel{
|
||||
padding: 0 11px;
|
||||
margin-right: 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,7 @@
|
||||
@import './common/searchInput.scss';
|
||||
@import './common/timePicker.scss';
|
||||
@import './common/deleteButton.scss';
|
||||
@import './common/diagnosisTab.scss';
|
||||
@import './common/filterSearch/filterSearch.scss';
|
||||
@import './common/panel/panelVariables.scss';
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -6,7 +6,13 @@
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
"icon_id": "34053254",
|
||||
"name": "编组 2",
|
||||
"font_class": "Diagnosis1",
|
||||
"unicode": "e7d1",
|
||||
"unicode_decimal": 59345
|
||||
},
|
||||
{
|
||||
"icon_id": "33998082",
|
||||
"name": "右纵轴",
|
||||
"font_class": "youzongzhou",
|
||||
@@ -21,8 +27,6 @@
|
||||
"unicode_decimal": 59343
|
||||
},
|
||||
{
|
||||
=======
|
||||
>>>>>>> 61106c08d5bd1c9b7263e6b915880385934c3c7d
|
||||
"icon_id": "33991102",
|
||||
"name": "全部收起",
|
||||
"font_class": "quanbushouqi",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
238
nezha-fronted/src/components/common/diagnosisTab.vue
Normal file
238
nezha-fronted/src/components/common/diagnosisTab.vue
Normal file
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog
|
||||
ref="diagnosisDialog"
|
||||
v-if="dialogVisible"
|
||||
id="diagnosisTab"
|
||||
class="diagnosisTab"
|
||||
:title="$t('overall.diagnosis')"
|
||||
:visible.sync="dialogVisible"
|
||||
@close='handleClose'
|
||||
width="780px"
|
||||
:modal-append-to-body="true"
|
||||
:append-to-body="true"
|
||||
>
|
||||
<div style="position: relative;">
|
||||
<!-- 头部 -->
|
||||
<div class="dialog-header" style="vertical-align:top;">
|
||||
<div class="dialog-header-l">
|
||||
<i class="nz-icon nz-icon-Diagnosis1"></i>
|
||||
<div>
|
||||
<div class="dialog-header-name">{{$t('project.endpoint.endpointName')}}</div>
|
||||
<div v-html="suspendedStr(diagnosisTabData.row.configs[0].state)" class="dialog-header-item">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-header-r">{{$t('overall.serviceTime')}}:{{secondFormatter(elapsedTime)}}</div>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="diagnosis-table">
|
||||
<el-table
|
||||
id="diagnosisTable"
|
||||
ref="dataTable"
|
||||
:height="'286px'"
|
||||
:data="tableData"
|
||||
>
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableTitle"
|
||||
:key="`col-${index}`"
|
||||
:label="item.label"
|
||||
:min-width="`${item.minWidth}`"
|
||||
:prop="item.prop"
|
||||
:resizable="true"
|
||||
:width="`${item.width}`"
|
||||
class="data-column"
|
||||
>
|
||||
<template slot="header">
|
||||
<span class="data-column__span">{{item.label}}</span>
|
||||
<div class="col-resize-area"></div>
|
||||
</template>
|
||||
<template slot-scope="scope" :column="item">
|
||||
<template v-if="item.prop === 'state'">
|
||||
<div>
|
||||
<i v-if="scope.row[item.prop] == 1" class="nz-icon nz-icon-import-success1 green"></i>
|
||||
<i v-else-if="scope.row[item.prop] == 2" class="nz-icon nz-icon-import-failed1 red"></i>
|
||||
<i v-else class="nz-icon nz-icon-stop" style="color:#BEBEBE;"></i>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</template>
|
||||
<template v-else>-</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column type="expand">
|
||||
<template slot-scope="{ row }">
|
||||
<div class="expand-details">
|
||||
<pre>{{row.resolution}}</pre>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template slot="empty">
|
||||
<div class="table-no-data">
|
||||
<svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#nz-icon-no-data-list"></use>
|
||||
</svg>
|
||||
<div class="table-no-data__title">No results found</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table>
|
||||
</div>
|
||||
<loading ref="loading"></loading>
|
||||
</div>
|
||||
<!-- 底部按钮 -->
|
||||
<span slot="footer" class="dialog-footer right-box__footer batch-delete-footer">
|
||||
<div>
|
||||
<button id="diagnosis-cancel" class="footer__btn footer__btn--light" type="button" @click="dialogVisible = false">{{$t('overall.close')}}</button>
|
||||
</div>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import loading from '@/components/common/loading'
|
||||
|
||||
// 解决浏览器切换或者小化时定时器失效问题
|
||||
function create (f) {
|
||||
const blob = new Blob(['(' + f + ')()'])
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const worker = new Worker(url)
|
||||
return worker
|
||||
}
|
||||
const createWorker = (callback, time) => {
|
||||
const pollingWorker = create(`function (e) {
|
||||
setInterval(function () {
|
||||
this.postMessage(null)
|
||||
}, ${time})
|
||||
}`)
|
||||
pollingWorker.onmessage = callback
|
||||
return pollingWorker
|
||||
}
|
||||
const stopWorker = (vm) => {
|
||||
try {
|
||||
vm && vm.terminate()
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'diagnosisTab',
|
||||
components: { loading },
|
||||
data () {
|
||||
return {
|
||||
dialogVisible: false,
|
||||
timer: null, // 运行定时器
|
||||
elapsedTime: 0, // 运行时间
|
||||
tableData: [],
|
||||
tableTitle: [ // table列
|
||||
{
|
||||
label: 'state',
|
||||
prop: 'state',
|
||||
minWidth: 34,
|
||||
width: 34
|
||||
}, {
|
||||
label: 'name',
|
||||
prop: 'item',
|
||||
minWidth: 200
|
||||
}]
|
||||
}
|
||||
},
|
||||
props: {
|
||||
diagnosisTabData: Object
|
||||
},
|
||||
methods: {
|
||||
handleClose () {
|
||||
this.dialogVisible = false
|
||||
},
|
||||
getTableData () {
|
||||
this.$get('monitor/endpoint/diagnose/' + this.diagnosisTabData.row.id).then(response => {
|
||||
if (response.code == 200) {
|
||||
this.tableData = response.data.list
|
||||
// 关闭定时器 取消任务
|
||||
stopWorker(this.timer)
|
||||
this.$refs.loading.endLoading()
|
||||
} else {
|
||||
this.$message.error(response.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 补零
|
||||
zeroize (num) {
|
||||
return num < 10 ? '0' + num : num
|
||||
},
|
||||
// 秒转为时-分-秒(00:00:00)
|
||||
secondFormatter (millisecond) {
|
||||
const secondTime = parseInt(millisecond / 1000)
|
||||
let time = '00:00:' + this.zeroize(secondTime)
|
||||
if (secondTime > 60) {
|
||||
const second = parseInt(secondTime % 60)
|
||||
let min = parseInt(secondTime / 60)
|
||||
time = '00:' + this.zeroize(min) + ':' + this.zeroize(second)
|
||||
|
||||
if (min > 60) {
|
||||
min = parseInt(secondTime / 60 % 60)
|
||||
const hour = parseInt((secondTime / 60) / 60)
|
||||
time = this.zeroize(hour) + ':' + this.zeroize(min) + ':' + this.zeroize(second) + ':'
|
||||
}
|
||||
}
|
||||
return time
|
||||
},
|
||||
suspendedStr (status) { // 10进制转为2进制 分别给对应的状态
|
||||
if (!status || status === 1 || status == 0) { return '' }
|
||||
const arr = status.toString(2).split('')
|
||||
while (arr.length < 4) {
|
||||
arr.unshift('0')
|
||||
}
|
||||
arr.pop()
|
||||
let str = ''
|
||||
arr.forEach((item, index) => {
|
||||
if (index === 0) {
|
||||
str += `<span><i class="active-icon inline-block ${item == '0' ? 'gray-bg' : 'green-bg'}"></i> DC</span>`
|
||||
}
|
||||
if (index === 1) {
|
||||
str += `<span><i class="active-icon inline-block ${item == '0' ? 'gray-bg' : 'green-bg'}"></i> ASSET</span>`
|
||||
}
|
||||
if (index === 2) {
|
||||
str += `<span><i class="active-icon inline-block ${item == '0' ? 'gray-bg' : 'green-bg'}"></i> ENDPOINT</span>`
|
||||
}
|
||||
})
|
||||
return str
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showDiagnosisTab () {
|
||||
return this.$store.getters.getShowDiagnosisTab
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
watch: {
|
||||
// 展示弹窗
|
||||
showDiagnosisTab (n) {
|
||||
if (n) {
|
||||
this.dialogVisible = true
|
||||
// 定时获取运行时间
|
||||
this.timer = createWorker(() => {
|
||||
this.elapsedTime += 100
|
||||
}, 100)
|
||||
this.$nextTick(() => {
|
||||
this.$refs.loading.startLoading()
|
||||
this.getTableData()
|
||||
})
|
||||
}
|
||||
},
|
||||
// 关闭弹窗
|
||||
dialogVisible (n) {
|
||||
if (!n) {
|
||||
this.$store.dispatch('dispatchShowDiagnosisTab', false)
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
stopWorker(this.timer)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -93,6 +93,14 @@ export default {
|
||||
this.$emit('metricTarget', row, param)
|
||||
break
|
||||
}
|
||||
case 'diagnosis': {
|
||||
this.$store.dispatch('diagnosisTab', {
|
||||
row: row,
|
||||
url: this.api,
|
||||
...param
|
||||
})
|
||||
break
|
||||
}
|
||||
default:
|
||||
this.$emit(command, row, param)
|
||||
break
|
||||
|
||||
@@ -112,6 +112,11 @@
|
||||
:delete-objs="singleDelete"
|
||||
@before="delFlag=true"
|
||||
></delete-button>
|
||||
<diagnosis-tab
|
||||
ref="diagnosisTab"
|
||||
:api="diagnosisTabData.url"
|
||||
:diagnosisTabData ="diagnosisTabData"
|
||||
></diagnosis-tab>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -124,6 +129,7 @@ import bus from '@/libs/bus'
|
||||
import routerPathParams from '@/components/common/mixin/routerPathParams'
|
||||
import SearchBox from '@/components/common/searchBox/searchBox'
|
||||
import deleteButton from '@/components/common/deleteButton'
|
||||
import diagnosisTab from '@/components/common/diagnosisTab'
|
||||
export default {
|
||||
name: 'nzDataList',
|
||||
mixins: [routerPathParams],
|
||||
@@ -131,7 +137,8 @@ export default {
|
||||
SearchBox,
|
||||
bottomBox,
|
||||
panelChart,
|
||||
deleteButton
|
||||
deleteButton,
|
||||
diagnosisTab
|
||||
},
|
||||
props: {
|
||||
from: {
|
||||
@@ -179,6 +186,9 @@ export default {
|
||||
},
|
||||
deleteTableRel () {
|
||||
return this.$store.getters.getDeleteTableRel
|
||||
},
|
||||
diagnosisTab () {
|
||||
return this.$store.getters.getDiagnosisTab
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -207,7 +217,9 @@ export default {
|
||||
showCustomTableTitle: false // 自定义列弹框是否显示
|
||||
},
|
||||
showLayout: [],
|
||||
timeRange: [new Date(), new Date()]
|
||||
timeRange: [new Date(), new Date()],
|
||||
// 故障诊断数据
|
||||
diagnosisTabData: {}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
@@ -294,6 +306,9 @@ export default {
|
||||
if (n) {
|
||||
this.delTableRelRow(this.deleteTableRel.url, this.deleteTableRel.row, this.deleteTableRel.forceDeleteShow, this.deleteTableRel.single, this.deleteTableRel.deleteTitle)
|
||||
}
|
||||
},
|
||||
diagnosisTab (n) {
|
||||
this.diagnosisTabData = n
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
<el-dropdown-item v-has="'monitor_endpoint_edit'" :command="['copy', scope.row, 'project']"><i class="nz-icon nz-icon-override"></i><span class="operation-dropdown-text">{{$t('overall.duplicate')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'alertSilence_add'" :command="['fastSilence', scope.row, 'endpoint']"><i class="nz-icon nz-icon-fast-silence"></i><span class="operation-dropdown-text">{{$t('overall.silenceAlert')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'asset_add'" :command="['topology', scope.row, 'endpoint']"><i class="nz-icon nz-icon-Topology"></i><span class="operation-dropdown-text">{{$t('overall.topology')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'asset_add'" :command="['diagnosis', scope.row]"><i class="nz-icon nz-icon-diagnosis"></i><span class="operation-dropdown-text">{{$t('overall.diagnosis')}}</span></el-dropdown-item>
|
||||
<el-dropdown-item v-has="'monitor_endpoint_add'" :command="['metricTarget', scope.row, 'endpoint']" :disabled="scope.row.configs[0].config.protocol !== ('http'||'https')"><i class="nz-icon nz-icon-Metrics"></i><span class="operation-dropdown-text">{{$t('endpoints.metricTarget')}}</span></el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
@@ -210,13 +211,11 @@ import table from '@/components/common/mixin/table'
|
||||
import alertLabel from '../../alert/alertLabel'
|
||||
import nzTooltip from '../../alert/nzTooltip'
|
||||
import alertLabelMixin from '@/components/common/mixin/alertLabelMixin'
|
||||
import deleteButton from '@/components/common/deleteButton'
|
||||
export default {
|
||||
name: 'endpointTable',
|
||||
components: {
|
||||
alertLabel,
|
||||
nzTooltip,
|
||||
deleteButton
|
||||
nzTooltip
|
||||
},
|
||||
mixins: [table, alertLabelMixin],
|
||||
props: {
|
||||
|
||||
@@ -50,7 +50,9 @@ const store = new Vuex.Store({
|
||||
nowPath: '',
|
||||
myEvent: new Event('resize'),
|
||||
deleteTableRel: {},
|
||||
showDeleteTableRel: false
|
||||
showDeleteTableRel: false,
|
||||
diagnosisTab: {}, // 故障诊断
|
||||
showDiagnosisTab: false
|
||||
},
|
||||
getters: {
|
||||
getGlobalSearchId (state) {
|
||||
@@ -112,6 +114,12 @@ const store = new Vuex.Store({
|
||||
},
|
||||
getShowDeleteTableRel (state) {
|
||||
return state.showDeleteTableRel
|
||||
},
|
||||
getDiagnosisTab (state) {
|
||||
return state.diagnosisTab
|
||||
},
|
||||
getShowDiagnosisTab (state) {
|
||||
return state.showDiagnosisTab
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
@@ -228,6 +236,12 @@ const store = new Vuex.Store({
|
||||
if (!flag) {
|
||||
state.deleteTableRel = {}
|
||||
}
|
||||
},
|
||||
setDiagnosisTab (state, payload) {
|
||||
state.diagnosisTab = payload
|
||||
},
|
||||
setShowDiagnosisTab (state, flag) {
|
||||
state.showDiagnosisTab = flag
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@@ -237,6 +251,13 @@ const store = new Vuex.Store({
|
||||
},
|
||||
dispatchShowDeleteTableRel (store, flag) {
|
||||
store.commit('setShowDeleteTableRel', flag)
|
||||
},
|
||||
diagnosisTab (store, payload) { // 故障诊断
|
||||
store.commit('setDiagnosisTab', payload)
|
||||
store.commit('setShowDiagnosisTab', true)
|
||||
},
|
||||
dispatchShowDiagnosisTab (store, flag) {
|
||||
store.commit('setShowDiagnosisTab', flag)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user