NEZ-1592 feat:asset等列表页面增加 最近告警趋势 图表(70%)
This commit is contained in:
@@ -3,3 +3,4 @@
|
||||
@import './tableCommon.scss';
|
||||
@import './rightBoxCommon.scss';
|
||||
@import './tooltip.scss';
|
||||
@import './loading.scss';
|
||||
|
||||
78
nezha-fronted/src/assets/css/common/loading.scss
Normal file
78
nezha-fronted/src/assets/css/common/loading.scss
Normal file
@@ -0,0 +1,78 @@
|
||||
// https://github.com/loadingio/css-spinner/tree/master/dist 从当前链接现在在 在tools.js 的myLoading 进行判断处理
|
||||
// 高度 宽度 等细节 记得处理
|
||||
// 1
|
||||
.lds-dual-ring,
|
||||
.lds-dual-ring:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.lds-dual-ring {
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
.lds-dual-ring:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 8px;
|
||||
border-radius: 50%;
|
||||
border: 6.4px solid currentColor;
|
||||
border-color: currentColor transparent currentColor transparent;
|
||||
animation: lds-dual-ring 1.2s linear infinite;
|
||||
}
|
||||
@keyframes lds-dual-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
// 2
|
||||
.ldsFacebook,
|
||||
.ldsFacebook div {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.ldsFacebook {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 32px;
|
||||
}
|
||||
.ldsFacebook div {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
width: 8px;
|
||||
background: $--background-color-empty;
|
||||
animation: ldsFacebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
|
||||
}
|
||||
.ldsFacebook div:nth-child(1) {
|
||||
left: 8px;
|
||||
background: $--background-color-empty;
|
||||
filter: invert(50%);
|
||||
animation-delay: -0.24s;
|
||||
}
|
||||
.ldsFacebook div:nth-child(2) {
|
||||
left: 20px;
|
||||
background: $--background-color-empty;
|
||||
filter: invert(50%);
|
||||
animation-delay: -0.12s;
|
||||
}
|
||||
.ldsFacebook div:nth-child(3) {
|
||||
left: 32px;
|
||||
background: $--background-color-empty;
|
||||
filter: invert(50%);
|
||||
animation-delay: 0s;
|
||||
}
|
||||
@keyframes ldsFacebook {
|
||||
0% {
|
||||
top: 8px;
|
||||
height: 32px;
|
||||
}
|
||||
50%, 100% {
|
||||
top: 12px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
.alert-days-info{
|
||||
display: flex;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
> div{
|
||||
width: 14px;
|
||||
height: 24px;
|
||||
margin-right: 5px;
|
||||
border-radius: 2px;
|
||||
background-color:$--color-success;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
@import './common/alert/alertLabel.scss';
|
||||
@import './common/alert/alertRuleInfo.scss';
|
||||
@import './common/alert/selectAlertSilence.scss';
|
||||
@import './common/alert/alertDaysInfo.scss';
|
||||
@import './common/bottomBox/bottomBox.scss';
|
||||
@import './common/bottomBox/panelTabNew.scss';
|
||||
@import './common/bottomBox/terminalLogCMDTab.scss';
|
||||
|
||||
75
nezha-fronted/src/components/common/alert/alertDaysInfo.vue
Normal file
75
nezha-fronted/src/components/common/alert/alertDaysInfo.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="alert-days-info">
|
||||
<!-- {{timestampStr(item.time, 'YYYY-MM-DD')}} {{item.P1+' '+item.P2+' '+item.P3}}-->
|
||||
<div v-for="item in daysData" :key="item.time" :style="showPriority(item)">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'alertDaysInfo',
|
||||
props: {
|
||||
alertDaysData: Array
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
daysData: [],
|
||||
severityData: this.$store.getters.severityData,
|
||||
severityDataWeight: this.$store.getters.severityDataWeight
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
alertDaysData: {
|
||||
immediate: true,
|
||||
handler () {
|
||||
this.getWeeksTime()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getWeeksTime () {
|
||||
const localOffset = new Date().getTimezoneOffset() // 默认 显示时区偏移的结果 单位分钟
|
||||
const now = new Date(new Date().toLocaleDateString()).getTime() - localOffset * 60 * 1000
|
||||
const arr = []
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const obj = {
|
||||
time: now - i * 24 * 60 * 60 * 1000
|
||||
}
|
||||
this.severityDataWeight.forEach(item => {
|
||||
obj[item.name] = 0
|
||||
})
|
||||
console.log(obj)
|
||||
arr.unshift(obj)
|
||||
}
|
||||
this.alertDaysData.forEach(item => {
|
||||
item.values.forEach(time => {
|
||||
const findItem = arr.find(days => days.time == time[0])
|
||||
// console.log(item)
|
||||
if (findItem) {
|
||||
findItem[item.metric.priority] = time[1]
|
||||
}
|
||||
})
|
||||
})
|
||||
this.daysData = arr
|
||||
},
|
||||
showPriority (daysData) {
|
||||
let style = ''
|
||||
this.severityDataWeight.forEach(item => {
|
||||
if (daysData[item.name] && !style) {
|
||||
style = {
|
||||
background: item.color
|
||||
}
|
||||
}
|
||||
})
|
||||
console.log(daysData,style)
|
||||
return style
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -98,6 +98,61 @@ function isEqual (o1, o2) {
|
||||
}
|
||||
return isEqualForInner(o1, o2)
|
||||
}
|
||||
export const myLoading = {
|
||||
bind: myLoadingFunction,
|
||||
update: myLoadingFunction,
|
||||
unbind: function (el, binding) {
|
||||
const className = binding.arg || 'el-loading-mask'
|
||||
const ds = el.getElementsByClassName(className)[0]
|
||||
if (ds) {
|
||||
el.removeChild(ds)
|
||||
}
|
||||
}
|
||||
}
|
||||
function myLoadingFunction (el, binding, vnode) {
|
||||
const className = binding.arg || 'el-loading-mask'
|
||||
const ds = el.getElementsByClassName(className)[0]
|
||||
if (binding.value) {
|
||||
if (ds) {
|
||||
return
|
||||
}
|
||||
// 若果是true创建一个div
|
||||
const div = document.createElement('div')
|
||||
div.style.textAlign = 'center'
|
||||
if (binding.modifiers.scaleMin) {
|
||||
div.style.transform = 'scale(0.5)'
|
||||
}
|
||||
if (binding.modifiers.scaleMax) {
|
||||
div.style.transform = 'scale(2)'
|
||||
}
|
||||
if (className === 'ldsFacebook') {
|
||||
const newDiv1 = document.createElement('div')
|
||||
const newDiv2 = document.createElement('div')
|
||||
const newDiv3 = document.createElement('div')
|
||||
div.appendChild(newDiv1)
|
||||
div.appendChild(newDiv2)
|
||||
div.appendChild(newDiv3)
|
||||
}
|
||||
if (className === 'el-loading-mask') {
|
||||
const newDiv1 = document.createElement('div')
|
||||
newDiv1.setAttribute('class', 'el-loading-spinner')
|
||||
div.appendChild(newDiv1)
|
||||
}
|
||||
// 插入到被绑定的元素内部
|
||||
el.appendChild(div)
|
||||
// div内部加入内容
|
||||
// div.innerHTML = '加载中...'
|
||||
// el 元素设置相对定位 div设置绝对定位
|
||||
el.setAttribute('class', 'elrelative')
|
||||
// 设置绝对定位
|
||||
div.setAttribute('class', className)
|
||||
} else {
|
||||
// 去掉div 去掉样式 去掉定位
|
||||
if (ds) {
|
||||
el.removeChild(ds)
|
||||
}
|
||||
}
|
||||
}
|
||||
export const cancelWithChange = {
|
||||
bind: function (el, binding) {
|
||||
if (!binding.value || !binding.value.obj) return
|
||||
|
||||
@@ -43,7 +43,13 @@
|
||||
<span style="cursor: pointer" @click="$emit('showBottomBox', 'endpointTab', scope.row)"><i class="nz-icon nz-icon-overview-endpoint monitorColor"></i> <span>{{scope.row.endpointNum ? scope.row.endpointNum : 0}}</span></span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'alertNum'">
|
||||
<span style="cursor: pointer" @click="$emit('showBottomBox', 'alertMessageTab', scope.row)"><i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert"></i> <span>{{scope.row.alertNum ? scope.row.alertNum : 0}}</span></span>
|
||||
<span style="cursor: pointer" @click="$emit('showBottomBox', 'alertMessageTab', scope.row)" v-myLoading:ldsFacebook="scope.row.trendLoading">
|
||||
<!-- <i :class="scope.row.alertNum ? 'red' : 'green'" class="nz-icon nz-icon-overview-alert"></i> <span>{{scope.row.alertNum ? scope.row.alertNum : 0}}</span>-->
|
||||
<alertDaysInfo
|
||||
v-if="scope.row.alertDaysData"
|
||||
:alertDaysData="scope.row.alertDaysData"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'dc'">{{scope.row.dc ? scope.row.dc.name : '-'}}</template>
|
||||
<template v-else-if="item.prop === 'cabinet'">
|
||||
@@ -154,11 +160,13 @@ import table from '@/components/common/mixin/table'
|
||||
import { showTableTooltip, hideTableTooltip } from '@/components/common/js/tools'
|
||||
// import bus from '@/libs/bus'
|
||||
import alertLabel from '@/components/common/alert/alertLabel'
|
||||
import alertDaysInfo from '@/components/common/alert/alertDaysInfo'
|
||||
export default {
|
||||
name: 'assetTable',
|
||||
mixins: [table],
|
||||
components: {
|
||||
alertLabel: alertLabel
|
||||
alertLabel: alertLabel,
|
||||
alertDaysInfo
|
||||
},
|
||||
props: {
|
||||
showOption: {
|
||||
|
||||
@@ -432,7 +432,9 @@ export default {
|
||||
index: -1
|
||||
}
|
||||
},
|
||||
timer: ''
|
||||
timer: '',
|
||||
needAlertDaysData: true,
|
||||
trendKey: 'assetId'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -713,6 +715,27 @@ export default {
|
||||
for (let i = 0; i < response.data.list.length; i++) {
|
||||
response.data.list[i].status = response.data.list[i].status + ''
|
||||
}
|
||||
if (this.needAlertDaysData) {
|
||||
console.log(123123123123)
|
||||
const arr = []
|
||||
response.data.list.forEach(item => {
|
||||
item.trendLoading = true
|
||||
const params = {
|
||||
type: 'total',
|
||||
dimension: 'priority',
|
||||
step: 'd'
|
||||
}
|
||||
params[this.trendKey] = item.id
|
||||
arr.push(this.$get('/stat/alertMessage/trend', params))
|
||||
})
|
||||
Promise.all(arr).then(res => {
|
||||
response.data.list.forEach((item, index) => {
|
||||
item.trendLoading = false
|
||||
item.alertDaysData = res[index].data.result ? res[index].data.result[0].values : []
|
||||
})
|
||||
this.tableData = response.data.list
|
||||
})
|
||||
}
|
||||
this.tableData = response.data.list
|
||||
const globalSearchId = this.$store.getters.getGlobalSearchId
|
||||
let detailViewRightObj = ''
|
||||
|
||||
@@ -19,7 +19,7 @@ import plTable from 'pl-table'
|
||||
import 'pl-table/themes/index.css'
|
||||
|
||||
import { post, get, put, del } from './http.js'
|
||||
import { clickoutside, bottomBoxWindow, stringTimeParseToUnix, unixTimeParseToString, chartResizeTool, tableSet, cancelWithChange } from './components/common/js/tools.js'
|
||||
import { clickoutside, bottomBoxWindow, stringTimeParseToUnix, unixTimeParseToString, chartResizeTool, tableSet, cancelWithChange, myLoading } from './components/common/js/tools.js'
|
||||
import * as tools from './components/common/js/tools.js'
|
||||
import * as constants from './components/common/js/constants.js'
|
||||
|
||||
@@ -122,12 +122,15 @@ Vue.mixin({
|
||||
return bus.timeFormate(this.timezoneToUtcTime(time), fmt)
|
||||
}
|
||||
},
|
||||
timestampStr: function (time) {
|
||||
timestampStr: function (time, fmt) {
|
||||
const date = new Date(time)
|
||||
const localOffset = date.getTimezoneOffset() * 60 * 1000 // 默认 一分钟显示时区偏移的结果
|
||||
const dateStr = new Date(time).getTime() + localOffset
|
||||
if (!fmt) {
|
||||
fmt = localStorage.getItem('nz-default-dateFormat') || 'YYYY-MM-DD HH:mm:ss'
|
||||
}
|
||||
if (time) {
|
||||
return bus.timeFormate(bus.UTCTimeToConfigTimezone(dateStr), localStorage.getItem('nz-default-dateFormat') ? localStorage.getItem('nz-default-dateFormat') : 'YYYY-MM-DD HH:mm:ss')
|
||||
return bus.timeFormate(bus.UTCTimeToConfigTimezone(dateStr), fmt)
|
||||
} else {
|
||||
return '-'
|
||||
}
|
||||
@@ -238,6 +241,7 @@ Vue.use(hasPermission)
|
||||
/* 指令 */
|
||||
Vue.directive('cancel', cancelWithChange)
|
||||
Vue.directive('clickoutside', clickoutside)
|
||||
Vue.directive('myLoading', myLoading)
|
||||
window.resizing = false
|
||||
window.vm = new Vue({
|
||||
el: '#app',
|
||||
|
||||
@@ -144,6 +144,13 @@ router.beforeEach((to, from, next) => {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
Vue.http.get(configUrl).then(config => {
|
||||
get(config.body.baseUrl + 'alert/severity', { pageNo: 1, pageSize: -1 }).then(response => {
|
||||
if (response.code == 200) {
|
||||
store.commit('setSeverityData', response.data.list)
|
||||
}
|
||||
})
|
||||
})
|
||||
Promise.all([i18nRequest, permissionRequest]).then(response => {
|
||||
if (to.path) {
|
||||
if (permissionWhiteList.indexOf(to.path) !== -1) {
|
||||
|
||||
@@ -10,7 +10,9 @@ const user = {
|
||||
menuList: [],
|
||||
buttonList: [],
|
||||
roleList: [],
|
||||
language: localStorage.getItem('nz-language')
|
||||
language: localStorage.getItem('nz-language'),
|
||||
severityData: [],
|
||||
severityDataWeight: []
|
||||
},
|
||||
mutations: {
|
||||
setLanguage (state, language) {
|
||||
@@ -25,6 +27,22 @@ const user = {
|
||||
setRoleList (state, roleList) {
|
||||
state.roleList = [...roleList]
|
||||
},
|
||||
setSeverityData (state, severityData) {
|
||||
state.severityData = [...severityData]
|
||||
console.log(severityData)
|
||||
const arr = JSON.parse(JSON.stringify(severityData.reverse()))
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
for (let j = 0; j < arr.length; j++) {
|
||||
if (arr[i].weight < arr[j].weight) {
|
||||
const temp = arr[i]
|
||||
arr[i] = arr[j]
|
||||
arr[j] = temp
|
||||
}
|
||||
}
|
||||
}
|
||||
state.severityDataWeight = arr
|
||||
console.log(arr)
|
||||
},
|
||||
clean (state) {
|
||||
state.menuList = []
|
||||
state.buttonList = []
|
||||
@@ -43,6 +61,12 @@ const user = {
|
||||
},
|
||||
roleList (state) {
|
||||
return state.roleList
|
||||
},
|
||||
severityData (state) {
|
||||
return state.severityData
|
||||
},
|
||||
severityDataWeight (state) {
|
||||
return state.severityDataWeight
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@@ -126,6 +150,11 @@ const user = {
|
||||
localStorage.setItem('nz-user-name', user.name)
|
||||
}
|
||||
})
|
||||
get('alert/severity', { pageNo: 1, pageSize: -1 }).then(response => {
|
||||
if (response.code == 200) {
|
||||
store.commit('setSeverityData', response.data.list)
|
||||
}
|
||||
})
|
||||
},
|
||||
logoutSuccess (store, res) {
|
||||
localStorage.removeItem('nz-username')
|
||||
|
||||
Reference in New Issue
Block a user