Merge remote-tracking branch 'origin/dev-3.1' into dev-3.2

# Conflicts:
#	nezha-fronted/src/assets/css/common/rightBoxCommon.scss
#	nezha-fronted/src/assets/css/components/common/project/topology.scss
#	nezha-fronted/src/components/common/bottomBox/tabs/chartTempPreview.vue
#	nezha-fronted/src/components/common/bottomBox/tabs/panelTabNew.vue
#	nezha-fronted/src/components/common/bottomBox/tabs/terminalLogCMDTab.vue
#	nezha-fronted/src/components/common/bottomBox/tabs/terminalLogRecordTab.vue
#	nezha-fronted/src/components/common/bottomBox/tabs/terminalLogTab.vue
#	nezha-fronted/src/components/common/popBox/selectPanel.vue
#	nezha-fronted/src/components/common/project/popData/Info.vue
#	nezha-fronted/src/components/common/project/topologyL5.vue
#	nezha-fronted/src/components/common/rightBox/alertRuleBox.vue
#	nezha-fronted/src/components/common/rightBox/setting/globalizationBox.vue
#	nezha-fronted/src/components/page/config/changePin.vue
#	nezha-fronted/src/components/page/dashboard/explore/editor.vue
#	nezha-fronted/src/components/page/dashboard/metricPreview.vue
#	nezha-fronted/src/components/page/dashboard/panel.vue
#	nezha-fronted/src/permission.js
#	nezha-fronted/src/store/user.js
This commit is contained in:
chenjinsong
2021-11-29 16:19:13 +08:00
80 changed files with 3257 additions and 587 deletions

View File

@@ -15,15 +15,22 @@ export default {
browserWindowZoom browserWindowZoom
}, },
async created () { async created () {
const herfSpiltArr = window.location.href.split('/')
if (herfSpiltArr[3] !== '#') {
herfSpiltArr[3] = '#'
window.location.href = herfSpiltArr.join('/')
}
const Timestamp = new Date().getTime() const Timestamp = new Date().getTime()
const url = 'static/config.json?Timestamp=' + Timestamp const url = 'static/config.json?Timestamp=' + Timestamp
const result = await this.$http.get(url) const result = await this.$http.get(url)
this.$axios.defaults.baseURL = result.body.baseUrl this.$axios.defaults.baseURL = result.body.baseUrl
const version = result.body.version const version = result.body.version
if (version !== localStorage.getItem('nz-version')) { if (version !== localStorage.getItem('nz-version')) {
sessionStorage.clear() localStorage.clear()
localStorage.clear() localStorage.clear()
localStorage.setItem('nz-version', version) localStorage.setItem('nz-version', version)
herfSpiltArr[2] = herfSpiltArr[2] + '?t=' + new Date().getTime()
window.location.href = herfSpiltArr[0] + '//' + herfSpiltArr[2]
} }
} }
} }

View File

@@ -63,6 +63,14 @@
background: rgba(196,196,196,0.4) !important; background: rgba(196,196,196,0.4) !important;
box-shadow: inset 0 -1px 0 0 rgba(0,0,0,0.27); box-shadow: inset 0 -1px 0 0 rgba(0,0,0,0.27);
} }
.topology-scroll{
&.v{
display: none;
}
&.h{
display: none;
}
}
.model-error.nz-icon-shuidi { .model-error.nz-icon-shuidi {
color: #FADED7; color: #FADED7;
animation: model-error-animation .6s infinite ease-in-out; animation: model-error-animation .6s infinite ease-in-out;
@@ -530,5 +538,8 @@
.topo-noData /deep/ .icon{ .topo-noData /deep/ .icon{
width: 5rem; width: 5rem;
height: 5rem; height: 5rem;
}
.topo-page{
overflow: hidden;
box-sizing: border-box;
} }

View File

@@ -65,11 +65,13 @@
@tableDataSort="tableDataSort" @tableDataSort="tableDataSort"
@del="deleteMessage" @del="deleteMessage"
@showText="showText" @showText="showText"
@addSilence="addSilence"
@messageDetail="messageDetail" @messageDetail="messageDetail"
ref="alertListTable" ref="alertListTable"
:form="'chartList'" :form="'chartList'"
:fromPath="'/alertList'" :fromPath="'/alertList'"
style="height: calc(100% - 50px)" style="height: calc(100% - 50px)"
:showOption="showOption"
:showTopBtn="false" :showTopBtn="false"
></alertMessageTable> ></alertMessageTable>
<Pagination :pageObj="pageObj" @pageNo='pageNo' @pageSize='pageSize' ref="Pagination" :append-to-body="false" pop-class="out-popper-fix" style="margin-top: 15px;"></Pagination> <Pagination :pageObj="pageObj" @pageNo='pageNo' @pageSize='pageSize' ref="Pagination" :append-to-body="false" pop-class="out-popper-fix" style="margin-top: 15px;"></Pagination>
@@ -101,7 +103,7 @@
:showOption="false" :showOption="false"
:chart-alert-list="true" :chart-alert-list="true"
></alertMessageTable> ></alertMessageTable>
<Pagination :pageObj="screenPageObj" @pageNo='screenPageNo' @pageSize='screenPageSize' ref="Pagination" ></Pagination> <Pagination :pageObj="screenPageObj" @pageNo='screenPageNo' @pageSize='screenPageSize' ref="screenPagination" ></Pagination>
<loading :ref="'localLoadingScreen'+chartIndex"></loading> <loading :ref="'localLoadingScreen'+chartIndex"></loading>
</el-dialog> </el-dialog>
<div class="export-xlsx"> <div class="export-xlsx">
@@ -155,6 +157,7 @@
</div> </div>
<span class="vue-resizable-handle" @mousedown="startResize" v-if="!isPreview && data.resizable&&!isLock"></span> <span class="vue-resizable-handle" @mousedown="startResize" v-if="!isPreview && data.resizable&&!isLock"></span>
</div> </div>
<transition name="right-box"><alert-silence-box v-if='silenceBoxShow' :alert-silence="objectSilence" @close="closeSilenceBox"></alert-silence-box></transition>
</div> </div>
</template> </template>
@@ -167,13 +170,15 @@ import pickTime from '../common/pickTime'
import chart from '../page/dashboard/overview/chart' import chart from '../page/dashboard/overview/chart'
import alertMessageTable from '@/components/common/table/alert/alertMessageTable.vue' import alertMessageTable from '@/components/common/table/alert/alertMessageTable.vue'
import chartDataList from '@/components/common/mixin/chartDataList' import chartDataList from '@/components/common/mixin/chartDataList'
import alertSilenceBox from '@/components/common/rightBox/alertSilenceBox'
export default { export default {
name: 'chartTable', name: 'chartTable',
components: { components: {
loading: loading, loading: loading,
chart: chart, chart: chart,
'pick-time': pickTime, 'pick-time': pickTime,
alertMessageTable: alertMessageTable alertMessageTable: alertMessageTable,
alertSilenceBox
}, },
props: { props: {
// 看板id // 看板id
@@ -197,12 +202,14 @@ export default {
chartData: {}, chartData: {},
id: { type: String }, id: { type: String },
from: { type: String }, from: { type: String },
showOption: { type: Boolean, default: true },
isLock: { type: Boolean, default: false } isLock: { type: Boolean, default: false }
}, },
mixins: [chartDataList], mixins: [chartDataList],
data () { data () {
return { return {
currentMsg: null, currentMsg: null,
silenceBoxShow: false,
tableHeight: 0, tableHeight: 0,
data: {}, // 该图表信息,chartItem data: {}, // 该图表信息,chartItem
unit: {}, unit: {},
@@ -319,7 +326,22 @@ export default {
logData: [], logData: [],
chartLoading: false, chartLoading: false,
dialogShowText: false, dialogShowText: false,
dialogText: '' dialogText: '',
blankSilenceObject: {
id: '',
startAt: '',
endAt: '',
ruleId: '',
type: 'asset',
linkId: '',
remark: '',
time: [],
matchers: [
{ name: '', value: '', regex: 0 }
],
name: ''
},
objectSilence: {}
} }
}, },
computed: { computed: {
@@ -493,7 +515,7 @@ export default {
const axiosArr = [] const axiosArr = []
const paramStr = this.currentMsg ? JSON.stringify(this.promQueryParamConvert(this.currentMsg)) : null const paramStr = this.currentMsg ? JSON.stringify(this.promQueryParamConvert(this.currentMsg)) : null
if (paramStr && paramStr.trim() != '""') { if (paramStr && paramStr.trim() != '""') {
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + paramStr.substring(1, paramStr.length - 1) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '')) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step + '&filter=' + encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))))
this.legend = [] this.legend = []
this.chartDatas = [] this.chartDatas = []
axios.all(axiosArr).then(res => { axios.all(axiosArr).then(res => {
@@ -626,7 +648,7 @@ export default {
this.$get('/alert/message', queryParam).then(response => { this.$get('/alert/message', queryParam).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.storedTableData = response.data.list this.storedTableData = response.data.list
this.storedScreanTableData = response.data.list this.storedScreanTableData = JSON.parse(JSON.stringify(response.data.list))
this.pageObj.total = response.data.total this.pageObj.total = response.data.total
this.isError = false this.isError = false
this.errorContent = '' this.errorContent = ''
@@ -686,7 +708,7 @@ export default {
this.$get('/alert/message', queryParam).then(response => { this.$get('/alert/message', queryParam).then(response => {
if (response.code == 200) { if (response.code == 200) {
this.storedTableData = response.data.list this.storedTableData = response.data.list
this.storedScreanTableData = response.data.list this.storedScreanTableData = JSON.parse(JSON.stringify(response.data.list))
const axiosAll = [] const axiosAll = []
this.$nextTick(() => { this.$nextTick(() => {
this.storedScreanTableData.forEach((item) => { this.storedScreanTableData.forEach((item) => {
@@ -736,7 +758,7 @@ export default {
this.getAlerScreetList() this.getAlerScreetList()
}, },
promQueryParamConvert (obj) { promQueryParamConvert (obj) {
let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'') + ')' let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '') + ')'
let intoLabels = false let intoLabels = false
obj.labels = JSON.parse(obj.labels) obj.labels = JSON.parse(obj.labels)
if (Object.keys(obj.labels).length > 0) { if (Object.keys(obj.labels).length > 0) {
@@ -767,6 +789,14 @@ export default {
} }
return r return r
}, },
promQueryParamLabels (labels) {
const obj = labels.constructor === Object ? labels : JSON.stringify(labels)
const filterArr = ['alertname', 'severity_id', 'severity', 'rule_type']
filterArr.forEach(key => {
delete obj[key]
})
return JSON.stringify(obj)
},
elementsetShow (s, e) { elementsetShow (s, e) {
const eventfixed = { const eventfixed = {
shezhi: 0, shezhi: 0,
@@ -899,6 +929,9 @@ export default {
// this.$refs.alertListTable.$refs.alertListTable.clearSelection() // this.$refs.alertListTable.$refs.alertListTable.clearSelection()
// this.$refs.alertListScreenTable.$refs.dataTable.clearSelection() // this.$refs.alertListScreenTable.$refs.dataTable.clearSelection()
this.screenPageObj = { ...this.pageObj } this.screenPageObj = { ...this.pageObj }
if (this.$refs.screenPagination && this.$refs.screenPagination.pageSize) {
this.$refs.screenPagination.pageSize = this.screenPageObj.pageSize
}
}, },
// 设置数据, filter区分 // 设置数据, filter区分
setData (chartItem, seriesItem, panelId, filter, area, errorMsg) { setData (chartItem, seriesItem, panelId, filter, area, errorMsg) {
@@ -974,7 +1007,7 @@ export default {
const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000) const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000)
const end = this.searchTimeDialog[1] ? this.searchTimeDialog[1] : bus.computeTimezoneTime(new Date().getTime()) const end = this.searchTimeDialog[1] ? this.searchTimeDialog[1] : bus.computeTimezoneTime(new Date().getTime())
this.expressions = [this.currentMsg.alertRule.expr] this.expressions = [this.currentMsg.alertRule.expr]
this.$get('/logs/loki/api/v1/query_range?format=1&query=' + this.currentMsg.alertRule.expr + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit).then(res => { this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(this.currentMsg.alertRule.expr) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit + '&filter=' + encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))).then(res => {
this.chartLoading = false this.chartLoading = false
const logData = [res.data] const logData = [res.data]
this.resultType = res.data.resultType this.resultType = res.data.resultType
@@ -1077,6 +1110,43 @@ export default {
showText (row) { showText (row) {
this.dialogShowText = true this.dialogShowText = true
this.dialogText = row.alertRule.trbShot this.dialogText = row.alertRule.trbShot
},
addSilence (row, type) {
this.blankSilenceObject.startAt = bus.timeFormate(bus.getOffsetTimezoneData(), 'yyyy-MM-dd hh:mm:ss')
this.blankSilenceObject.endAt = bus.timeFormate(bus.getOffsetTimezoneData(1), 'yyyy-MM-dd hh:mm:ss')
this.objectSilence = JSON.parse(JSON.stringify(this.blankSilenceObject))
this.objectSilence.name = 'Quick silence'
if (type !== 'alertMessage' && type !== 'alertRule') {
this.objectSilence.matchers = [
{ name: type, value: row.name, regex: 0 },
{ name: type + '_id', value: row.id, regex: 0 }
]
} else if (type === 'alertMessage') {
if (typeof row.labels === 'string') row.labels = JSON.parse(row.labels)
const labels = JSON.parse(JSON.stringify(row.labels))
this.objectSilence.matchers = []
const filterArr = ['alertname', 'severity_id', 'severity', 'rule_type']
Object.keys(labels).forEach((key, i) => {
if (filterArr.indexOf(key) != -1) {
return
}
this.objectSilence.matchers.push(
{ name: key, value: labels[key], regex: 0 }
)
})
} else if (type === 'alertRule') {
this.objectSilence.matchers = [
{ name: 'alertName', value: row.name, regex: 0 }
]
}
this.silenceBoxShow = true
},
closeSilenceBox (refresh) {
this.silenceBoxShow = false
if (refresh) {
this.delFlag = true
this.getAlertList()
}
} }
}, },
created () { created () {

View File

@@ -635,23 +635,6 @@ export default {
}, 100) }, 100)
}) })
}, },
dealLegendAlias (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
clickLegend (legendName, index) { clickLegend (legendName, index) {
/* 点击legend /* 点击legend
* 1.当前如果是全高亮状态则全部置灰只留被点击的legend高亮 * 1.当前如果是全高亮状态则全部置灰只留被点击的legend高亮

View File

@@ -213,6 +213,7 @@ import chartBarStatis from './chart-bar-statistics'
import logs from './logs' import logs from './logs'
import { fromRoute } from '@/components/common/js/constants' import { fromRoute } from '@/components/common/js/constants'
import chartTempData from '@/components/charts/chartTempData' import chartTempData from '@/components/charts/chartTempData'
import { dealLegendAlias } from '@/components/common/js/tools'
// import visNetwork from './visNetwork' // import visNetwork from './visNetwork'
export default { export default {
name: 'chartList', name: 'chartList',
@@ -289,7 +290,7 @@ export default {
dragging: null, dragging: null,
// chartDataCacheGroup:new Map,//图表数据缓存用于查询id:{} // chartDataCacheGroup:new Map,//图表数据缓存用于查询id:{}
stepHeight: 50, stepHeight: 50,
childrenScrollTop: 0,
tempDom: { height: '', width: '' } tempDom: { height: '', width: '' }
// showShadow:false, // showShadow:false,
} }
@@ -408,6 +409,7 @@ export default {
this.cleanData() this.cleanData()
// 内含 panelId,开始时间,结束时间 // 内含 panelId,开始时间,结束时间
this.filter = filter this.filter = filter
this.childrenScrollTop = 0
this.pagePanelId = this.filter.panelId this.pagePanelId = this.filter.panelId
this.getData(this.filter) this.getData(this.filter)
}, },
@@ -510,10 +512,11 @@ export default {
// this.getChartData(item, index, this.filter) // this.getChartData(item, index, this.filter)
this.setChartSize(item, index) this.setChartSize(item, index)
const chartBox = document.getElementById('chart-' + item.id)// this.$refs['editChart'+item.id][0]; const chartBox = document.getElementById('chart-' + item.id)// this.$refs['editChart'+item.id][0];
this.handleElementInViewport(chartBox, 0, item, index, true) this.handleElementInViewport(chartBox, this.childrenScrollTop, item, index, true)
}) })
}, },
loadChartData (scrollTop) { loadChartData (scrollTop) {
this.childrenScrollTop = scrollTop
if (this.dataList.length > 0) { if (this.dataList.length > 0) {
this.dataList.forEach((item, index) => { this.dataList.forEach((item, index) => {
this.setChartSize(item, index) this.setChartSize(item, index)
@@ -703,7 +706,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
const axiosArr = chartItem.elements.map((ele) => { const axiosArr = chartItem.elements.map((ele) => {
const filterItem = ele const filterItem = ele
let query = filterItem.expression let query = encodeURIComponent(filterItem.expression)
if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea' || chartInfo.type === 'table') && chartInfo.param) { // 如果是这三个 默认给null if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea' || chartInfo.type === 'table') && chartInfo.param) { // 如果是这三个 默认给null
chartInfo.param.nullType = chartInfo.param.nullType || 'null' chartInfo.param.nullType = chartInfo.param.nullType || 'null'
query += '&nullType=' + chartInfo.param.nullType query += '&nullType=' + chartInfo.param.nullType
@@ -870,7 +873,7 @@ export default {
host = chartItem.elements[innerPos].expression host = chartItem.elements[innerPos].expression
} }
// 处理legend别名 // 处理legend别名
let alias = this.$refs['editChart' + chartItem.id][0].dealLegendAlias(host, chartItem.elements[innerPos].legend) let alias = dealLegendAlias(host, chartItem.elements[innerPos].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1106,7 +1109,7 @@ export default {
host += '}' host += '}'
} }
// 处理legend别名 // 处理legend别名
let alias = this.$refs['editChart' + chartInfo.id][0].dealLegendAlias(host, chartInfo.elements[0].legend) let alias = dealLegendAlias(host, chartInfo.elements[0].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1196,7 +1199,7 @@ export default {
const endTime = bus.timeFormate(now, 'yyyy-MM-dd hh:mm:ss') const endTime = bus.timeFormate(now, 'yyyy-MM-dd hh:mm:ss')
// const step = bus.getStep(startTime, endTime) // const step = bus.getStep(startTime, endTime)
this.$nextTick(() => { this.$nextTick(() => {
let query = chartInfo.elements[0].expression let query = encodeURIComponent(chartInfo.elements[0].expression)
if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea') && chartInfo.param) { if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea') && chartInfo.param) {
chartInfo.param.nullType = chartInfo.param.nullType || 'null' chartInfo.param.nullType = chartInfo.param.nullType || 'null'
query += '&nullType=' + chartInfo.param.nullType query += '&nullType=' + chartInfo.param.nullType
@@ -1397,7 +1400,7 @@ export default {
if (this.additionalInfo) { if (this.additionalInfo) {
this.$set(chartInfo, 'param', { endpointId: this.additionalInfo.id }) this.$set(chartInfo, 'param', { endpointId: this.additionalInfo.id })
} }
this.$refs['editChart' + chartInfo.id][0].getAlertList(filterType) this.$refs['editChart' + chartInfo.id][0] && this.$refs['editChart' + chartInfo.id][0].getAlertList(filterType)
}, },
getAlertRuleChartData (chartInfo) { getAlertRuleChartData (chartInfo) {
const vm = this const vm = this

View File

@@ -225,7 +225,7 @@ import chartGroup from './chart-group'
import logs from './logs' import logs from './logs'
import { fromRoute } from '@/components/common/js/constants' import { fromRoute } from '@/components/common/js/constants'
import chartTempData from '@/components/charts/chartTempData' import chartTempData from '@/components/charts/chartTempData'
import { chartResizeTool } from '@/components/common/js/tools' import { chartResizeTool, dealLegendAlias } from '@/components/common/js/tools'
export default { export default {
name: 'chartList', name: 'chartList',
props: { props: {
@@ -236,7 +236,8 @@ export default {
obj: Object, obj: Object,
panelLock: { type: Boolean, default: false }, panelLock: { type: Boolean, default: false },
hasGroup: { type: Boolean, default: true }, hasGroup: { type: Boolean, default: true },
panelDataList: Array panelDataList: Array,
nowTimeType: {}
}, },
components: { components: {
@@ -280,7 +281,8 @@ export default {
// chartDataCacheGroup:new Map,//图表数据缓存用于查询id:{} // chartDataCacheGroup:new Map,//图表数据缓存用于查询id:{}
stepWidth: null, stepWidth: null,
tempDom: { height: '', width: '' } tempDom: { height: '', width: '' },
childrenScrollTop: 0
// showShadow:false, // showShadow:false,
} }
}, },
@@ -439,6 +441,7 @@ export default {
this.cleanData() this.cleanData()
// 内含 panelId,开始时间,结束时间 // 内含 panelId,开始时间,结束时间
this.filter = filter this.filter = filter
this.childrenScrollTop = 0
this.pagePanelId = this.filter.panelId this.pagePanelId = this.filter.panelId
this.getData(this.filter) this.getData(this.filter)
}, },
@@ -565,10 +568,6 @@ export default {
// 获取panel详情数据,获取panel下所有chart列表 // 获取panel详情数据,获取panel下所有chart列表
getData (params) { getData (params) {
if (this.finshGetData) {
return
}
this.finshGetData = true
const param = { const param = {
panelId: params.panelId, panelId: params.panelId,
query: params.query, query: params.query,
@@ -641,21 +640,16 @@ export default {
} }
}) })
}) })
this.finshGetData = false
return return
} }
if (!param.query) delete param.query if (!param.query) delete param.query
// 根据panelId获得panel下的所有图表 // 根据panelId获得panel下的所有图表
// const groupId = true ? '&groupId=0' : '' // const groupId = true ? '&groupId=0' : ''
if (!params.panelId) { if (!params.panelId) {
this.finshGetData = false
return return
} // 没有panelId不调用接口 } // 没有panelId不调用接口
this.$get('visual/panel/chart?panelId=' + params.panelId + '&groupId=0' + '&pageSize=-1').then(response => { this.$get('visual/panel/chart?panelId=' + params.panelId + '&groupId=0' + '&pageSize=-1').then(response => {
if (response.code === 200) { if (response.code === 200) {
setTimeout(() => {
this.finshGetData = false
}, 100)
response.data.list.forEach((item, index) => { response.data.list.forEach((item, index) => {
item.isLoaded = false item.isLoaded = false
}) })
@@ -706,7 +700,7 @@ export default {
if (!item.isLoaded) { if (!item.isLoaded) {
// 获得当前显示在浏览器的图表,从后台获取数据 // 获得当前显示在浏览器的图表,从后台获取数据
const chartBox = document.getElementById('chart-' + item.id) const chartBox = document.getElementById('chart-' + item.id)
this.handleElementInViewport(chartBox, 0, item, index) this.handleElementInViewport(chartBox, this.childrenScrollTop, item, index)
} }
if (item.type === 'group') { if (item.type === 'group') {
this.$refs['editChart' + item.id][0].$refs.listGroup.getData(params) this.$refs['editChart' + item.id][0].$refs.listGroup.getData(params)
@@ -718,6 +712,7 @@ export default {
}) })
}, },
loadChartData (scrollTop) { loadChartData (scrollTop) {
this.childrenScrollTop = scrollTop
if (this.dataList.length > 0) { if (this.dataList.length > 0) {
this.dataList.forEach((item, index) => { this.dataList.forEach((item, index) => {
if (!item.isLoaded) { if (!item.isLoaded) {
@@ -821,7 +816,7 @@ export default {
getChartData (chartInfo, pos, filterType) { getChartData (chartInfo, pos, filterType) {
const chartItem = chartInfo const chartItem = chartInfo
if (chartItem.type === 'group') { if (chartItem.type === 'group') {
this.$refs['editChart' + chartItem.id][0].setData(chartItem) this.$refs['editChart' + chartItem.id][0] && this.$refs['editChart' + chartItem.id][0].setData(chartItem)
return return
} }
if (chartItem.type === 'assetInfo') { if (chartItem.type === 'assetInfo') {
@@ -905,7 +900,12 @@ export default {
let startTime = '' let startTime = ''
let endTime = '' let endTime = ''
if (filterType === 'refresh') { // 刷新 if (filterType === 'refresh') { // 刷新
const now = new Date(bus.computeTimezone(new Date().getTime())) let now = null
if (this.nowTimeType.id === 0 && this.nowTimeType.value === -1) {
now = new Date(this.filter.start_time)
} else {
now = new Date(bus.computeTimezone(new Date().getTime()))
}
const origin = new Date(this.filter.end_time) const origin = new Date(this.filter.end_time)
const numInterval = now.getTime() - origin.getTime() const numInterval = now.getTime() - origin.getTime()
if (numInterval >= 60000) { // 大于1分钟则start、end均往后移numInterval否则时间不变 if (numInterval >= 60000) { // 大于1分钟则start、end均往后移numInterval否则时间不变
@@ -918,8 +918,8 @@ export default {
endTime = this.filter.end_time endTime = this.filter.end_time
} }
} else if (filterType === 'showFullScreen') { // 全屏时间查询 } else if (filterType === 'showFullScreen') { // 全屏时间查询
startTime = this.filter.start_time startTime = this.filter.showFullScreenStart_time
endTime = this.filter.end_time endTime = this.filter.showFullScreenEnd_time
// this.$parent.refreshTime(startTime,endTime);全屏查询不更新panel列表的时间条件 // this.$parent.refreshTime(startTime,endTime);全屏查询不更新panel列表的时间条件
} else { } else {
startTime = this.filter.start_time startTime = this.filter.start_time
@@ -930,7 +930,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
const axiosArr = chartItem.elements.map((ele) => { const axiosArr = chartItem.elements.map((ele) => {
const filterItem = ele const filterItem = ele
let query = filterItem.expression let query = encodeURIComponent(filterItem.expression)
if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea' || chartInfo.type === 'table') && chartInfo.param) { // 如果是这三个 默认给null if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea' || chartInfo.type === 'table') && chartInfo.param) { // 如果是这三个 默认给null
chartInfo.param.nullType = chartInfo.param.nullType || 'null' chartInfo.param.nullType = chartInfo.param.nullType || 'null'
query += '&nullType=' + chartInfo.param.nullType query += '&nullType=' + chartInfo.param.nullType
@@ -1096,7 +1096,7 @@ export default {
host = chartItem.elements[innerPos].expression host = chartItem.elements[innerPos].expression
} }
// 处理legend别名 // 处理legend别名
let alias = this.$refs['editChart' + chartItem.id][0].dealLegendAlias(host, chartItem.elements[innerPos].legend) let alias = dealLegendAlias(host, chartItem.elements[innerPos].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1336,7 +1336,7 @@ export default {
host += '}' host += '}'
} }
// 处理legend别名 // 处理legend别名
let alias = this.$refs['editChart' + chartInfo.id][0].dealLegendAlias(host, chartInfo.elements[0].legend) let alias = dealLegendAlias(host, chartInfo.elements[0].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1416,7 +1416,7 @@ export default {
}, },
getEndpointInfoChartData (chartInfo) { getEndpointInfoChartData (chartInfo) {
const detail = [] const detail = []
this.$refs['editChart' + chartInfo.id][0].showLoad() this.$refs['editChart' + chartInfo.id][0] && this.$refs['editChart' + chartInfo.id][0].showLoad()
chartInfo.name = this.$t('project.chart.endpointInfo') chartInfo.name = this.$t('project.chart.endpointInfo')
chartInfo.from = fromRoute.endpoint chartInfo.from = fromRoute.endpoint
const basicInfo = JSON.parse(JSON.stringify(this.obj)) const basicInfo = JSON.parse(JSON.stringify(this.obj))
@@ -1447,7 +1447,6 @@ export default {
const arr = [] const arr = []
arr.push(this.$get(`/asset/asset/${assetId}`)) arr.push(this.$get(`/asset/asset/${assetId}`))
arr.push(this.$get(`/asset/asset/feature/${assetId}`)) arr.push(this.$get(`/asset/asset/feature/${assetId}`))
console.log(this.$refs['editChart' + chartInfo.id][0])
if (this.$refs['editChart' + chartInfo.id][0]) { if (this.$refs['editChart' + chartInfo.id][0]) {
this.$refs['editChart' + chartInfo.id][0].showLoad() this.$refs['editChart' + chartInfo.id][0].showLoad()
} }
@@ -1619,7 +1618,7 @@ export default {
if (this.obj) { if (this.obj) {
this.$set(chartInfo, 'param', { endpointId: this.obj.id }) this.$set(chartInfo, 'param', { endpointId: this.obj.id })
} }
this.$refs['editChart' + chartInfo.id][0].getAlertList(null, null, chartInfo) this.$refs['editChart' + chartInfo.id][0] && this.$refs['editChart' + chartInfo.id][0].getAlertList(null, null, chartInfo)
}, },
getAlertRuleChartData (chartInfo) { getAlertRuleChartData (chartInfo) {
const vm = this const vm = this
@@ -1760,8 +1759,8 @@ export default {
}, },
searchData (chartId, searchTime) { searchData (chartId, searchTime) {
if (searchTime) { // 全屏时间查询 if (searchTime) { // 全屏时间查询
this.filter.start_time = bus.timeFormate(searchTime[0], 'yyyy-MM-dd hh:mm:ss') this.filter.showFullScreenStart_time = bus.timeFormate(searchTime[0], 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(searchTime[1], 'yyyy-MM-dd hh:mm:ss') this.filter.showFullScreenEnd_time = bus.timeFormate(searchTime[1], 'yyyy-MM-dd hh:mm:ss')
} }
this.dataList.forEach((item, index) => { this.dataList.forEach((item, index) => {
if (item.id === chartId) { if (item.id === chartId) {
@@ -1834,6 +1833,9 @@ export default {
this.$post('visual/panel/chart/syncTmpl', { ids: [item.id] }).then(res => { this.$post('visual/panel/chart/syncTmpl', { ids: [item.id] }).then(res => {
if (res.code === 200) { if (res.code === 200) {
this.getData(this.filter) this.getData(this.filter)
// setTimeout(() => {
// this.refreshChart(item.id)
// }, 100)
this.$message.success(this.$t('tip.syncSuccess')) this.$message.success(this.$t('tip.syncSuccess'))
} else { } else {
this.$message.error(res.msg) this.$message.error(res.msg)

View File

@@ -533,23 +533,6 @@ export default {
}, 100) }, 100)
}) })
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
clickLegend (legendName, index) { clickLegend (legendName, index) {
/* 点击legend /* 点击legend
* 1.当前如果是全高亮状态则全部置灰只留被点击的legend高亮 * 1.当前如果是全高亮状态则全部置灰只留被点击的legend高亮

View File

@@ -88,6 +88,7 @@
</div> </div>
</div> </div>
<el-table :data="seriesItemScreen" border height="95%" style="margin-top: 10px;" <el-table :data="seriesItemScreen" border height="95%" style="margin-top: 10px;"
ref="tableScreen"
@sort-change="tableDataSortScreen" tooltip-effect="light"> @sort-change="tableDataSortScreen" tooltip-effect="light">
<el-table-column :label="$t('dashboard.panel.chartTableColumn.time')" min-width="100" prop="time" <el-table-column :label="$t('dashboard.panel.chartTableColumn.time')" min-width="100" prop="time"
:sort-orders="['ascending', 'descending']" :sortable="'custom'"></el-table-column> :sort-orders="['ascending', 'descending']" :sortable="'custom'"></el-table-column>
@@ -101,7 +102,7 @@
<el-table-column :label="$t('dashboard.panel.chartTableColumn.value')" class-name="costom-value" min-width="90" prop="value" <el-table-column :label="$t('dashboard.panel.chartTableColumn.value')" class-name="costom-value" min-width="90" prop="value"
:resizable="false" :sort-orders="['ascending', 'descending']" :sortable="'custom'"> :resizable="false" :sort-orders="['ascending', 'descending']" :sortable="'custom'">
<template slot-scope="scope"> <template slot-scope="scope">
<div :style="{color:mapping?mapping.color.text:'#000',background:mapping?mapping.color.bac:'#fff'}" > <div :style="{color:scope.row.mapping?scope.row.mapping.color.text:'#000',background:scope.row.mapping?scope.row.mapping.color.bac:'#fff'}" >
<span style="padding: 0px 10px;">{{ scope.row.value}}</span> <span style="padding: 0px 10px;">{{ scope.row.value}}</span>
</div> </div>
</template> </template>
@@ -352,6 +353,8 @@ export default {
this.seriesItemScreen = this.seriesItem this.seriesItemScreen = this.seriesItem
this.screenModal = true this.screenModal = true
this.screenPageObj.pageNo = 1
this.screenPageObj.pageSize = this.pageObj.pageSize
}, },
// 设置数据, filter区分 // 设置数据, filter区分
setData (chartItem, seriesItem, panelId, filter, area, errorMsg) { setData (chartItem, seriesItem, panelId, filter, area, errorMsg) {
@@ -390,6 +393,7 @@ export default {
} }
this.mapping = mapping this.mapping = mapping
item.mapping = mapping item.mapping = mapping
item.oldValue = item.value
item.value = mapping ? mapping.text.replace('{{value}}', item.value).replace('{{name}}', item.element.alias) : chartDataFormat.getUnit(chartItem.unit ? chartItem.unit : 2).compute(value, null, 2) item.value = mapping ? mapping.text.replace('{{value}}', item.value).replace('{{name}}', item.element.alias) : chartDataFormat.getUnit(chartItem.unit ? chartItem.unit : 2).compute(value, null, 2)
} }
return item return item
@@ -608,23 +612,6 @@ export default {
this.orderByScreen = { order: item.order, prop: item.prop } this.orderByScreen = { order: item.order, prop: item.prop }
this.seriesItemScreen = this.filterShowData(this.storedScreanTableData, this.screenPageObj, 'seriesScreen') this.seriesItemScreen = this.filterShowData(this.storedScreanTableData, this.screenPageObj, 'seriesScreen')
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
// 获取格式 // 获取格式
getNumStr (num) { getNumStr (num) {
if (num) { if (num) {

View File

@@ -138,7 +138,7 @@
</div> </div>
</template> </template>
<chart-alert-list v-if="chart.type === 'alertList'" :showTitle="false" ref="alertListChart" id="chartAlertListPreview" :chart-info="chart" :chart-data="chart" class="height-100"></chart-alert-list> <chart-alert-list v-if="chart.type === 'alertList'" :show-option="false" :showTitle="false" ref="alertListChart" id="chartAlertListPreview" :chart-info="chart" :chart-data="chart" class="height-100"></chart-alert-list>
<template v-if="chart.type==='text'"> <template v-if="chart.type==='text'">
<div id="chartTextPreview" class="chart-text-preview height-100"> <div id="chartTextPreview" class="chart-text-preview height-100">
@@ -170,7 +170,7 @@ import chartAlertList from './chart-alert-list'
import chartConfig from '../page/dashboard/overview/chartConfig' import chartConfig from '../page/dashboard/overview/chartConfig'
import diagram from '@/components/common/ChartDiagram/diagram' import diagram from '@/components/common/ChartDiagram/diagram'
import moment from 'moment-timezone' import moment from 'moment-timezone'
import { formatScientificNotation } from '@/components/common/js/tools' import { formatScientificNotation, dealLegendAlias } from '@/components/common/js/tools'
export default { export default {
name: 'chartPreview', name: 'chartPreview',
components: { components: {
@@ -302,6 +302,9 @@ export default {
}, },
initDialog () { initDialog () {
// 此时初始化才能获得screenShowArea对象否则此对象为undefined无法初始化图表 // 此时初始化才能获得screenShowArea对象否则此对象为undefined无法初始化图表
if (this.$refs.pickTime) {
this.$refs.pickTime.$refs.timePicker.setCustomTime()
}
const chartType = this.chart.type const chartType = this.chart.type
if (chartType === 'table') { if (chartType === 'table') {
// //
@@ -361,11 +364,16 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
const axiosArr = chartItem.elements.map((ele) => { const axiosArr = chartItem.elements.map((ele) => {
const filterItem = ele const filterItem = ele
const query = filterItem.expression const query = encodeURIComponent(filterItem.expression)
// if(chartItem.type === 'table'&&chartItem.param&&chartItem.param.last == 1){ // if(chartItem.type === 'table'&&chartItem.param&&chartItem.param.last == 1){
// return this.$get('/prom/api/v1/query_range?query=' + query + "&start=" + this.$stringTimeParseToUnix(endTime) + "&end=" + this.$stringTimeParseToUnix(endTime) + '&step=' + step); // return this.$get('/prom/api/v1/query_range?query=' + query + "&start=" + this.$stringTimeParseToUnix(endTime) + "&end=" + this.$stringTimeParseToUnix(endTime) + '&step=' + step);
// } // }
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step) let str = ''
if ((chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 'stackArea' || chartItem.type === 'table') && chartItem.param) { // 如果是这三个 默认给null
chartItem.param.nullType = chartItem.param.nullType || 'null'
str += '&nullType=' + chartItem.param.nullType
}
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step + str)
}) })
// 一个图表的所有element单独获取数据 // 一个图表的所有element单独获取数据
axios.all(axiosArr).then((res) => { axios.all(axiosArr).then((res) => {
@@ -510,7 +518,7 @@ export default {
host = chartItem.elements[innerPos].expression host = chartItem.elements[innerPos].expression
} }
// 处理legend别名 // 处理legend别名
let alias = this.dealLegendAlias(host, chartItem.elements[innerPos].legend) let alias = dealLegendAlias(host, chartItem.elements[innerPos].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -765,6 +773,7 @@ export default {
// chartSite用于区分是全屏显示还是局部显示 // chartSite用于区分是全屏显示还是局部显示
initChart (chartInfo, dataArg, ele, legend) { initChart (chartInfo, dataArg, ele, legend) {
const self = this const self = this
self.isStackArea = false
let minTime = null let minTime = null
let maxTime = null let maxTime = null
if (dataArg.length > 0 && dataArg[0].data && if (dataArg.length > 0 && dataArg[0].data &&
@@ -860,6 +869,7 @@ export default {
formatter: function (params) { formatter: function (params) {
let str = '<div>' let str = '<div>'
let sum = 0 let sum = 0
let showFlag = false
params.forEach((item, i) => { params.forEach((item, i) => {
const tip = legend[item.seriesIndex] const tip = legend[item.seriesIndex]
const color = self.bgColorList[item.seriesIndex] const color = self.bgColorList[item.seriesIndex]
@@ -870,33 +880,40 @@ export default {
[tData.getHours(), tData.getMinutes(), tData.getSeconds()].join(':') [tData.getHours(), tData.getMinutes(), tData.getSeconds()].join(':')
str += '<br/>' str += '<br/>'
} }
const val = formatScientificNotation(item.data[1], 2) showFlag = showFlag || item.data[1]
sum += self.numberWithEConvent(val) if (!isNaN(item.data[1] + '')) {
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' const val = formatScientificNotation(item.data[1], 2)
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>` sum += isNaN(self.numberWithEConvent(val)) ? 0 : Number(self.numberWithEConvent(val))
str += '<div style="padding-left: 10px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += (function () { str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>`
if (chartInfo.from == 'endpoint') { str += '<div style="padding-left: 10px;">'
return val == 1 ? 'up' : 'down' str += (function () {
} if (chartInfo.from == 'endpoint') {
return chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, 2) return val == 1 ? 'up' : 'down'
}()) }
str += '</div>' return chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, 2)
str += '</div>' }())
str += '</div>'
str += '</div>'
}
}) })
if (chartInfo.type === 'stackArea' || self.isStackArea) { if (chartInfo.type === 'stackArea' || self.isStackArea) {
sum = parseFloat(Number(sum).toFixed(2)) sum = parseFloat(Number(sum).toFixed(6))
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += '<div style="line-height: 18px; font-size: 12px;padding-left:20px;">' str += '<div style="line-height: 18px; font-size: 12px;padding-left:20px;">'
str += self.$t('dashboard.panel.chartTotal') str += self.$t('dashboard.panel.chartTotal')
str += '</div>' str += '</div>'
str += '<div style="padding-left: 10px;">' str += '<div style="padding-left: 10px;">'
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(sum, null, 2) str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(sum, null, 6)
str += '</div>' str += '</div>'
str += '</div>' str += '</div>'
} }
str += '</div>' str += '</div>'
return str if (!showFlag) {
return ''
} else {
return str
}
} }
}, },
legend: { legend: {
@@ -1015,6 +1032,7 @@ export default {
this.$refs.loadingPreview.endLoading() this.$refs.loadingPreview.endLoading()
}) })
this.echartModalStore.off('magictypechanged')
this.echartModalStore.on('magictypechanged', function (params) { this.echartModalStore.on('magictypechanged', function (params) {
self.isStackArea = !self.isStackArea self.isStackArea = !self.isStackArea
if (self.isStackArea) { if (self.isStackArea) {
@@ -1046,7 +1064,7 @@ export default {
str += '<br/>' str += '<br/>'
} }
const val = formatScientificNotation(item.data[1], 2) const val = formatScientificNotation(item.data[1], 2)
sum += self.numberWithEConvent(val) sum += isNaN(self.numberWithEConvent(val)) ? 0 : Number(self.numberWithEConvent(val))
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>` str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>`
str += '<div style="padding-left: 10px;">' str += '<div style="padding-left: 10px;">'
@@ -1600,11 +1618,16 @@ export default {
const step = bus.getStep(startTime, endTime) const step = bus.getStep(startTime, endTime)
axiosArr = this.chart.elements.map((ele) => { axiosArr = this.chart.elements.map((ele) => {
const filterItem = ele const filterItem = ele
const query = filterItem.expression const query = encodeURIComponent(filterItem.expression)
if (chartItem.type === 'table' && chartItem.param && chartItem.param.last == 1) { let str = ''
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(endTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step) if ((chartItem.type === 'line' || chartItem.type === 'bar' || chartItem.type === 'stackArea' || chartItem.type === 'table') && chartItem.param) { // 如果是这三个 默认给null
chartItem.param.nullType = chartItem.param.nullType || 'null'
str += '&nullType=' + chartItem.param.nullType
} }
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step) if (chartItem.type === 'table' && chartItem.param && chartItem.param.last == 1) {
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(endTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step + str)
}
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step + str)
}) })
// 一个图表 // 一个图表
axios.all(axiosArr).then(res => { axios.all(axiosArr).then(res => {
@@ -1673,7 +1696,7 @@ export default {
if (!host || host === '') { if (!host || host === '') {
host = this.chart.elements[pos].expression host = this.chart.elements[pos].expression
} }
let alias = this.dealLegendAlias(host, this.chart.elements[pos].legend) let alias = dealLegendAlias(host, this.chart.elements[pos].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1713,23 +1736,6 @@ export default {
}) })
}) })
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
screenPageNo (val) { screenPageNo (val) {
this.screenPageObj.pageNo = val this.screenPageObj.pageNo = val
this.seriesItemScreen = this.filterShowData(this.storedScreanTableData, this.screenPageObj) this.seriesItemScreen = this.filterShowData(this.storedScreanTableData, this.screenPageObj)

View File

@@ -206,7 +206,7 @@ import chartDataFormat from './chartDataFormat'
import { randomcolor } from '../common/js/radomcolor/randomcolor.js' import { randomcolor } from '../common/js/radomcolor/randomcolor.js'
import chartConfig from '../page/dashboard/overview/chartConfig' import chartConfig from '../page/dashboard/overview/chartConfig'
import { getChart, setChart, lineChartMove, getMousePoint } from '../common/js/common' import { getChart, setChart, lineChartMove, getMousePoint } from '../common/js/common'
import { getMetricTypeValue, chartResizeTool, formatScientificNotation } from '../common/js/tools' import { getMetricTypeValue, chartResizeTool, formatScientificNotation, dealLegendAlias } from '../common/js/tools'
import moment from 'moment-timezone' import moment from 'moment-timezone'
import chartDataList from '@/components/common/mixin/chartDataList' import chartDataList from '@/components/common/mixin/chartDataList'
@@ -399,7 +399,6 @@ export default {
const hasGrey = highlightNum < this.isGrey.length // 是否有置灰的 const hasGrey = highlightNum < this.isGrey.length // 是否有置灰的
const curIsGrey = this.isGrey[index] // 当前legend的状态 const curIsGrey = this.isGrey[index] // 当前legend的状态
const currentIsTheOnlyOneHighlight = !curIsGrey && highlightNum === 1 // 当前legend是否是目前唯一高亮的 const currentIsTheOnlyOneHighlight = !curIsGrey && highlightNum === 1 // 当前legend是否是目前唯一高亮的
const echart = getChart(this.chartIndex) const echart = getChart(this.chartIndex)
if (echart) { if (echart) {
if (!hasGrey) { // 1.除当前legend外全置灰 if (!hasGrey) { // 1.除当前legend外全置灰
@@ -424,6 +423,34 @@ export default {
}) })
this.$set(this.isGrey, index, !this.isGrey[index]) this.$set(this.isGrey, index, !this.isGrey[index])
} }
const chartInfo = this.data
const dataArg = this.seriesItem.filter((seriesItem, seriesIndex) => !this.isGrey[seriesIndex])
const maxValueCopies = this.getMaxValue(dataArg, chartInfo)
const maxValue = maxValueCopies.maxValue
// const minValue = maxValueCopies.minValue
// const dot = maxValueCopies.dot
const copies = maxValueCopies.copies
const unit = maxValueCopies.unit
const option = {
yAxis: {
minInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'min'),
maxInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(dataArg.length / 5)
}
}
if (!maxValueCopies.copies) {
option.yAxis.min = 0
option.yAxis.max = 1
} else {
option.yAxis.max = undefined
}
if (unit.type == 'Time' || option.yAxis.maxInterval === 1) {
delete option.yAxis.maxInterval
}
getChart(this.chartIndex).setOption({
yAxis: {
...option.yAxis
}
})
} }
}, },
clickLegend2 (legendName, index) { clickLegend2 (legendName, index) {
@@ -488,7 +515,6 @@ export default {
const hasGrey = highlightNum < this.isGreyScreen.length // 是否有置灰的 const hasGrey = highlightNum < this.isGreyScreen.length // 是否有置灰的
const curIsGrey = this.isGreyScreen[index] // 当前legend的状态 const curIsGrey = this.isGreyScreen[index] // 当前legend的状态
const currentIsTheOnlyOneHighlight = !curIsGrey && highlightNum === 1 // 当前legend是否是目前唯一高亮的 const currentIsTheOnlyOneHighlight = !curIsGrey && highlightNum === 1 // 当前legend是否是目前唯一高亮的
const echart = this.echartModalStore const echart = this.echartModalStore
if (echart) { if (echart) {
if (!hasGrey) { // 1.除当前legend外全置灰 if (!hasGrey) { // 1.除当前legend外全置灰
@@ -513,6 +539,34 @@ export default {
}) })
this.$set(this.isGreyScreen, index, !this.isGreyScreen[index]) this.$set(this.isGreyScreen, index, !this.isGreyScreen[index])
} }
const chartInfo = this.data
const dataArg = this.seriesItemScreen.filter((seriesItem, seriesIndex) => !this.isGreyScreen[seriesIndex])
const maxValueCopies = this.getMaxValue(dataArg, chartInfo)
const maxValue = maxValueCopies.maxValue
// const minValue = maxValueCopies.minValue
// const dot = maxValueCopies.dot
const copies = maxValueCopies.copies
const unit = maxValueCopies.unit
const option = {
yAxis: {
minInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'min'),
maxInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(dataArg.length / 5)
}
}
if (!maxValueCopies.copies) {
option.yAxis.min = 0
option.yAxis.max = 1
} else {
option.yAxis.max = undefined
}
if (unit.type == 'Time' || option.yAxis.maxInterval === 1) {
delete option.yAxis.maxInterval
}
echart.setOption({
yAxis: {
...option.yAxis
}
})
} }
}, },
clickScreenLegend2 (legendName, index) { clickScreenLegend2 (legendName, index) {
@@ -588,6 +642,7 @@ export default {
this.legendMagicType = legend this.legendMagicType = legend
this.chartInfo = chartInfo this.chartInfo = chartInfo
const self = this const self = this
self.isStackArea = false
this.chartType = '' // 图表类型 this.chartType = '' // 图表类型
if (chartInfo.type === 4) { // line,bar if (chartInfo.type === 4) { // line,bar
this.chartType = 'line' this.chartType = 'line'
@@ -611,7 +666,7 @@ export default {
// chartId='screenShowArea'; // chartId='screenShowArea';
} }
const chartWidth = ele.clientWidth const chartWidth = ele.clientWidth
this.stepWidth = document.getElementById('listContainer').offsetWidth / 12 this.stepWidth = this.chartInfo.groupId ? (document.getElementById('listContainer').offsetWidth / 12) - 10 : document.getElementById('listContainer').offsetWidth / 12
const stackIconBorderColor = (chartInfo.type === 'stackArea' ? '#53a3cb' : '#7e7e7e') const stackIconBorderColor = (chartInfo.type === 'stackArea' ? '#53a3cb' : '#7e7e7e')
const stackIconChooseBorderColor = (chartInfo.type === 'stackArea' ? '#7e7e7e' : '#53a3cb') const stackIconChooseBorderColor = (chartInfo.type === 'stackArea' ? '#7e7e7e' : '#53a3cb')
let maxValueCopies = this.getMaxValue(dataArg, chartInfo) let maxValueCopies = this.getMaxValue(dataArg, chartInfo)
@@ -627,7 +682,7 @@ export default {
let dot = this.chartDot = maxValueCopies.dot let dot = this.chartDot = maxValueCopies.dot
const copies = maxValueCopies.copies const copies = maxValueCopies.copies
const unit = maxValueCopies.unit const unit = maxValueCopies.unit
const oldDot = maxValueCopies.oldDot // const oldDot = maxValueCopies.oldDot
let option = { let option = {
title: { title: {
show: false show: false
@@ -754,6 +809,7 @@ export default {
formatter: function (params) { formatter: function (params) {
let str = '<div>' let str = '<div>'
let sum = 0 let sum = 0
let showFlag = false
let minusFlag = true let minusFlag = true
params.forEach((item, i) => { params.forEach((item, i) => {
const tip = legend[item.seriesIndex] const tip = legend[item.seriesIndex]
@@ -776,45 +832,49 @@ export default {
str += '</div>' str += '</div>'
minusFlag = false minusFlag = false
} }
const previousItem = params.find((series) => ('Previous ' + item.seriesName) === series.seriesName) showFlag = showFlag || item.data[1]
let paramsDot = bus.countDecimals(item.data[1]) if (!isNaN(item.data[1] + '')) {
if (paramsDot < self.chartDot) { const previousItem = params.find((series) => ('Previous ' + item.seriesName) === series.seriesName)
paramsDot = self.chartDot let paramsDot = bus.countDecimals(item.data[1])
} else if (paramsDot > 6) { if (paramsDot < self.chartDot) {
paramsDot = 6 paramsDot = self.chartDot
} } else if (paramsDot > 6) {
const val = formatScientificNotation(item.data[1], paramsDot) paramsDot = 6
sum += self.numberWithEConvent(val)
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>`
str += '<div style="padding-left: 10px;min-width: 75px;text-align: right">'
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, -1, paramsDot)
if (previousItem) {
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">'
const previousval = formatScientificNotation(item.data[1], paramsDot)
let minusVal = 0
if (previousval <= val) {
minusVal = val - previousval
str += '+'
} else {
minusVal = previousval - val
str += '-'
} }
const val = formatScientificNotation(item.data[1], paramsDot)
sum += isNaN(self.numberWithEConvent(val)) ? 0 : Number(self.numberWithEConvent(val))
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(minusVal, null, -1, paramsDot) str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += '</span>' str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>`
} else if (tip.alias.indexOf('Previous ') !== -1) { str += '<div style="padding-left: 10px;min-width: 75px;text-align: right">'
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">' str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, -1, paramsDot)
str += '</span>' if (previousItem) {
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right;box-sizing: border-box;padding-right: 10px">'
const previousval = formatScientificNotation(previousItem.data[1], paramsDot)
let minusVal = 0
if (previousval <= val) {
minusVal = val - previousval
str += '+'
} else {
minusVal = previousval - val
str += '-'
}
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(minusVal, null, -1, paramsDot)
str += '</span>'
} else if (tip.alias.indexOf('Previous ') !== -1) {
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">'
str += '</span>'
}
str += '</div>'
str += '</div>'
} }
str += '</div>'
str += '</div>'
}) })
if (self.data.type === 'stackArea' || self.isStackArea) { if (self.data.type === 'stackArea' || self.isStackArea) {
if (!self.stackTotalColor || self.stackTotalColor == '') { if (!self.stackTotalColor || self.stackTotalColor == '') {
self.stackTotalColor = randomcolor() self.stackTotalColor = randomcolor()
} }
sum = parseFloat(Number(sum).toFixed(2)) sum = parseFloat(Number(sum).toFixed(6))
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += '<div style="line-height: 18px; font-size: 12px;padding-left:0px;">' str += '<div style="line-height: 18px; font-size: 12px;padding-left:0px;">'
str += `<span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${self.stackTotalColor};}'></span>` str += `<span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${self.stackTotalColor};}'></span>`
@@ -827,7 +887,11 @@ export default {
} }
str += '</div>' str += '</div>'
return str if (!showFlag) {
return ''
} else {
return str
}
} }
}, },
legend: { legend: {
@@ -946,6 +1010,8 @@ export default {
if (!maxValueCopies.copies) { if (!maxValueCopies.copies) {
option.yAxis.min = 0 option.yAxis.min = 0
option.yAxis.max = 1 option.yAxis.max = 1
} else {
option.yAxis.max = undefined
} }
if (unit.type == 'Time') { if (unit.type == 'Time') {
delete option.yAxis.maxInterval delete option.yAxis.maxInterval
@@ -1000,38 +1066,41 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
const vm = this const vm = this
setTimeout(function () { setTimeout(function () {
const divHeight = self.$refs.legendArea.offsetHeight const divHeight = self.$refs.legendArea && self.$refs.legendArea.offsetHeight > 20 ? self.$refs.legendArea.offsetHeight : 27
if (!chartInfo.height) { if (!chartInfo.height) {
getChart(self.chartIndex).resize({ height: (250 - divHeight - chartResizeTool.titleHeight - chartResizeTool.chartBlankHeight) }) getChart(self.chartIndex) && getChart(self.chartIndex).resize({ height: (250 - divHeight - chartResizeTool.titleHeight - chartResizeTool.chartBlankHeight) })
} else { } else {
getChart(self.chartIndex).resize({ height: (chartInfo.height * vm.stepWidth - divHeight - chartResizeTool.titleHeight - chartResizeTool.chartBlankHeight) }) getChart(self.chartIndex) && getChart(self.chartIndex).resize({ height: (chartInfo.height * vm.stepWidth - divHeight - chartResizeTool.titleHeight - chartResizeTool.chartBlankHeight) })
} }
if (dataArg && dataArg.length > 0) { if (dataArg && dataArg.length > 0) {
getChart(self.chartIndex).clear() getChart(self.chartIndex) && getChart(self.chartIndex).clear()
getChart(self.chartIndex).setOption(option)// 创建图表 getChart(self.chartIndex) && getChart(self.chartIndex).setOption(option)// 创建图表
self.noData = false self.noData = false
} else { } else {
self.noData = true self.noData = true
option = chartConfig.getOptionNoData('noData') option = chartConfig.getOptionNoData('noData')
if (self.$refs.resizeBox.offsetWidth < 200) { if (self.$refs.resizeBox && getChart(self.chartIndex)) {
option.xAxis.splitNumber = 1 if (self.$refs.resizeBox.offsetWidth < 200) {
} else if (self.$refs.resizeBox.offsetWidth < 300) { option.xAxis.splitNumber = 1
option.xAxis.splitNumber = 3 } else if (self.$refs.resizeBox.offsetWidth < 300) {
} else if (self.$refs.resizeBox.offsetWidth < 500) { option.xAxis.splitNumber = 3
option.xAxis.splitNumber = 5 } else if (self.$refs.resizeBox.offsetWidth < 500) {
option.xAxis.splitNumber = 5
}
getChart(self.chartIndex) && getChart(self.chartIndex).clear()
getChart(self.chartIndex) && getChart(self.chartIndex).setOption(option)// 创建图表
} }
getChart(self.chartIndex).clear()
getChart(self.chartIndex).setOption(option)// 创建图表
} }
self.$refs['localLoading' + self.chartIndex].endLoading() self.$refs['localLoading' + self.chartIndex] && self.$refs['localLoading' + self.chartIndex].endLoading()
self.firstShow = true // 展示操作按键 self.firstShow = true // 展示操作按键
}, 800) }, 800)
window.addEventListener('resize', this.chartResize) window.addEventListener('resize', this.chartResize)
getChart(this.chartIndex).off('magictypechanged')
getChart(this.chartIndex).on('magictypechanged', function (params) { getChart(this.chartIndex).on('magictypechanged', function (params) {
self.isStackArea = !self.isStackArea self.isStackArea = !self.isStackArea
if (self.isStackArea) { if (self.isStackArea) {
getChart(self.chartIndex).setOption({ getChart(self.chartIndex) && getChart(self.chartIndex).setOption({
toolbox: { toolbox: {
feature: { feature: {
dataZoom: { dataZoom: {
@@ -1063,6 +1132,7 @@ export default {
formatter: function (params) { formatter: function (params) {
let str = '<div>' let str = '<div>'
let sum = 0 let sum = 0
let showFlag = false
params.forEach((item, i) => { params.forEach((item, i) => {
const tip = self.legendMagicType[item.seriesIndex] const tip = self.legendMagicType[item.seriesIndex]
const color = self.bgColorList[item.seriesIndex] const color = self.bgColorList[item.seriesIndex]
@@ -1077,34 +1147,41 @@ export default {
str += bus.timeFormate(tData) str += bus.timeFormate(tData)
str += '</div>' str += '</div>'
} }
const val = formatScientificNotation(item.data[1], 2) showFlag = showFlag || item.data[1]
sum += self.numberWithEConvent(val) if (!isNaN(item.data[1] + '')) {
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' const val = formatScientificNotation(item.data[1], 2)
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>` sum += isNaN(self.numberWithEConvent(val)) ? 0 : Number(self.numberWithEConvent(val))
str += '<div style="padding-left: 10px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, -1, paramsDot) str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>`
str += '</div>' str += '<div style="padding-left: 10px;">'
str += '</div>' str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, -1, paramsDot)
str += '</div>'
str += '</div>'
}
}) })
if (self.data.type === 'stackArea' || self.isStackArea) { if (self.data.type === 'stackArea' || self.isStackArea) {
sum = parseFloat(Number(sum).toFixed(2)) sum = parseFloat(Number(sum).toFixed(6))
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += '<div style="line-height: 18px; font-size: 12px;padding-left:20px;">' str += '<div style="line-height: 18px; font-size: 12px;padding-left:20px;">'
str += self.$t('dashboard.panel.chartTotal') str += self.$t('dashboard.panel.chartTotal')
str += '</div>' str += '</div>'
str += '<div style="padding-left: 10px;">' str += '<div style="padding-left: 10px;">'
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(sum, null, 2) str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(sum, null, self.chartDot)
str += '</div>' str += '</div>'
str += '</div>' str += '</div>'
} }
str += '</div>' str += '</div>'
return str if (!showFlag) {
return ''
} else {
return str
}
} }
} }
}) })
} else { } else {
getChart(self.chartIndex).setOption({ getChart(self.chartIndex) && getChart(self.chartIndex).setOption({
toolbox: { toolbox: {
feature: { feature: {
dataZoom: { dataZoom: {
@@ -1194,7 +1271,7 @@ export default {
self.echartModalStore.off('finished') self.echartModalStore.off('finished')
}) })
}, 100) }, 100)
this.echartModalStore.off('magictypechanged')
this.echartModalStore.on('magictypechanged', function (params) { this.echartModalStore.on('magictypechanged', function (params) {
self.isStackArea = !self.isStackArea self.isStackArea = !self.isStackArea
if (self.isStackArea) { if (self.isStackArea) {
@@ -1231,6 +1308,7 @@ export default {
formatter: function (params) { formatter: function (params) {
let str = '<div>' let str = '<div>'
let sum = 0 let sum = 0
let showFlag = false
let minusFlag = true let minusFlag = true
params.forEach((item, i) => { params.forEach((item, i) => {
const tip = self.legendMagicType[item.seriesIndex] const tip = self.legendMagicType[item.seriesIndex]
@@ -1253,51 +1331,54 @@ export default {
str += '</div>' str += '</div>'
minusFlag = false minusFlag = false
} }
const previousItem = params.find((series) => ('Previous ' + item.seriesName) === series.seriesName) showFlag = showFlag || item.data[1]
const val = formatScientificNotation(item.data[1], 2) if (!isNaN(item.data[1] + '')) {
sum += self.numberWithEConvent(val) const previousItem = params.find((series) => ('Previous ' + item.seriesName) === series.seriesName)
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' const val = formatScientificNotation(item.data[1], 2)
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>` sum += isNaN(self.numberWithEConvent(val)) ? 0 : Number(self.numberWithEConvent(val))
str += '<div style="padding-left: 10px;min-width: 75px;text-align: right">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, self.chartDot) str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${color};}'></span>${tip ? (tip.alias ? tip.alias : tip.name) : item.seriesName} </div>`
if (previousItem) { str += '<div style="padding-left: 10px;min-width: 75px;text-align: right">'
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">' str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(val, null, self.chartDot)
const previousval = formatScientificNotation(previousItem.data[1], 2) if (previousItem) {
let minusVal = 0 str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right;box-sizing: border-box;padding-right: 10px">'
if (previousval <= val) { const previousval = formatScientificNotation(previousItem.data[1], 2)
minusVal = val - previousval let minusVal = 0
str += '+' if (previousval <= val) {
} else { minusVal = val - previousval
minusVal = previousval - val str += '+'
str += '-' } else {
} minusVal = previousval - val
str += '-'
}
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(minusVal, null, self.chartDot) str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(minusVal, null, self.chartDot)
str += '</span>' str += '</span>'
} else if (tip.alias.indexOf('Previous ') !== -1) { } else if (tip.alias.indexOf('Previous ') !== -1) {
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">' str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right">'
str += '</span>' str += '</span>'
}
str += '</div>'
if (previousItem) {
str += '<div style="padding-left: 10px;">'
const previousval = formatScientificNotation(previousItem.data[1], 2)
let minusVal = 0
if (previousval <= val) {
minusVal = val - previousval
str += '+'
} else {
minusVal = previousval - val
str += '-'
} }
str += '</div>'
if (previousItem) {
str += '<div style="padding-left: 10px;">'
const previousval = formatScientificNotation(previousItem.data[1], 2)
let minusVal = 0
if (previousval <= val) {
minusVal = val - previousval
str += '+'
} else {
minusVal = previousval - val
str += '-'
}
str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(minusVal, null, self.chartDot) str += chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(minusVal, null, self.chartDot)
str += '</div>'
}
str += '</div>' str += '</div>'
} }
str += '</div>'
}) })
if (self.data.type === 'stackArea' || self.isStackArea) { if (self.data.type === 'stackArea' || self.isStackArea) {
sum = parseFloat(Number(sum).toFixed(2)) sum = parseFloat(Number(sum).toFixed(6))
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
str += '<div style="line-height: 18px; font-size: 12px;padding-left:20px;">' str += '<div style="line-height: 18px; font-size: 12px;padding-left:20px;">'
str += self.$t('dashboard.panel.chartTotal') str += self.$t('dashboard.panel.chartTotal')
@@ -1309,7 +1390,11 @@ export default {
} }
str += '</div>' str += '</div>'
return str if (!showFlag) {
return ''
} else {
return str
}
} }
} }
}) })
@@ -1573,6 +1658,7 @@ export default {
this.echartModalStore.showLoading(); this.echartModalStore.showLoading();
} }
*/ */
const self = this
let axiosArr = [] let axiosArr = []
this.$nextTick(() => { this.$nextTick(() => {
let startTime = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss') let startTime = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
@@ -1588,7 +1674,7 @@ export default {
if (type === 'list') { // 普通模式,主控台使用 if (type === 'list') { // 普通模式,主控台使用
axiosArr = this.data.elements.map((ele) => { axiosArr = this.data.elements.map((ele) => {
const filterItem = ele const filterItem = ele
let query = filterItem.expression let query = encodeURIComponent(filterItem.expression)
if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null
!this.chartInfo.param && (this.chartInfo.param = {}) !this.chartInfo.param && (this.chartInfo.param = {})
this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null' this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null'
@@ -1601,7 +1687,7 @@ export default {
endTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[1], 'yyyy-MM-dd hh:mm:ss') endTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[1], 'yyyy-MM-dd hh:mm:ss')
this.data.elements.forEach((ele) => { this.data.elements.forEach((ele) => {
const filterItem = ele const filterItem = ele
let query = filterItem.expression let query = encodeURIComponent(filterItem.expression)
if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null
!this.chartInfo.param && (this.chartInfo.param = {}) !this.chartInfo.param && (this.chartInfo.param = {})
this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null' this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null'
@@ -1613,14 +1699,14 @@ export default {
} else if (type === 'dashboard') { // 概览模式,指标概览中使用 } else if (type === 'dashboard') { // 概览模式,指标概览中使用
// 概览模式,需要区分单独一个和多个 // 概览模式,需要区分单独一个和多个
if (this.stableFilter.chartCount === 'multiple') { if (this.stableFilter.chartCount === 'multiple') {
let query = this.data.name let query = encodeURIComponent(this.data.name)
if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null
this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null' this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null'
query += '&nullType=' + this.chartInfo.param.nullType query += '&nullType=' + this.chartInfo.param.nullType
} }
axiosArr = [this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step)] axiosArr = [this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step)]
} else { } else {
let query = this.data.elements[0].expression let query = encodeURIComponent(this.data.elements[0].expression)
if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null if (this.chartInfo.type === 'line' || this.chartInfo.type === 'bar' || this.chartInfo.type === 'stackArea') { // 如果是这三个 默认给null
this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null' this.chartInfo.param.nullType = this.chartInfo.param.nullType || 'null'
query += '&nullType=' + this.chartInfo.param.nullType query += '&nullType=' + this.chartInfo.param.nullType
@@ -1680,7 +1766,7 @@ export default {
label: { label: {
distance: this.computeDistance(chartDataFormat.getUnit(this.data.unit ? this.data.unit : 2).compute(this.data.param.threshold)), distance: this.computeDistance(chartDataFormat.getUnit(this.data.unit ? this.data.unit : 2).compute(this.data.param.threshold)),
formatter: function (params) { formatter: function (params) {
return chartDataFormat.getUnit(this.data.unit ? this.data.unit : 2).compute(params.value) return chartDataFormat.getUnit(self.data ? self.data.unit : 2).compute(params.value)
} }
}, },
lineStyle: { lineStyle: {
@@ -1718,7 +1804,7 @@ export default {
if (!host || host === '') { if (!host || host === '') {
host = elements.expression host = elements.expression
} }
let alias = this.dealLegendAlias(host, elements.legend) let alias = dealLegendAlias(host, elements.legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1816,23 +1902,6 @@ export default {
this.$refs['localLoading' + this.chartIndex].startLoading() this.$refs['localLoading' + this.chartIndex].startLoading()
this.divFirstShow = true this.divFirstShow = true
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
// 获取格式 // 获取格式
getNumStr (num) { getNumStr (num) {
if (num >= 1000) { if (num >= 1000) {
@@ -1863,18 +1932,32 @@ export default {
const copies = maxValueCopies.copies const copies = maxValueCopies.copies
const unit = maxValueCopies.unit const unit = maxValueCopies.unit
// const oldDot = maxValueCopies.oldDot // const oldDot = maxValueCopies.oldDot
getChart(this.chartIndex).setOption({ const option = {
series: this.seriesItem,
yAxis: { yAxis: {
minInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'min'), minInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'min'),
maxInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(dataArg.length / 5) maxInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(dataArg.length / 5)
} }
}
if (!maxValueCopies.copies) {
option.yAxis.min = 0
option.yAxis.max = 1
} else {
option.yAxis.max = undefined
}
if (unit.type == 'Time' || option.yAxis.maxInterval === 1) {
delete option.yAxis.maxInterval
}
getChart(this.chartIndex).setOption({
series: this.seriesItem,
yAxis: {
...option.yAxis
}
}) })
if (this.hasLegendOptions) { if (this.hasLegendOptions) {
this.computeLegendData(this.legendListMore, this.seriesItemArr, 'local') this.computeLegendData(this.legendListMore, this.seriesItemArr, 'local')
} }
this.$nextTick(() => { this.$nextTick(() => {
const divHeight = this.$refs.legendArea.offsetHeight const divHeight = this.$refs.legendArea && this.$refs.legendArea.offsetHeight > 20 ? this.$refs.legendArea.offsetHeight : 27
if (!this.chartInfo.height) { if (!this.chartInfo.height) {
getChart(this.chartIndex).resize({ height: (400 - divHeight - this.$chartResizeTool.titleHeight - this.$chartResizeTool.chartBlankHeight) }) getChart(this.chartIndex).resize({ height: (400 - divHeight - this.$chartResizeTool.titleHeight - this.$chartResizeTool.chartBlankHeight) })
} else { } else {
@@ -1896,12 +1979,26 @@ export default {
const copies = maxValueCopies.copies const copies = maxValueCopies.copies
const unit = maxValueCopies.unit const unit = maxValueCopies.unit
// const oldDot = maxValueCopies.oldDot // const oldDot = maxValueCopies.oldDot
this.echartModalStore.setOption({ const option = {
series: this.seriesItemScreen,
yAxis: { yAxis: {
minInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'min'), minInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'min'),
maxInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(dataArg.length / 5) maxInterval: chartDataFormat.Interval(maxValue, copies, unit.type, 'max') * Math.ceil(dataArg.length / 5)
} }
}
if (!maxValueCopies.copies) {
option.yAxis.min = 0
option.yAxis.max = 1
} else {
option.yAxis.max = undefined
}
if (unit.type == 'Time' || option.yAxis.maxInterval === 1) {
delete option.yAxis.maxInterval
}
this.echartModalStore.setOption({
series: this.seriesItemScreen,
yAxis: {
...option.yAxis
}
}) })
if (this.hasLegendOptions) { if (this.hasLegendOptions) {
this.computeLegendData(this.screenLegendListMore, this.seriesItemArrScreen, 'screen') this.computeLegendData(this.screenLegendListMore, this.seriesItemArrScreen, 'screen')

View File

@@ -126,6 +126,7 @@ import logTab from '@/components/page/dashboard/explore/logTab'
import bus from '@/libs/bus' import bus from '@/libs/bus'
import logsTempData from '@/components/charts/logsTempData' import logsTempData from '@/components/charts/logsTempData'
import { fromRoute } from '@/components/common/js/constants' import { fromRoute } from '@/components/common/js/constants'
import { dealLegendAlias } from '@/components/common/js/tools'
export default { export default {
name: 'logs', name: 'logs',
components: { components: {
@@ -312,7 +313,7 @@ export default {
const requestArr = [] const requestArr = []
this.expressions.forEach((item, index) => { this.expressions.forEach((item, index) => {
if (item != '' && this.from.trim() != fromRoute.chartTemp) { if (item != '' && this.from.trim() != fromRoute.chartTemp) {
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + item + '&start=' + this.$stringTimeParseToUnix(this.startTime) + '&end=' + this.$stringTimeParseToUnix(this.endTime) + '&limit=' + limit)) requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(item) + '&start=' + this.$stringTimeParseToUnix(this.startTime) + '&end=' + this.$stringTimeParseToUnix(this.endTime) + '&limit=' + limit))
} else if (item != '' && this.from.trim() == fromRoute.chartTemp) { } else if (item != '' && this.from.trim() == fromRoute.chartTemp) {
requestArr.push(logsTempData[index % 2]) requestArr.push(logsTempData[index % 2])
} }
@@ -395,7 +396,7 @@ export default {
const requestArr = [] const requestArr = []
this.expressions.forEach((item, index) => { this.expressions.forEach((item, index) => {
if (item != '' && this.from.trim() != fromRoute.chartTemp) { if (item != '' && this.from.trim() != fromRoute.chartTemp) {
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + item + '&start=' + this.$stringTimeParseToUnix(this.searchTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.searchTime[1]) + '&limit=' + limit)) requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(item) + '&start=' + this.$stringTimeParseToUnix(this.searchTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.searchTime[1]) + '&limit=' + limit))
} else if (item != '' && this.from.trim() == fromRoute.chartTemp) { } else if (item != '' && this.from.trim() == fromRoute.chartTemp) {
requestArr.push(logsTempData[index % 2]) requestArr.push(logsTempData[index % 2])
} }
@@ -523,7 +524,7 @@ export default {
host += '}' host += '}'
} }
// 处理legend别名 // 处理legend别名
alias = this.dealLegendAlias(host, this.chartData.elements[index].legend) alias = dealLegendAlias(host, this.chartData.elements[index].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -602,7 +603,7 @@ export default {
host += '}' host += '}'
} }
// 处理legend别名 // 处理legend别名
alias = this.dealLegendAlias(host, this.chartData.elements[index].legend) alias = dealLegendAlias(host, this.chartData.elements[index].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -672,23 +673,6 @@ export default {
reader.readAsText(error.response.data) reader.readAsText(error.response.data)
}) })
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
dateChange (time) { dateChange (time) {
this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss') this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss') this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss')

View File

@@ -157,7 +157,7 @@ export default {
}) })
this.term.open(terminalContainer) this.term.open(terminalContainer)
this.term.focus() this.term.focus()
const token = sessionStorage.getItem('nz-token') const token = localStorage.getItem('nz-token')
let baseUrl = JSON.parse(JSON.stringify(this.$axios.defaults.baseURL)) let baseUrl = JSON.parse(JSON.stringify(this.$axios.defaults.baseURL))
const protocol = window.location.protocol.indexOf('https') > -1 ? 'wss' : 'ws' const protocol = window.location.protocol.indexOf('https') > -1 ? 'wss' : 'ws'
if (baseUrl.startsWith('/')) { if (baseUrl.startsWith('/')) {

View File

@@ -508,13 +508,13 @@ export default {
host: this.customConnect.host, host: this.customConnect.host,
port: this.customConnect.port, port: this.customConnect.port,
authType: this.customConnect.authType, authType: this.customConnect.authType,
authUsername: encodeURIComponent(this.customConnect.authUsername), authUsername: encodeURIComponentComponent(this.customConnect.authUsername),
authPin: this.encode(this.customConnect.authPin), authPin: this.encode(this.customConnect.authPin),
authPriKey: encodeURIComponent(this.customConnect.authPriKey), authPriKey: encodeURIComponentComponent(this.customConnect.authPriKey),
authUserTip: encodeURIComponent(this.customConnect.authUserTip), authUserTip: encodeURIComponentComponent(this.customConnect.authUserTip),
authPinTip: encodeURIComponent(this.customConnect.authPinTip), authPinTip: encodeURIComponentComponent(this.customConnect.authPinTip),
authProtocolPort: encodeURIComponent(this.customConnect.authProtocolPort), authProtocolPort: encodeURIComponentComponent(this.customConnect.authProtocolPort),
authProtocol: encodeURIComponent(this.customConnect.authProtocol) authProtocol: encodeURIComponentComponent(this.customConnect.authProtocol)
} }
} }
this.editableTabsValue = newTabName this.editableTabsValue = newTabName
@@ -948,7 +948,7 @@ export default {
}, },
encode (str) { encode (str) {
// 对编码的字符串转化base64 // 对编码的字符串转化base64
const base64 = encodeURIComponent(btoa(str)) const base64 = encodeURIComponentComponent(btoa(str))
return base64 return base64
}, },
closeAssetCustom () { closeAssetCustom () {

View File

@@ -132,7 +132,7 @@
<popDataInfo :moduleId="moduleId" :projectId="projectInfo.id"></popDataInfo> <popDataInfo :moduleId="moduleId" :projectId="projectInfo.id"></popDataInfo>
</div> </div>
</div> </div>
<div :class="['page',fromOverView?'overview-page':'']"> <div :class="['page topo-page',fromOverView?'overview-page':'']">
<!--画布部分--> <!--画布部分-->
<div :id="'topology-canvas' + topologyIndexF" :ref="'topology-canvas'+ topologyIndexF" class="full" @contextmenu="onContextMenu($event)"></div> <div :id="'topology-canvas' + topologyIndexF" :ref="'topology-canvas'+ topologyIndexF" class="full" @contextmenu="onContextMenu($event)"></div>
<!--设置属性--> <!--设置属性-->
@@ -336,7 +336,7 @@ import alertTable from '../project/popData/alertTable'
import assetTable from '../project/popData/assetTable' import assetTable from '../project/popData/assetTable'
import endpointTable from '../project/popData/endpointTable' import endpointTable from '../project/popData/endpointTable'
import topoTooltip from '../project/L5/topoTooltip' import topoTooltip from '../project/L5/topoTooltip'
import { getMetricTypeValue } from '../js/tools' import { getMetricTypeValue, dealLegendAlias } from '../js/tools'
import bus from '../../../libs/bus' import bus from '../../../libs/bus'
import CanvasContextMenu from '@/components/common/project/L5/CanvasContextMenu' import CanvasContextMenu from '@/components/common/project/L5/CanvasContextMenu'
// 注册到画布 // 注册到画布
@@ -348,7 +348,7 @@ const canvasOptions = {
translateKey: 'None', translateKey: 'None',
disableEmptyLine: true, disableEmptyLine: true,
autoExpandDistance: 0, autoExpandDistance: 0,
minScale: 0.01 minScale: 0.2
// scaleKey: -1 // scaleKey: -1
} }
export default { export default {
@@ -681,7 +681,8 @@ export default {
resolve({ data: '', status: 'no query' }) resolve({ data: '', status: 'no query' })
}) })
} }
query += '&nullType=' + 'connected' query = encodeURIComponent(query)
query += '&nullType=' + 'null'
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step) return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step)
}) })
} }
@@ -698,6 +699,9 @@ export default {
}, 100) }, 100)
} else { } else {
Promise.all(promiseArr).then((res) => { Promise.all(promiseArr).then((res) => {
if (!getTopology(this.topologyIndex)) {
return
}
getTopology(this.topologyIndex).open(data) getTopology(this.topologyIndex).open(data)
getTopology(this.topologyIndex).lock(1) getTopology(this.topologyIndex).lock(1)
this.objChange = false this.objChange = false
@@ -780,6 +784,9 @@ export default {
// 打开topology数据 // 打开topology数据
openTopologyData (data) { openTopologyData (data) {
return new Promise(resolve => { return new Promise(resolve => {
if (!document.getElementById('topology-canvas' + this.topologyIndexF)) {
return
}
if (!getTopology(this.topologyIndex)) { if (!getTopology(this.topologyIndex)) {
const options = { const options = {
...canvasOptions ...canvasOptions
@@ -995,7 +1002,7 @@ export default {
host = pen.data.expressArr[innerPos] host = pen.data.expressArr[innerPos]
} }
// 处理legend别名 // 处理legend别名
let alias = this.dealLegendAlias(host, pen.data.legends[innerPos]) let alias = dealLegendAlias(host, pen.data.legends[innerPos])
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1009,23 +1016,6 @@ export default {
} }
return res return res
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
// Severity Label // Severity Label
returnSeverityLabel (key) { returnSeverityLabel (key) {
return this.$t(this.$CONSTANTS.alertMessage.severityData.find(s => { return s.value == key }).label) return this.$t(this.$CONSTANTS.alertMessage.severityData.find(s => { return s.value == key }).label)
@@ -1407,7 +1397,8 @@ export default {
} }
break break
case 'resize': { case 'resize': {
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
if (getTopology(this.topologyIndex)) { if (getTopology(this.topologyIndex)) {
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
} }
@@ -1417,7 +1408,8 @@ export default {
if (this.$refs.topTool) { if (this.$refs.topTool) {
this.$refs.topTool.scaleNum = parseInt(data * 100) this.$refs.topTool.scaleNum = parseInt(data * 100)
} }
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
if (getTopology(this.topologyIndex)) { if (getTopology(this.topologyIndex)) {
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
} }
@@ -1935,7 +1927,8 @@ export default {
index: 0, index: 0,
list: [JSON.parse(JSON.stringify(getTopology(this.topologyIndex).data))] list: [JSON.parse(JSON.stringify(getTopology(this.topologyIndex).data))]
} }
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
getTopology(this.topologyIndex).resize() getTopology(this.topologyIndex).resize()
}, 100) }, 100)
@@ -2057,7 +2050,8 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.previewData = topologyData this.previewData = topologyData
getTopology(this.topologyIndex).lock(1) getTopology(this.topologyIndex).lock(1)
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
this.initPens(topologyData) this.initPens(topologyData)
// this.reload() // this.reload()
@@ -2082,7 +2076,8 @@ export default {
winResize () { winResize () {
setTimeout(() => { setTimeout(() => {
const domRect = document.getElementById('topology-canvas' + this.topologyIndex).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndex)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
if (this.fromOverView) { if (this.fromOverView) {
getTopology(this.topologyIndex).open(this.oldTopologyData) getTopology(this.topologyIndex).open(this.oldTopologyData)
@@ -2093,7 +2088,7 @@ export default {
x: this.$refs['topology-canvas' + this.topologyIndexF].offsetWidth, x: this.$refs['topology-canvas' + this.topologyIndexF].offsetWidth,
y: this.$refs['topology-canvas' + this.topologyIndexF].offsetHeight y: this.$refs['topology-canvas' + this.topologyIndexF].offsetHeight
} }
getTopology(this.topologyIndex).data.pens.forEach(item => { getTopology(this.topologyIndex) && getTopology(this.topologyIndex).data.pens.forEach(item => {
if (flag) { if (flag) {
return return
} }

View File

@@ -19,36 +19,36 @@
<!------TAB区------> <!------TAB区------>
<div class="sub-list__tabs"> <div class="sub-list__tabs">
<!--机柜--> <!--机柜-->
<cabinet-tab v-if="from === fromRoute.dc && targetTab === 'cabinet'" :tabs="tabs.dc.cabinet" v-show="subResizeShow" :obj="obj" @changeTab="changeTab"></cabinet-tab> <cabinet-tab v-if="from === fromRoute.dc && targetTab === 'cabinet'" :tabs="tabs.dc.cabinet" v-show="subResizeShow" :obj="obj" @changeTab="changeTab" :targetTab.sync="targetTab"></cabinet-tab>
<alertMessageTabNew v-if="from === fromRoute.dc && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.dc.alertMessage" :targetTab="targetTab" @changeTab="changeTab"></alertMessageTabNew> <alertMessageTabNew v-if="from === fromRoute.dc && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.dc.alertMessage" @changeTab="changeTab" :targetTab.sync="targetTab"></alertMessageTabNew>
<!--告警信息--> <!--告警信息-->
<alert-message-tab v-if="((from === fromRoute.alertRule || from === fromRoute.asset || from === fromRoute.endpoint || from === fromRoute.project ) && targetTab === 'alertMessage')" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab"></alert-message-tab> <alert-message-tab v-if="((from === fromRoute.alertRule || from === fromRoute.asset || from === fromRoute.endpoint || from === fromRoute.project ) && targetTab === 'alertMessage')" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab" :targetTab.sync="targetTab"></alert-message-tab>
<!--asset页的endpoint列表--> <!--asset页的endpoint列表-->
<endpoint-tab v-if="from === fromRoute.asset && targetTab === fromRoute.endpoint" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab"></endpoint-tab> <endpoint-tab v-if="from === fromRoute.asset && targetTab === fromRoute.endpoint" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab" :targetTab.sync="targetTab"></endpoint-tab>
<!--terminal-log的记录和回放--> <!--terminal-log的记录和回放-->
<terminal-log-cmd-tab v-if="from === fromRoute.terminalLog && targetTab === 'cmdTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.cmd" @changeTab="changeTab"></terminal-log-cmd-tab> <terminal-log-cmd-tab v-if="from === fromRoute.terminalLog && targetTab === 'cmdTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.cmd" @changeTab="changeTab" :targetTab.sync="targetTab"></terminal-log-cmd-tab>
<terminal-log-record-tab v-if="from === fromRoute.terminalLog && targetTab === 'recordTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.record" @changeTab="changeTab"></terminal-log-record-tab> <terminal-log-record-tab v-if="from === fromRoute.terminalLog && targetTab === 'recordTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.record" @changeTab="changeTab" :targetTab.sync="targetTab"></terminal-log-record-tab>
<terminal-log-monitor-tab v-if="from === fromRoute.terminalLog && targetTab === 'monitorTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.monitor" @changeTab="changeTab" @exit="closeSubList"></terminal-log-monitor-tab> <terminal-log-monitor-tab v-if="from === fromRoute.terminalLog && targetTab === 'monitorTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.monitor" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></terminal-log-monitor-tab>
<asset-tab v-if="from === fromRoute.dc && targetTab === 'asset'" :tabs="tabs.dc.asset" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></asset-tab> <asset-tab v-if="from === fromRoute.dc && targetTab === 'asset'" :tabs="tabs.dc.asset" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab.sync="targetTab"></asset-tab>
<!--user列表的两个日志--> <!--user列表的两个日志-->
<operation-log-tab v-if="from === fromRoute.user && targetTab === 'operationLogTab'" :from="from" :obj="obj" :tabs="tabs.user.operationLog" @changeTab="changeTab"></operation-log-tab> <operation-log-tab v-if="from === fromRoute.user && targetTab === 'operationLogTab'" :from="from" :obj="obj" :tabs="tabs.user.operationLog" @changeTab="changeTab" :targetTab.sync="targetTab"></operation-log-tab>
<terminal-log-tab v-if="from === fromRoute.user && targetTab === 'terminalLogTab'" :from="from" :obj="obj" :tabs="tabs.user.terminalLog" @changeTab="changeTab"></terminal-log-tab> <terminal-log-tab v-if="from === fromRoute.user && targetTab === 'terminalLogTab'" :from="from" :obj="obj" :tabs="tabs.user.terminalLog" @changeTab="changeTab" :targetTab.sync="targetTab"></terminal-log-tab>
<!-- asset列表的3个 --> <!-- asset列表的3个 -->
<panel-tab-new @getTableData="getTableData" :paramsType="'asset'" v-if="from === fromRoute.asset && targetTab === 'panelTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.panel" :targetTab.sync="targetTab" @changeTab="changeTab"></panel-tab-new> <panel-tab-new @getTableData="getTableData" :paramsType="'asset'" v-if="from === fromRoute.asset && targetTab === 'panelTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.panel" :targetTab.sync="targetTab" @changeTab="changeTab"></panel-tab-new>
<alertMessageTabNew v-if="from === fromRoute.asset && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.alertMessage" :targetTab="targetTab" @changeTab="changeTab"></alertMessageTabNew> <alertMessageTabNew v-if="from === fromRoute.asset && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.alertMessage" :targetTab.sync="targetTab" @changeTab="changeTab" ></alertMessageTabNew>
<endpointTabNew v-if="from === fromRoute.asset && targetTab === 'endpointTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.endpoint" :targetTab="targetTab" @changeTab="changeTab"></endpointTabNew> <endpointTabNew v-if="from === fromRoute.asset && targetTab === 'endpointTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.endpoint" :targetTab.sync="targetTab" @changeTab="changeTab"></endpointTabNew>
<log-bottom-tab v-if="from === fromRoute.asset && targetTab === 'log'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.log" :targetTab.sync="targetTab" @changeTab="changeTab"></log-bottom-tab> <log-bottom-tab v-if="from === fromRoute.asset && targetTab === 'log'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.log" :targetTab.sync="targetTab" @changeTab="changeTab"></log-bottom-tab>
<assetSubTab v-if="from === fromRoute.asset && targetTab === 'assetSubTab' && obj.childrenNum" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.alertMessageSub" :targetTab="targetTab" @changeTab="changeTab"></assetSubTab> <assetSubTab v-if="from === fromRoute.asset && targetTab === 'assetSubTab' && obj.childrenNum" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.alertMessageSub" @changeTab="changeTab" :targetTab.sync="targetTab"></assetSubTab>
<!--module列表的tab--> <!--module列表的tab-->
<endpointTabNew v-if="from === fromRoute.module && targetTab === 'endpoint'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.module.moduleTabTitle" :targetTab="targetTab" @changeTab="changeTab"></endpointTabNew> <endpointTabNew v-if="from === fromRoute.module && targetTab === 'endpoint'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.module.moduleTabTitle" :targetTab="targetTab" @changeTab="changeTab"></endpointTabNew>
<alertMessageTabNew v-if="from === fromRoute.module && targetTab === 'moduleAlertMessage'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.module.moduleTabTitle" @changeTab="changeTab" :targetTab="targetTab"></alertMessageTabNew> <alertMessageTabNew v-if="from === fromRoute.module && targetTab === 'moduleAlertMessage'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.module.moduleTabTitle" @changeTab="changeTab" :targetTab="targetTab"></alertMessageTabNew>
<panel-tab-new @getTableData="getTableData" :paramsType="'module'" v-if="from === fromRoute.module && targetTab === 'panel'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.module.moduleTabTitle" :targetTab.sync="targetTab" @changeTab="changeTab"></panel-tab-new> <panel-tab-new @getTableData="getTableData" :paramsType="'module'" v-if="from === fromRoute.module && targetTab === 'panel'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.module.moduleTabTitle" :targetTab.sync="targetTab" @changeTab="changeTab"></panel-tab-new>
<!--endpoint列表的tab--> <!--endpoint列表的tab-->
<panel-tab-new v-if="from === fromRoute.endpoint && targetTab === 'panelTab'" v-show="subResizeShow" :from="from" :obj="obj" :paramsType="'endpoint'" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab" @getTableData="getTableData"></panel-tab-new> <panel-tab-new v-if="from === fromRoute.endpoint && targetTab === 'panelTab'" v-show="subResizeShow" :from="from" :obj="obj" :paramsType="'endpoint'" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab" @getTableData="getTableData"></panel-tab-new>
<endpointQuery v-if="from === fromRoute.endpoint && targetTab === 'endpointQuery'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab"></endpointQuery> <endpointQuery v-if="from === fromRoute.endpoint && targetTab === 'Metrics'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab"></endpointQuery>
<log-bottom-tab v-if="from === fromRoute.endpoint && targetTab === 'log' && hasLogConfig" v-show="subResizeShow" :from="from" :obj="obj" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab"></log-bottom-tab> <log-bottom-tab v-if="from === fromRoute.endpoint && targetTab === 'log' && hasLogConfig" v-show="subResizeShow" :from="from" :obj="obj" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab"></log-bottom-tab>
<alertMessageTabNew v-if="from === fromRoute.endpoint && targetTab === 'endpointAlertMessage'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab"></alertMessageTabNew> <alertMessageTabNew v-if="from === fromRoute.endpoint && targetTab === 'endpointAlertMessage'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="endpointTabs" :targetTab.sync="targetTab" @changeTab="changeTab"></alertMessageTabNew>
<!--chartTemp的Tab--> <!--chartTemp的Tab-->
@@ -205,7 +205,7 @@ export default {
endpointTabTitle: [ endpointTabTitle: [
{ prop: 'panelTab', name: this.$t('overall.detail') }, { prop: 'panelTab', name: this.$t('overall.detail') },
{ prop: 'endpointAlertMessage', name: this.$t('overall.alert') }, { prop: 'endpointAlertMessage', name: this.$t('overall.alert') },
{ prop: 'endpointQuery', name: 'Metrics' }, { prop: 'Metrics', name: 'Metrics' },
{ prop: 'log', name: 'Log' } { prop: 'log', name: 'Log' }
] ]
}, },
@@ -255,7 +255,7 @@ export default {
const tabs = [ const tabs = [
{ prop: 'panelTab', name: this.$t('overall.detail') }, { prop: 'panelTab', name: this.$t('overall.detail') },
{ prop: 'endpointAlertMessage', name: this.$t('overall.alert') }, { prop: 'endpointAlertMessage', name: this.$t('overall.alert') },
{ prop: 'endpointQuery', name: 'Metrics' } { prop: 'Metrics', name: 'Metrics' }
] ]
if (hasLog) { if (hasLog) {
tabs.push({ prop: 'log', name: 'Log' }) tabs.push({ prop: 'log', name: 'Log' })

View File

@@ -4,12 +4,12 @@
<div class="top-tool-left"> <div class="top-tool-left">
<div class="sub-list-title" v-if="showTitle">{{bottomHeaderTitle}}<slot name="title"></slot></div> <div class="sub-list-title" v-if="showTitle">{{bottomHeaderTitle}}<slot name="title"></slot></div>
<div class="sub-list-tabs"> <div class="sub-list-tabs">
<div v-for="tab in tabs" :key="tab.prop" :class="{'sub-list-tab--active': tab.active || tab.prop == targetTab }" :title='tab.prop + targetTab' class="sub-list-tab" @click="changeTab(tab.prop)">{{tab.name}}</div> <div v-for="tab in tabs" :key="tab.prop" :class="{'sub-list-tab--active': tab.active || tab.prop == targetTab }" :title='tab.prop' class="sub-list-tab" @click="changeTab(tab.prop)">{{tab.name}}</div>
</div> </div>
</div> </div>
<div class="top-tool-right" v-if="!customTool"> <div class="top-tool-right" v-if="!customTool">
<div v-if="layout.indexOf('searchInput') > -1" class="top-tool-search margin-r-20"> <div v-if="layout.indexOf('searchInput') > -1" class="top-tool-search margin-r-20">
<search-input :searchMsg="searchMsg" position="endpoint-bottom" @search="search" :targetTab="targetTab"></search-input> <search-input v-if="searchInputShow" :searchMsg="searchMsg" :position="'bottom' + targetTab + obj.id" @search="search" :targetTab="targetTab"></search-input>
</div> </div>
<slot name="top-tool-right"></slot> <slot name="top-tool-right"></slot>
<button v-if="layout.indexOf('elementSet') > -1" id="account-column-setting" class="top-tool-btn margin-r-20" <button v-if="layout.indexOf('elementSet') > -1" id="account-column-setting" class="top-tool-btn margin-r-20"
@@ -71,6 +71,7 @@ export default {
type: String, type: String,
default: '' default: ''
}, },
obj: { },
tabs: { tabs: {
type: Array type: Array
}, },
@@ -117,6 +118,7 @@ export default {
data () { data () {
return { return {
fromRoute: fromRoute, fromRoute: fromRoute,
searchInputShow: true,
tools: { tools: {
toTopBtnTop: this.$tableHeight.toTopBtnTop, // to-top按钮的top属性 toTopBtnTop: this.$tableHeight.toTopBtnTop, // to-top按钮的top属性
tableHover: false, // 控制滚动条和top按钮同时出现 tableHover: false, // 控制滚动条和top按钮同时出现
@@ -124,6 +126,20 @@ export default {
} }
} }
}, },
watch: {
obj (n) {
this.searchInputShow = false
setTimeout(() => {
this.searchInputShow = true
}, 100)
},
targetTab (n) {
this.searchInputShow = false
setTimeout(() => {
this.searchInputShow = true
}, 100)
}
},
methods: { methods: {
updateCustomTableTitle (custom) { updateCustomTableTitle (custom) {
this.$emit('update:customTableTitle', custom) this.$emit('update:customTableTitle', custom)

View File

@@ -2,6 +2,7 @@
<div class="full-width-height"> <div class="full-width-height">
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:api="url" :api="url"
:custom-table-title.sync="tools.customTableTitle" :custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet']" :layout="['searchInput', 'elementSet']"
@@ -54,6 +55,18 @@
class="line-chart-block-modal nz-dialog endpoint-dialog" class="line-chart-block-modal nz-dialog endpoint-dialog"
width="90%" width="90%"
@close="dialogClose"> @close="dialogClose">
<el-popover
v-if="isError"
placement="top-start"
:close-delay=10
trigger="hover"
popper-class="chart-error-popper">
<div >{{errorContent}}</div>
<span slot="reference" class="panel-info-corner panel-info-corner--error">
<i class="nz-icon nz-icon-warning fa-model" ></i>
<span class="panel-info-corner-inner"></span>
</span>
</el-popover>
<div slot="title"> <div slot="title">
{{$t("project.endpoint.dialogTitle")}} {{$t("project.endpoint.dialogTitle")}}
<div class="float-right panel-calendar dialog-tool" style="display: flex"> <div class="float-right panel-calendar dialog-tool" style="display: flex">
@@ -203,7 +216,9 @@ export default {
logData: [], logData: [],
chartLoading: false, chartLoading: false,
dialogShowText: false, dialogShowText: false,
dialogText: '' dialogText: '',
isError: false,
errorContent: ''
} }
}, },
methods: { methods: {
@@ -249,8 +264,7 @@ export default {
if (this.$refs.messageChart) { if (this.$refs.messageChart) {
this.$refs.messageChart.startLoading() this.$refs.messageChart.startLoading()
const axiosArr = [] const axiosArr = []
const paramStr = JSON.stringify(this.promQueryParamConvert(this.currentMsg)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(this.currentMsg.alertRule.expr.replace(/\r|\n+/g, '')) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step + '&filter=' + encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))))
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + paramStr.substring(1, paramStr.length - 1) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step))
this.legend = [] this.legend = []
this.chartDatas = [] this.chartDatas = []
axios.all(axiosArr).then(res => { axios.all(axiosArr).then(res => {
@@ -323,6 +337,17 @@ export default {
} else { } else {
this.$message.error(response.data.error) this.$message.error(response.data.error)
} }
} else {
this.$refs.messageChart.endLoading()
this.chartLoading = false
this.isError = true
if (response.msg) {
this.errorContent = response.msg
} else if (response.error) {
this.errorContent = response.error
} else {
this.errorContent = response
}
} }
}) })
this.$nextTick(() => { this.$nextTick(() => {
@@ -401,7 +426,7 @@ export default {
}, },
promQueryParamConvert (alert) { promQueryParamConvert (alert) {
const obj = { ...alert } const obj = { ...alert }
let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'') + ')' let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '') + ')'
let intoLabels = false let intoLabels = false
obj.labels = JSON.parse(obj.labels) obj.labels = JSON.parse(obj.labels)
if (Object.keys(obj.labels).length > 0) { if (Object.keys(obj.labels).length > 0) {
@@ -432,6 +457,14 @@ export default {
} }
return r return r
}, },
promQueryParamLabels (labels) {
const obj = JSON.parse(labels)
const filterArr = ['alertname', 'severity_id', 'severity', 'rule_type']
filterArr.forEach(key => {
delete obj[key]
})
return JSON.stringify(obj)
},
// asset弹框控制 // asset弹框控制
tabControl (data) { tabControl (data) {
if (data === 'close') { if (data === 'close') {
@@ -705,7 +738,7 @@ export default {
const start = this.searchTime[0] ? this.searchTime[0] : getTime(-1, 'h') const start = this.searchTime[0] ? this.searchTime[0] : getTime(-1, 'h')
const end = this.searchTime[1] ? this.searchTime[1] : getTime(0, 'h') const end = this.searchTime[1] ? this.searchTime[1] : getTime(0, 'h')
this.expressions = [this.currentMsg.alertRule.expr] this.expressions = [this.currentMsg.alertRule.expr]
this.$get('/logs/loki/api/v1/query_range?format=1&query=' + this.currentMsg.alertRule.expr + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit).then(res => { this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(this.currentMsg.alertRule.expr) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit + '&filter=' + encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))).then(res => {
this.chartLoading = false this.chartLoading = false
const logData = [res.data] const logData = [res.data]
this.resultType = res.data.resultType this.resultType = res.data.resultType

View File

@@ -1,6 +1,7 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:api="url" :api="url"
:custom-table-title.sync="tools.customTableTitle" :custom-table-title.sync="tools.customTableTitle"
:layout="['elementSet']" :layout="['elementSet']"

View File

@@ -2,7 +2,9 @@
<div> <div>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:api="url" :api="url"
:targetTab="targetTab"
style="height: 100%" style="height: 100%"
:custom-table-title.sync="tools.customTableTitle" :custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet']" :layout="['searchInput', 'elementSet']"

View File

@@ -2,6 +2,7 @@
<div> <div>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:targetTab.sync="targetTab" :targetTab.sync="targetTab"
:api="url" :api="url"
style="height: 100%" style="height: 100%"

View File

@@ -2,7 +2,9 @@
<div> <div>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:api="url" :api="url"
:targetTab="targetTab"
style="height: 100%" style="height: 100%"
:custom-table-title.sync="tools.customTableTitle" :custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet']" :layout="['searchInput', 'elementSet']"

View File

@@ -0,0 +1,624 @@
<template>
<div class="full-width-height">
<nz-bottom-data-lis
:layout="[]"
:tabs="tabs"
:targetTab="targetTab"
@changeTab="changeTab"
class="full-width-height"
>
<template v-slot:title><span :title="obj.name">{{obj.name}}</span></template>
<template v-slot>
<div class="panel">
<!--图表-->
<div class="table-list" id="tableList">
<div ref="dashboardScrollbar" id="dashboardScrollbar" style="height: 100%; overflow: auto;">
<div class="box-content">
<chart-list :nowTimeType='nowTimeType' :additional-info="obj" :detail="detail" :draggable="draggable" :from="from" :is-model="from == $CONSTANTS.fromRoute.model" @on-edit-chart="editChart"
@on-refresh-time="refreshTime" @on-remove-chart="delChart" ref="chartList" :panel-lock="panelLock"></chart-list>
</div>
</div>
</div>
<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">
<chart-box :chart="chart" :from="from" :panel-data="panelData" :panel-data-list="panelDataList" :show-panel="showPanel" @close="closeRightBox" @delete-chart="delChart" @on-create-success="createSuccess" @on-delete-success="delChartOk" ref="addChartModal" v-if="rightBox.show"></chart-box>
</transition>
</div>
</template>
</nz-bottom-data-lis>
</div>
</template>
<script>
import ChartBox from '../../../page/dashboard/chartBox'
import ChartList from '../../../charts/chart-list'
import bus from '../../../../libs/bus'
import subDataListMixin from '@/components/common/mixin/subDataList'
import nzBottomDataList from '@/components/common/bottomBox/nzBottomDataList'
export default {
name: 'chartTempPreview',
mixins: [subDataListMixin],
props: {
from: String,
obj: Object,
draggable: { type: Boolean, default: true },
detail: Object
},
data () {
return {
panelLock: true,
showTopBtn: false, // top按钮
visible: false,
rightBox: { // 面板弹出框相关
show: false
},
tableHover: false,
searchTime: bus.getTimezontDateRange(),
intervalTimer: null,
interval: 0,
panel: { // 新增panel
id: '',
name: ''
},
chart: {},
blankChart: {
id: '',
title: '',
type: 'line',
span: 12,
height: '400',
unit: 2,
param: {
url: '',
threshold: ''
},
elements: [{ expression: '', legend: '', type: 'expert', id: '' }],
panel: '',
sync: 0
},
pageObj: {
pageNo: 1,
pageSize: -1, // 此处获取所有数据,所以设置一个较大的值
total: 0
},
chartsData: [], // 中间部分图表相关数据
panelData: [],
panelDataList: [], // chartTemp列表
searchMsg: { // 给搜索框子组件传递的信息
zheze_none: true,
searchLabelList: [
]
},
searchLabel: {}, // 搜索参数
// ---图表相关参数--start
dataList: [], // 数据列表
// searchName: '', // 搜索名称
filter: { // 过滤条件
// productId: 0,
panelId: 0,
start_time: '',
end_time: '',
searchName: ''
},
showPanel: {
name: '',
type: this.from,
id: ''
},
// removeModal: false, // 删除弹出
// deleteObj: {}, // 删除对象
// ---图表相关参数--end
scrollbarWrap: null,
nowTimeType: {}
}
},
components: {
'chart-box': ChartBox,
'chart-list': ChartList,
nzBottomDataList
},
methods: {
// 刷新
refresh () {
this.getTableData(this.obj.id)
},
refreshTime (st, et) {
const startTime = bus.timeFormate(st, 'yyyy-MM-dd hh:mm')
const endTime = bus.timeFormate(et, 'yyyy-MM-dd hh:mm')
this.searchTime = [startTime, endTime]
},
panelReloadForDel () {
this.getTableData(this.obj.id)
},
/* 图表相关操作--start */
addChart () {
this.chart = this.newChart()
this.rightBox.show = true
},
newChart () {
return JSON.parse(JSON.stringify(this.blankChart))
},
// 切换tab
changeTab (tab) {
this.$emit('changeTab', tab)
},
closeRightBox (refresh) {
this.rightBox.show = false
if (refresh) {
this.refresh()
}
},
// 编辑图表信息,打开编辑弹窗
editChart (data) {
if (!data.param) {
data.param = { url: '', threshold: '' }
}
this.chart = JSON.parse(JSON.stringify(data))
this.rightBox.show = true
},
// 移除图表:弹出确认框询问
delChart (data, from) {
this.$confirm(this.$t('tip.confirmDelete'), {
confirmButtonText: this.$t('tip.yes'),
cancelButtonText: this.$t('tip.no'),
type: 'warning'
}).then(() => {})
},
delChartOk () {
this.getData(this.filter)
},
// 图表创建成功回调panel页面进行图表的刷新
createSuccess (msg, data, params) {
this.getData(this.filter)
},
// 获取数据,用在子页面
getData (params) {
if (params.start_time === '' || params.end_time === '') {
const now = bus.getTimezontDateRange()
const endTimeTmp = bus.timeFormate(now[1].getTime(), 'yyyy-MM-dd hh:mm:ss')
const startTimeTmp = bus.timeFormate(now[0].getTime(), 'yyyy-MM-dd hh:mm:ss')
params.start_time = startTimeTmp
params.end_time = endTimeTmp
params.from = this.from
}
if (this.$refs.chartList) {
this.$refs.chartList.initData(params)
}
},
/* 图表相关操作--end */
/* 时间条件查询--start */
// 选择日期变化
dateChange (val) {
// this.searchTime = [...val];
const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.setSearchTime(nowTimeType.type, nowTimeType.value)
this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss')
this.filter.panelId = this.showPanel.id
this.getData(this.filter)
},
/* 时间条件查询--end */
setSearchTime (type, val) { // 设置searchTime
if (type === 'minute') {
const startTime = bus.timeFormate(new Date(bus.computeTimezone(new Date().getTime())).setMinutes(new Date(bus.computeTimezone(new Date().getTime())).getMinutes() - val), 'yyyy-MM-dd hh:mm:ss')
const endTime = bus.timeFormate(new Date(bus.computeTimezone(new Date().getTime())), 'yyyy-MM-dd hh:mm:ss')
this.$set(this.searchTime, 0, startTime)
this.$set(this.searchTime, 1, endTime)
this.$set(this.searchTime, 2, val + 'm')
} else if (type === 'hour') {
const startTime = bus.timeFormate(new Date(bus.computeTimezone(new Date().getTime())).setHours(new Date(bus.computeTimezone(new Date().getTime())).getHours() - val), 'yyyy-MM-dd hh:mm:ss')
const endTime = bus.timeFormate(new Date(bus.computeTimezone(new Date().getTime())), 'yyyy-MM-dd hh:mm:ss')
this.$set(this.searchTime, 0, startTime)
this.$set(this.searchTime, 1, endTime)
this.$set(this.searchTime, 2, val + 'h')
} else if (type === 'date') {
const startTime = bus.timeFormate(new Date(bus.computeTimezone(new Date().getTime())).setDate(new Date(bus.computeTimezone(new Date().getTime())).getDate() - val), 'yyyy-MM-dd hh:mm:ss')
const endTime = bus.timeFormate(new Date(bus.computeTimezone(new Date().getTime())), 'yyyy-MM-dd hh:mm:ss')
this.$set(this.searchTime, 0, startTime)
this.$set(this.searchTime, 1, endTime)
this.$set(this.searchTime, 2, val + 'd')
}
this.$refs.pickTime.$refs.timePicker.searchTime = this.searchTime
},
// 公用操作
getTableData (linkId) {
if (this.from == this.$CONSTANTS.fromRoute.rule || this.from == this.$CONSTANTS.fromRoute.endpoint) {
this.getData(this.filter)
} else {
this.panelData = [this.obj]
if (this.panelData.length > 0) {
this.showPanel.id = this.filter.panelId = this.panelData[0].id
this.getData(this.filter)
}
}
},
// 定期刷新
selectInterval (val) {
this.visible = false
clearInterval(this.intervalTimer)
if (val) {
this.interval = val
const start = new Date(this.searchTime[1])
const now = new Date()
const interval = Math.floor((now.getTime() - start.getTime()) / 1000) // 计算当前结束时间到现在的间隔(秒)
if (interval >= 60) { // 如果结束时间到现在超过1分钟
this.getIntervalData(interval)
}
this.intervalTimer = setInterval(() => {
this.getIntervalData(this.interval)
}, val * 1000)
}
},
getIntervalData (interval) { // interval:结束时间到现在的秒数
const start = new Date(this.searchTime[0])
const end = new Date(this.searchTime[1])
start.setSeconds(start.getSeconds() + interval)
end.setSeconds(end.getSeconds() + interval)
const startTime = bus.timeFormate(start, 'yyyy-MM-dd hh:mm')
const endTime = bus.timeFormate(end, 'yyyy-MM-dd hh:mm')
this.searchTime = [startTime, endTime]
// 刷新数据
this.dateChange()
},
pageNo (val) {
this.pageObj.pageNo = val
this.getTableData(this.obj.id)
},
pageSize (val) {
this.pageObj.pageSize = val
this.getTableData(this.obj.id)
},
search: function () {
if (this.$refs.chartList) {
this.$refs.chartList.searchCharts(this.filter.searchName)
}
},
// 滚动事件触发下拉加载
onScroll () {
const _self = this
this.scrollbarWrap.addEventListener('scroll', bus.debounce(function () {
_self.showTopBtn = _self.scrollbarWrap.scrollTop > 50
_self.$refs.chartList.loadChartData(_self.scrollbarWrap.scrollTop)
}, 300))
},
focusInput: function () {
let classVal = document.getElementById('queryPanel').parentElement.getAttribute('class')
classVal = classVal.replace('query-input-inactive', 'query-input-active')
document.getElementById('queryPanel').parentElement.setAttribute('class', classVal)
this.$refs.queryPanel.focus()
},
blurInput: function () {
if (!this.filter.searchName || this.filter.searchName == '') {
setTimeout(function () {
let classVal = document.getElementById('queryPanel').parentElement.getAttribute('class')
classVal = classVal.replace('query-input-active', 'query-input-inactive')
document.getElementById('queryPanel').parentElement.setAttribute('class', classVal)
}, 100)
}
},
clearInput: function () {
this.$refs.queryPanel.focus()
},
syncChart: function () {
if (this.from == this.$CONSTANTS.fromRoute.asset || this.from == this.$CONSTANTS.fromRoute.model) {
this.$confirm(this.$t('tip.syncTip'), {
confirmButtonText: this.$t('tip.yes'),
cancelButtonText: this.$t('tip.no'),
type: 'warning'
}).then(() => {
const param = {
modelId: this.from == this.$CONSTANTS.fromRoute.model ? this.obj.id : null,
assetId: this.from == this.$CONSTANTS.fromRoute.asset ? this.obj.id : null
}
this.$put('/model/syncChart', param).then(response => {
if (response.code == 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.syncSuccess') })
if (this.from == this.$CONSTANTS.fromRoute.asset) {
this.refresh()
}
} else {
console.error(response.msg)
this.$message.error(response.msg)
}
})
})
}
},
toTop (wrap) {
let currentTop = wrap.scrollTop
const interval = currentTop / 10
const intervalFunc = setInterval(function () { // 花200ms分10次回到顶部模拟动画效果
if (currentTop === 0) {
clearInterval(intervalFunc)
} else {
currentTop = (currentTop - interval) < interval * 0.5 ? 0 : currentTop - interval
wrap.scrollTop = currentTop
}
}, 20)
},
tableListEnter () {
this.tableHover = true
},
tableListLeave () {
this.tableHover = false
}
},
mounted: function () {
this.scrollbarWrap = this.$refs.dashboardScrollbar
this.onScroll()
document.querySelector('#tableList').addEventListener('mouseenter', this.tableListEnter)
document.querySelector('#tableList').addEventListener('mouseleave', this.tableListLeave)
},
watch: {
'filter.searchName': function (n, o) {
const temp = this
setTimeout(function () {
temp.search()
}, 1000)
},
obj: {
immediate: true,
handler (n, o) {
setTimeout(() => {
if (n && n.id) {
this.getTableData(n.id)
}
}, 500)
}
}
},
beforeDestroy () {
document.querySelector('#tableList').removeEventListener('mouseenter', this.tableListEnter)
document.querySelector('#tableList').removeEventListener('mouseleave', this.tableListLeave)
if (this.scrollbarWrap) {
this.scrollbarWrap.removeEventListener('scroll', bus.debounce)
};
}
}
</script>
<style scoped lang="scss">
.panel {
height: 100%;
}
.panel .el-table {
border-radius: 5px;
}
.panel-list-width {
width:240px;
}
.panel-dropdown-title {
line-height:24px;
padding-left:5px;
margin-left:10px;
margin-top: 3px;
text-align:left;
border-radius:4px;
width:120px;
height:24px;
border:solid 1px #d8dce1;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
.panel-list-title {
min-height:24px;
width:100px;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
.panel-list-item {
width:190px;
white-space: nowrap;
overflow-x: hidden;
text-overflow: ellipsis;
}
.content-right-option {
cursor: pointer;
display: inline-block;
margin-right: 6px;
}
.content-right-option .nz-icon-delete {
color: #F98D9A;
}
.content-right-option .nz-icon-delete:hover {
color: #D96D7A;
}
.content-right-option .nz-icon-view {
color: #60BEFF;
}
.content-right-option .nz-icon-view:hover {
color: #409EFF;
}
/* begin-chart list*/
.table-list {
margin-top: 6px;
overflow-y: auto;
height: calc(100% - 56px);
}
.box-content {
position: relative;
}
/* end-chart list*/
/* begin--Panel-自定义可编辑的el-select下拉框样式*/
.panel-dropdown-btn {
display: inline-block;
margin-left: 7px;
float: right;
color: #60BEFF;
font-size: 13px
}
.panel-dropdown-btn:hover {
color: #409EFF;
}
.panel-dropdown-btn-create {
display: inline-block;
float: left;
font-size: 13px;
color: #F98D9A;
width: 100%;
}
.panel-dropdown-btn-create:hover {
color: #D96D7A;
}
.panel-dropdown-btn-delete {
color: #F98D9A;
font-size: 13px
}
.panel-dropdown-btn-delete:hover {
color: #D96D7A;
}
.panel-dropdown-error-message {
color: #F98D9A;
}
/* end--Panel-自定义可编辑的el-select下拉框样式*/
.panel-select-width {
width: 150px;
}
.panel-refresh-interval {
margin-right: 5px;
float: right;
}
.panel-refresh-interval-select {
width: 95px;
}
.panel-calendar {
float: right;
margin-right: 1px;
}
.top-tools {
button {
background: $btn-light-background-color;
outline: none;
border: 1px solid #ccc;
}
button:hover {
background: $btn-light-background-color-hover;
}
}
.nz-dashboard-dropdown {
height: 300px;
overflow-y: auto;
li {
/*padding: 0 20px !important;*/
padding-left:20px !important;
padding-right:0px !important;
width:240px;
white-space:nowrap;
overflow-x:hidden;
text-overflow:ellipsis;
}
}
.nz-dashboard-dropdown-bg {
background: $global-text-color-active;
color: #fff;
}
.el-dropdown-link {
cursor: pointer;
font-weight: bold;
}
.refresh {
display: flex;
background: #fff;
border-radius: 4px;
align-items: center;
justify-content: center;
margin: 0 10px;
border: 1px solid #ccc;
background: $btn-light-background-color;
span {
display: inline-block;
padding: 1px 8px;
}
}
.popover_ul li {
padding: 10px 3px;
cursor: pointer;
}
.popover_ul li:hover {
background: $dropdown-hover-background-color !important;
color: $global-text-color-active !important;
}
.nz-dashboard-refresh {
border-right: 1px solid #ccc;
color: #F0BF84;
}
.nz-dashboard-picker {
}
.full-width-height{
width: 100%;
height: 100%;
}
</style>
<style lang="scss">
.nz-dashboard-dropdown {
z-index: 3001 !important;
}
.panel .top-tools input {
background-color: $content-right-background-color;
}
.panel .top-tools .el-input__inner {
background-color: $content-right-background-color;
}
.panel-calendar .el-range-editor--mini.el-input__inner {
height: 25px !important;
border-color: #d8d8d8;
}
.panel-calendar .el-range-editor--mini .el-range__close-icon {
line-height: 18px;
}
.panel-calendar .el-range-editor--mini .el-range__icon {
display: none;
}
.panel-calendar .el-range-editor--mini .el-range-separator {
line-height: 17px;
}
.panel-calendar .el-date-editor--datetimerange.el-input, .panel-calendar .el-date-editor--datetimerange.el-input__inner {
padding-right: 0;
vertical-align: top;
}
.nz-dashboard-dropdown .nz-icon-edit {
font-size: 12px;
}
</style>

View File

@@ -2,6 +2,7 @@
<div class="full-width-height endpoint-tab-new"> <div class="full-width-height endpoint-tab-new">
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:api="url" :api="url"
:layout="['searchInput', 'elementSet']" :layout="['searchInput', 'elementSet']"
:search-msg="searchMsg" :search-msg="searchMsg"

View File

@@ -246,7 +246,7 @@ export default {
this.tableData = [] this.tableData = []
this.tableDataCopy = '' this.tableDataCopy = ''
setTimeout(() => { setTimeout(() => {
this.$get("/prom/api/v1/query?query={endpoint='" + this.currentEndpoint.id + "'}&time=" + this.formatTime).then(response => { this.$get('/prom/api/v1/query?query=' + encodeURIComponent("{endpoint_id='" + this.currentEndpoint.id + "'}") + '&time=' + this.formatTime).then(response => {
this.loading = false this.loading = false
if (response.status === 'success') { if (response.status === 'success') {
const results = response.data.result const results = response.data.result
@@ -448,13 +448,13 @@ export default {
} }
const axiosArr = [] const axiosArr = []
for (const endpoint of this.selectedEndpoints) { for (const endpoint of this.selectedEndpoints) {
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + endpoint.element + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(endpoint.element) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step))
} }
if (this.$refs.pickTime && this.$refs.pickTime.$refs.multipleTime && this.$refs.pickTime.$refs.multipleTime.searchTime.length) { // 判断是否需要添加比较 if (this.$refs.pickTime && this.$refs.pickTime.$refs.multipleTime && this.$refs.pickTime.$refs.multipleTime.searchTime.length) { // 判断是否需要添加比较
const startTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[0], 'yyyy-MM-dd hh:mm:ss') const startTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
const endTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[1], 'yyyy-MM-dd hh:mm:ss') const endTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[1], 'yyyy-MM-dd hh:mm:ss')
for (const endpoint of this.selectedEndpoints) { for (const endpoint of this.selectedEndpoints) {
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + endpoint.element + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(endpoint.element) + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step))
} }
} }
this.legend = [] this.legend = []

View File

@@ -2,6 +2,7 @@
<div class="full-width-height"> <div class="full-width-height">
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:api="url" :api="url"
:custom-table-title.sync="tools.customTableTitle" :custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet']" :layout="['searchInput', 'elementSet']"

View File

@@ -1,6 +1,7 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:custom-tool="true" :custom-tool="true"
:layout="[]" :layout="[]"
:show-pagination="false" :show-pagination="false"
@@ -114,7 +115,7 @@ export default {
if (item != '') { if (item != '') {
let expr = item let expr = item
this.matchContent && (expr = `${item} ${this.matchSymbol} "${this.matchContent}"`) this.matchContent && (expr = `${item} ${this.matchSymbol} "${this.matchContent}"`)
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + expr + '&start=' + this.$stringTimeParseToUnix(this.filterTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.filterTime[1]) + '&limit=' + limit)) requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(expr) + '&start=' + this.$stringTimeParseToUnix(this.filterTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.filterTime[1]) + '&limit=' + limit))
} }
}) })
axios.all(requestArr).then(res => { axios.all(requestArr).then(res => {

View File

@@ -1,11 +1,13 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:api="url" :obj='obj'
:custom-table-title.sync="tools.customTableTitle" :api="url"
:layout="['searchInput', 'elementSet']" :custom-table-title.sync="tools.customTableTitle"
:search-msg="searchMsg" :layout="['searchInput', 'elementSet']"
:tabs="tabs" :search-msg="searchMsg"
:tabs="tabs"
:targetTab="targetTab"
@changeTab="changeTab" @changeTab="changeTab"
@search="search" @search="search"
> >

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="full-width-height chart-list panel-tab-new"> <div class="full-width-height chart-list panel-tab-new asset-detail" v-loading="panelTabLoading">
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:layout="[]" :layout="[]"
:tabs="tabs" :tabs="tabs"
:targetTab="targetTab" :targetTab="targetTab"
@@ -41,6 +42,9 @@
<el-dropdown-item v-has="'panel_chart_add'"> <el-dropdown-item v-has="'panel_chart_add'">
<div id="chart-temp-add" @click="addChartByTemp"><i class="nz-icon nz-icon-add"></i>{{ $t('overall.AddByTemplate') }}</div> <div id="chart-temp-add" @click="addChartByTemp"><i class="nz-icon nz-icon-add"></i>{{ $t('overall.AddByTemplate') }}</div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-has="'panel_chart_edit'">
<div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div>
</el-dropdown-item>
</template> </template>
</top-tool-more-options> </top-tool-more-options>
</div> </div>
@@ -74,6 +78,9 @@
<el-dropdown-item v-has="'panel_chart_add'"> <el-dropdown-item v-has="'panel_chart_add'">
<div id="chart-temp-add" @click="addChartByTemp"><i class="nz-icon nz-icon-add"></i>{{ $t('overall.AddByTemplate') }}</div> <div id="chart-temp-add" @click="addChartByTemp"><i class="nz-icon nz-icon-add"></i>{{ $t('overall.AddByTemplate') }}</div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-has="'panel_chart_edit'">
<div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div>
</el-dropdown-item>
</template> </template>
</top-tool-more-options> </top-tool-more-options>
</div> </div>
@@ -93,7 +100,7 @@
<div class="table-list" id="tableList"> <div class="table-list" id="tableList">
<div ref="dashboardScrollbar" id="dashboardScrollbar" style="height: 100%; overflow: auto;"> <div ref="dashboardScrollbar" id="dashboardScrollbar" style="height: 100%; overflow: auto;">
<div class="box-content"> <div class="box-content">
<chart-list :draggable="draggable" :from="from" :is-model="from === fromRoute.model" :obj="obj" @on-edit-chart="editChart" <chart-list :nowTimeType='nowTimeType' :draggable="draggable" :from="from" :is-model="from === fromRoute.model" :obj="obj" @on-edit-chart="editChart"
@on-refresh-time="refreshTime" @on-remove-chart="delChart" ref="chartList" :panel-lock="panelLock" :panel-data-list="panelDataList" @on-refresh-time="refreshTime" @on-remove-chart="delChart" ref="chartList" :panel-lock="panelLock" :panel-data-list="panelDataList"
@on-add-group-item-chart="addGroupItem"></chart-list> @on-add-group-item-chart="addGroupItem"></chart-list>
</div> </div>
@@ -137,6 +144,7 @@ export default {
data () { data () {
return { return {
fromRoute, fromRoute,
panelTabLoading: false,
panelLock: true, panelLock: true,
showTopBtn: false, // top按钮 showTopBtn: false, // top按钮
visible: false, visible: false,
@@ -213,7 +221,8 @@ export default {
// ---图表相关参数--end // ---图表相关参数--end
scrollbarWrap: null, scrollbarWrap: null,
panelDataList: [], panelDataList: [],
batchDeleteObjs: [] batchDeleteObjs: [],
nowTimeType: {}
} }
}, },
components: { components: {
@@ -347,6 +356,7 @@ export default {
// this.searchTime = [...val]; // this.searchTime = [...val];
if (this.$refs.pickTime) { if (this.$refs.pickTime) {
const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.setSearchTime(nowTimeType.type, nowTimeType.value) this.setSearchTime(nowTimeType.type, nowTimeType.value)
this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss') this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss') this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss')
@@ -551,9 +561,11 @@ export default {
this.panelLock = boolean this.panelLock = boolean
}, },
chartBySync () { chartBySync () {
this.$post('visual/panel/chart/syncTmpl', { pid: this.obj.id }).then(res => { this.panelTabLoading = true
this.$post('visual/panel/chart/syncTmpl', { panelId: this.showPanel.id }).then(res => {
this.panelTabLoading = false
if (res.code === 200) { if (res.code === 200) {
this.getTableData() this.getTableData(this.obj.id)
this.$message.success(this.$t('tip.syncSuccess')) this.$message.success(this.$t('tip.syncSuccess'))
} else { } else {
this.$message.error(res.msg) this.$message.error(res.msg)

View File

@@ -1,8 +1,10 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:layout="[]" :layout="[]"
:tabs="tabs" :tabs="tabs"
:targetTab="targetTab"
@changeTab="changeTab" @changeTab="changeTab"
:title="'Session ID'" :title="'Session ID'"
> >

View File

@@ -1,8 +1,10 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:layout="[]" :layout="[]"
:tabs="tabs" :tabs="tabs"
:targetTab="targetTab"
@changeTab="changeTab" @changeTab="changeTab"
:title="'Session ID'" :title="'Session ID'"
> >
@@ -91,7 +93,7 @@ export default {
}) })
this.terminal.open(document.getElementById(this.obj.uuid)) this.terminal.open(document.getElementById(this.obj.uuid))
const token = sessionStorage.getItem('nz-token') const token = localStorage.getItem('nz-token')
let baseUrl = this.$axios.defaults.baseURL let baseUrl = this.$axios.defaults.baseURL
if (baseUrl.startsWith('/')) { if (baseUrl.startsWith('/')) {
baseUrl = 'ws://' + window.location.host + baseUrl baseUrl = 'ws://' + window.location.host + baseUrl

View File

@@ -1,11 +1,13 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:layout="[]" :layout="[]"
:tabs="tabs" :tabs="tabs"
:targetTab="targetTab"
@changeTab="changeTab" @changeTab="changeTab"
:title="'Session ID'" :title="'Session ID'"
> >
<template v-slot:title><span :title="obj.uuid.substring(0, 8).toUpperCase()">{{obj.uuid.substring(0, 8).toUpperCase()}}</span></template> <template v-slot:title><span :title="obj.uuid.substring(0, 8).toUpperCase()">{{obj.uuid.substring(0, 8).toUpperCase()}}</span></template>
<template v-slot> <template v-slot>
<div class="replay-container"> <div class="replay-container">

View File

@@ -1,6 +1,8 @@
<template> <template>
<nz-bottom-data-list <nz-bottom-data-list
:showTitle='showTitle' :showTitle='showTitle'
:obj='obj'
:targetTab="targetTab"
:api="url" :api="url"
:custom-table-title.sync="tools.customTableTitle" :custom-table-title.sync="tools.customTableTitle"
:layout="['searchInput', 'elementSet']" :layout="['searchInput', 'elementSet']"

View File

@@ -2,23 +2,23 @@
<div class="sub-box detail-view-sub-box"> <div class="sub-box detail-view-sub-box">
<div class="sub-list__tabs"> <div class="sub-list__tabs">
<!--机柜--> <!--机柜-->
<cabinet-tab :showTitle="false" v-if="from === fromRoute.dc && targetTab === 'cabinet'" :tabs="tabs.dc.cabinet" v-show="subResizeShow" :obj="obj" @changeTab="changeTab"></cabinet-tab> <cabinet-tab :showTitle="false" v-if="from === fromRoute.dc && targetTab === 'cabinet'" :tabs="tabs.dc.cabinet" v-show="subResizeShow" :obj="obj" @changeTab="changeTab" :targetTab="targetTab"></cabinet-tab>
<alertMessageTabNew :showTitle="false" v-if="from === fromRoute.dc && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.dc.alertMessage" :targetTab="targetTab" @changeTab="changeTab"></alertMessageTabNew> <alertMessageTabNew :showTitle="false" v-if="from === fromRoute.dc && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.dc.alertMessage" :targetTab="targetTab" @changeTab="changeTab"></alertMessageTabNew>
<!--告警信息--> <!--告警信息-->
<alert-message-tab :showTitle="false" v-if="((from === fromRoute.alertRule || from === fromRoute.asset || from === fromRoute.endpoint || from === fromRoute.project ) && targetTab === 'alertMessage')" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab"></alert-message-tab> <alert-message-tab :showTitle="false" v-if="((from === fromRoute.alertRule || from === fromRoute.asset || from === fromRoute.endpoint || from === fromRoute.project ) && targetTab === 'alertMessage')" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab" :targetTab="targetTab"></alert-message-tab>
<!--asset页的endpoint列表--> <!--asset页的endpoint列表-->
<endpoint-tab :showTitle="false" v-if="from === fromRoute.asset && targetTab === fromRoute.endpoint" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab"></endpoint-tab> <endpoint-tab :showTitle="false" v-if="from === fromRoute.asset && targetTab === fromRoute.endpoint" v-show="subResizeShow" :from="from" :obj="obj" @changeTab="changeTab" :targetTab="targetTab"></endpoint-tab>
<!--terminal-log的记录和回放--> <!--terminal-log的记录和回放-->
<terminal-log-cmd-tab :showTitle="false" v-if="from === fromRoute.terminalLog && targetTab === 'cmdTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.cmd" @changeTab="changeTab"></terminal-log-cmd-tab> <terminal-log-cmd-tab :showTitle="false" v-if="from === fromRoute.terminalLog && targetTab === 'cmdTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.cmd" @changeTab="changeTab" :targetTab="targetTab"></terminal-log-cmd-tab>
<terminal-log-record-tab :showTitle="false" v-if="from === fromRoute.terminalLog && targetTab === 'recordTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.record" @changeTab="changeTab"></terminal-log-record-tab> <terminal-log-record-tab :showTitle="false" v-if="from === fromRoute.terminalLog && targetTab === 'recordTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.record" @changeTab="changeTab" :targetTab="targetTab"></terminal-log-record-tab>
<terminal-log-monitor-tab :showTitle="false" v-if="from === fromRoute.terminalLog && targetTab === 'monitorTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.monitor" @changeTab="changeTab" @exit="closeSubList"></terminal-log-monitor-tab> <terminal-log-monitor-tab :showTitle="false" v-if="from === fromRoute.terminalLog && targetTab === 'monitorTab'" :from="from" :obj="obj" :tabs="tabs.terminalLog.monitor" @changeTab="changeTab" @exit="closeSubList" :targetTab="targetTab"></terminal-log-monitor-tab>
<asset-tab :showTitle="false" v-if="from === fromRoute.dc && targetTab === 'asset'" :tabs="tabs.dc.asset" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList"></asset-tab> <asset-tab :showTitle="false" v-if="from === fromRoute.dc && targetTab === 'asset'" :tabs="tabs.dc.asset" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab="targetTab"></asset-tab>
<!--user列表的两个日志--> <!--user列表的两个日志-->
<operation-log-tab :showTitle="false" v-if="from === fromRoute.user && targetTab === 'operationLogTab'" :from="from" :obj="obj" :tabs="tabs.user.operationLog" @changeTab="changeTab"></operation-log-tab> <operation-log-tab :showTitle="false" v-if="from === fromRoute.user && targetTab === 'operationLogTab'" :from="from" :obj="obj" :tabs="tabs.user.operationLog" @changeTab="changeTab" :targetTab="targetTab"></operation-log-tab>
<terminal-log-tab :showTitle="false" v-if="from === fromRoute.user && targetTab === 'terminalLogTab'" :from="from" :obj="obj" :tabs="tabs.user.terminalLog" @changeTab="changeTab"></terminal-log-tab> <terminal-log-tab :showTitle="false" v-if="from === fromRoute.user && targetTab === 'terminalLogTab'" :from="from" :obj="obj" :tabs="tabs.user.terminalLog" @changeTab="changeTab" :targetTab="targetTab"></terminal-log-tab>
<!-- asset列表的3个 --> <!-- asset列表的3个 -->
<panel-tab-new @getTableData="getTableData" :paramsType="'asset'" :showTitle="false" v-if="from === fromRoute.asset && targetTab === 'panelTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.panel" :targetTab.sync="targetTab" @changeTab="changeTab"></panel-tab-new> <panel-tab-new @getTableData="getTableData" :paramsType="'asset'" :showTitle="false" v-if="from === fromRoute.asset && targetTab === 'panelTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.panel" :targetTab.sync="targetTab" @changeTab="changeTab"></panel-tab-new>
<alertMessageTabNew :showTitle="false" v-if="from === fromRoute.asset && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.alertMessage" :targetTab="targetTab" @changeTab="changeTab"></alertMessageTabNew> <alertMessageTabNew :showTitle="false" v-if="from === fromRoute.asset && targetTab === 'alertMessageTab'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.asset.alertMessage" :targetTab="targetTab" @changeTab="changeTab"></alertMessageTabNew>
@@ -40,7 +40,7 @@
<alertMessageTabNew v-if="from === fromRoute.alertRule && targetTab === 'alertRuleAlertMessage'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertRule.alertRule" @changeTab="changeTab" :targetTab.sync="targetTab"></alertMessageTabNew> <alertMessageTabNew v-if="from === fromRoute.alertRule && targetTab === 'alertRuleAlertMessage'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertRule.alertRule" @changeTab="changeTab" :targetTab.sync="targetTab"></alertMessageTabNew>
<alertRuleEvalLog v-if="from === fromRoute.alertRule && targetTab === 'evalLog'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertRule.alertRule" @changeTab="changeTab" :targetTab.sync="targetTab"></alertRuleEvalLog> <alertRuleEvalLog v-if="from === fromRoute.alertRule && targetTab === 'evalLog'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertRule.alertRule" @changeTab="changeTab" :targetTab.sync="targetTab"></alertRuleEvalLog>
<!--model 下滑--> <!--model 下滑-->
<asset-tab :showTitle="false" v-if="(from === fromRoute.model) && targetTab === 'asset'" :tabs="tabs.model" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList"></asset-tab> <asset-tab :showTitle="false" v-if="(from === fromRoute.model) && targetTab === 'asset'" :tabs="tabs.model" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab="targetTab"></asset-tab>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -720,6 +720,10 @@ export const tableSet = {
return function (obj1, obj2) { return function (obj1, obj2) {
let val1 = obj1[prop] let val1 = obj1[prop]
let val2 = obj2[prop] let val2 = obj2[prop]
if (prop === 'value') {
val1 = obj1.oldValue
val2 = obj2.oldValue
}
if (!isNaN(val1) && !isNaN(val2) && prop === 'value') { if (!isNaN(val1) && !isNaN(val2) && prop === 'value') {
val1 = Number(val1) val1 = Number(val1)
val2 = Number(val2) val2 = Number(val2)
@@ -754,7 +758,11 @@ export const tableSet = {
return function (obj1, obj2) { return function (obj1, obj2) {
let val1 = obj1[prop] let val1 = obj1[prop]
let val2 = obj2[prop] let val2 = obj2[prop]
if (!isNaN(Number(val1)) && !isNaN(Number(val2)) && prop !== 'time') { if (prop === 'value') {
val1 = obj1.oldValue
val2 = obj2.oldValue
}
if (!isNaN(Number(val1)) && !isNaN(Number(val2)) && prop === 'value') {
val1 = Number(val1) val1 = Number(val1)
val2 = Number(val2) val2 = Number(val2)
} }
@@ -864,3 +872,21 @@ export function formatScientificNotation (value, dot = 2) {
return getTdDom(dom.parentElement); return getTdDom(dom.parentElement);
} }
} */ } */
/* 处理legend的别名 */
export function dealLegendAlias (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp('\\b' + label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
}

View File

@@ -214,6 +214,8 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.needMore(type, item, true) this.needMore(type, item, true)
}) })
} else if (!value.length) {
this.$refs[`${type}_${item.id}_cascader`][0].$el.querySelector('.el-input__inner').style.width = ''
} }
/* 组织参数 */ /* 组织参数 */

View File

@@ -168,7 +168,7 @@ export default {
localStorage.setItem('nz-language-list', JSON.stringify(langList)) localStorage.setItem('nz-language-list', JSON.stringify(langList))
} }
}) })
sessionStorage.setItem('nz-token', res.data.authToken) localStorage.setItem('nz-token', res.data.authToken)
if (res.data.authFlag === 1) { if (res.data.authFlag === 1) {
if (res.data.authBind === 0) { if (res.data.authBind === 0) {
this.verifyShow = true this.verifyShow = true
@@ -190,7 +190,7 @@ export default {
}) })
} }
} else { } else {
sessionStorage.setItem('nz-username', this.loginData.username) localStorage.setItem('nz-username', this.loginData.username)
localStorage.setItem('nz-username', this.loginData.username) localStorage.setItem('nz-username', this.loginData.username)
localStorage.setItem('nz-prometheus-federation-enabled', res.data.prometheusFederationEnabled) localStorage.setItem('nz-prometheus-federation-enabled', res.data.prometheusFederationEnabled)
localStorage.setItem('nz-language', this.lang) localStorage.setItem('nz-language', this.lang)
@@ -211,7 +211,7 @@ export default {
} }
this.$post('/mfa/verify', params).then(res => { this.$post('/mfa/verify', params).then(res => {
if (res.code === 200) { if (res.code === 200) {
sessionStorage.setItem('nz-username', this.loginData.username) localStorage.setItem('nz-username', this.loginData.username)
localStorage.setItem('nz-username', this.loginData.username) localStorage.setItem('nz-username', this.loginData.username)
localStorage.setItem('nz-prometheus-federation-enabled', res.data.prometheusFederationEnabled) localStorage.setItem('nz-prometheus-federation-enabled', res.data.prometheusFederationEnabled)
localStorage.setItem('nz-language', this.lang) localStorage.setItem('nz-language', this.lang)
@@ -303,7 +303,7 @@ export default {
}, },
downloadTxt () { downloadTxt () {
const element = document.createElement('a') const element = document.createElement('a')
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(this.fileContent)) element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponentComponent(this.fileContent))
element.setAttribute('download', 'Nezha recovery codes') element.setAttribute('download', 'Nezha recovery codes')
element.style.display = 'none' element.style.display = 'none'
element.click() element.click()

View File

@@ -96,7 +96,7 @@ export default {
}) })
} }
if (this.detailType === 'view') { if (this.detailType === 'view') {
this.$refs.dataDetail.$refs.dataTable.scrollTop = 0 this.$refs.dataDetail && (this.$refs.dataDetail.$refs.dataTable.scrollTop = 0)
} }
} }
}) })
@@ -241,7 +241,11 @@ export default {
if (typeof row.labels === 'string') row.labels = JSON.parse(row.labels) if (typeof row.labels === 'string') row.labels = JSON.parse(row.labels)
const labels = JSON.parse(JSON.stringify(row.labels)) const labels = JSON.parse(JSON.stringify(row.labels))
this.objectSilence.matchers = [] this.objectSilence.matchers = []
const filterArr = ['alertname', 'severity_id', 'severity', 'rule_type']
Object.keys(labels).forEach((key, i) => { Object.keys(labels).forEach((key, i) => {
if (filterArr.indexOf(key) != -1) {
return
}
this.objectSilence.matchers.push( this.objectSilence.matchers.push(
{ name: key, value: labels[key], regex: 0 } { name: key, value: labels[key], regex: 0 }
) )

View File

@@ -141,8 +141,10 @@ export default {
}, },
dateChange (time) { dateChange (time) {
this.searchTime = time this.searchTime = time
this.$emit('change', this.searchTime) setTimeout(() => {
this.refreshDataFunc() this.$emit('change', this.searchTime)
this.refreshDataFunc()
}, 100)
}, },
antiShake () { antiShake () {
if (this.timer) { if (this.timer) {

View File

@@ -28,10 +28,10 @@
<span class="el-dropdown-link tree--operation" @click.stop><i class="nz-icon nz-icon-more1"></i></span> <span class="el-dropdown-link tree--operation" @click.stop><i class="nz-icon nz-icon-more1"></i></span>
<el-dropdown-menu class="right-box-select-top" slot="dropdown" v-has="['panel_edit', 'panel_delete']"> <el-dropdown-menu class="right-box-select-top" slot="dropdown" v-has="['panel_edit', 'panel_delete']">
<el-dropdown-item> <el-dropdown-item>
<span @click.stop="editPanel(data)"><i v-has="'panel_edit'" class="nz-icon nz-icon-edit"></i>{{$t('overall.edit')}}</span> <div @click="editPanel(data)"><i v-has="'panel_edit'" class="nz-icon nz-icon-edit"></i>{{$t('overall.edit')}}</div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item> <el-dropdown-item>
<span @click.stop="deletePanel(data)" v-has="'panel_delete'"><i class="nz-icon nz-icon-delete"></i>{{$t('overall.delete')}}</span> <div @click="deletePanel(data)" v-has="'panel_delete'"><i class="nz-icon nz-icon-delete"></i>{{$t('overall.delete')}}</div>
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>

View File

@@ -1,7 +1,8 @@
<template> <template>
<div class="props-box" :loading="loading"> <div class="props-box" :loading="loading">
<!--所有属性--> <!--所有属性-->
<el-tabs v-model="tab" type="card" v-if="selection.pen" @tab-click="tabClick"> <keep-alive>
<el-tabs v-model="tab" type="card" v-if="selection.pen" @tab-click="tabClick">
<el-tab-pane :label="$t('project.topology.data')" name="1"> <el-tab-pane :label="$t('project.topology.data')" name="1">
<el-form v-model="selection.pen.data" class="pens-data" label-position="top"> <el-form v-model="selection.pen.data" class="pens-data" label-position="top">
<!--module--> <!--module-->
@@ -748,8 +749,10 @@
</el-collapse> </el-collapse>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</keep-alive>
<!--选中多个--> <!--选中多个-->
<div v-else-if="selection.pens" class=""> <keep-alive>
<div v-if="selection.pens" class="">
<el-collapse v-model="activeNames"> <el-collapse v-model="activeNames">
<!--对齐方式--> <!--对齐方式-->
<el-collapse-item :title="$t('project.topology.align')" name="1" v-if="selection.pens"> <el-collapse-item :title="$t('project.topology.align')" name="1" v-if="selection.pens">
@@ -816,8 +819,10 @@
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</div> </div>
</keep-alive>
<!-- 选中为空 --> <!-- 选中为空 -->
<div v-else style="height: 100%"> <keep-alive>
<div v-if="!selection.pens&&!selection.pen" style="height: 100%">
<div class="project-title"> <div class="project-title">
Project Project
</div> </div>
@@ -1080,7 +1085,7 @@
</div> </div>
</div> </div>
</keep-alive>
</div> </div>
</template> </template>
@@ -1582,7 +1587,7 @@ export default {
}, },
onClickName (name) { onClickName (name) {
this.pen.name = name this.pen.name = name
// this.pen.calcControlPoints() this.selection.pen.calcControlPoints()
this.drowdown = 0 this.drowdown = 0
if (this.selection.pen) { if (this.selection.pen) {
this.selection.pen.name = name this.selection.pen.name = name

View File

@@ -40,6 +40,7 @@ import { fromRoute } from '@/components/common/js/constants'
import chartTempData from '@/components/charts/chartTempData' import chartTempData from '@/components/charts/chartTempData'
import axios from 'axios' import axios from 'axios'
import chartDataFormat from '@/components/charts/chartDataFormat' import chartDataFormat from '@/components/charts/chartDataFormat'
import { dealLegendAlias } from '@/components/common/js/tools'
export default { export default {
name: 'topoTooltip', name: 'topoTooltip',
components: { components: {
@@ -73,7 +74,7 @@ export default {
data () { data () {
return { return {
tempDom: { height: 250, width: '' }, tempDom: { height: 250, width: '' },
chartDataTemp: { id: 8832, prev: null, next: null, panelId: 0, title: '123', span: 12, height: 0, createAt: '2021-01-27 07:36:19', unit: 2, weight: 0, pid: null, buildIn: null, seq: null, param: { last: 0, legendValue: { total: 'off', min: 'off', avg: 'off', last: 'off', max: 'off' }, threshold: '', url: '', nullType: 'connected' }, sync: null, asset: null, isLoaded: true, from: '__vue_devtool_undefined__', draggable: true, resizable: true, editable: true }, chartDataTemp: { id: 8832, prev: null, next: null, panelId: 0, title: '123', span: 12, height: 0, createAt: '2021-01-27 07:36:19', unit: 2, weight: 0, pid: null, buildIn: null, seq: null, param: { last: 0, legendValue: { total: 'off', min: 'off', avg: 'off', last: 'off', max: 'off' }, threshold: '', url: '', nullType: 'null' }, sync: null, asset: null, isLoaded: true, from: '__vue_devtool_undefined__', draggable: true, resizable: true, editable: true },
chartData: {}, chartData: {},
filter: { filter: {
end_time: bus.timeFormate(bus.getOffsetTimezoneData(), 'yyyy-MM-dd hh:mm:ss'), end_time: bus.timeFormate(bus.getOffsetTimezoneData(), 'yyyy-MM-dd hh:mm:ss'),
@@ -107,7 +108,7 @@ export default {
chartData.param = { chartData.param = {
legendValue: { total: 'off', min: 'off', avg: 'off', last: 'off', max: 'off' }, legendValue: { total: 'off', min: 'off', avg: 'off', last: 'off', max: 'off' },
last: 0, last: 0,
nullType: 'connected', nullType: 'null',
threshold: '', threshold: '',
url: '', url: '',
valueMapping: { mapping: [{ color: { bac: '#fff', text: '#000' }, text: '', value: '' }], type: 'text' }, valueMapping: { mapping: [{ color: { bac: '#fff', text: '#000' }, text: '', value: '' }], type: 'text' },
@@ -136,7 +137,7 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
const axiosArr = chartItem.elements.map((ele) => { const axiosArr = chartItem.elements.map((ele) => {
const filterItem = ele const filterItem = ele
let query = filterItem.expression let query = encodeURIComponent(filterItem.expression)
if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea' || chartInfo.type === 'table') && chartInfo.param) { // 如果是这三个 默认给null if ((chartInfo.type === 'line' || chartInfo.type === 'bar' || chartInfo.type === 'stackArea' || chartInfo.type === 'table') && chartInfo.param) { // 如果是这三个 默认给null
chartInfo.param.nullType = chartInfo.param.nullType || 'null' chartInfo.param.nullType = chartInfo.param.nullType || 'null'
query += '&nullType=' + chartInfo.param.nullType query += '&nullType=' + chartInfo.param.nullType
@@ -299,7 +300,7 @@ export default {
host = chartItem.elements[innerPos].expression host = chartItem.elements[innerPos].expression
} }
// 处理legend别名 // 处理legend别名
let alias = this.$refs['editChart' + chartItem.type].dealLegendAlias(host, chartItem.elements[innerPos].legend) let alias = dealLegendAlias(host, chartItem.elements[innerPos].legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="info-content pop-data-info-content"> <div class="info-content pop-data-info-content" v-if="showInfo">
<div class="info-box" v-loading="loading"> <div class="info-box" v-loading="loading">
<div class="info-box-title">Module info</div> <div class="info-box-title">Module info</div>
<div class="info-box-content"> <div class="info-box-content">
@@ -56,6 +56,7 @@ export default {
data () { data () {
return { return {
loading: true, loading: true,
showInfo: false,
moduleInfo: {} moduleInfo: {}
} }
}, },
@@ -65,7 +66,9 @@ export default {
this.loading = false this.loading = false
if (res.code === 200) { if (res.code === 200) {
this.moduleInfo = res.data this.moduleInfo = res.data
this.showInfo = true
} else { } else {
this.showInfo = false
this.$message.error(res.msg) this.$message.error(res.msg)
} }
}) })

View File

@@ -151,7 +151,7 @@
<popDataInfo :moduleId="moduleId" :projectId="projectInfo.id"></popDataInfo> <popDataInfo :moduleId="moduleId" :projectId="projectInfo.id"></popDataInfo>
</div> </div>
</div> </div>
<div :class="['page',fromOverView?'overview-page':'']" :style="{ <div :class="['page topo-page',fromOverView?'overview-page':'']" :style="{
border: fromOverView ? 'none' :`1px solid $--color-text-regular` border: fromOverView ? 'none' :`1px solid $--color-text-regular`
}"> }">
<!--画布部分--> <!--画布部分-->
@@ -174,7 +174,7 @@
<CanvasContextMenu :index="topologyIndexF" :props.sync="props"></CanvasContextMenu> <CanvasContextMenu :index="topologyIndexF" :props.sync="props"></CanvasContextMenu>
</div> </div>
<!--所有节点上的小图标--> <!--所有节点上的小图标-->
<div v-for="(item,index) in nodesArr" v-if="!editTopologyFlag&&item.data.iconToolState&&!fromPrev" <div v-for="(item,index) in nodesArr" v-if="!editTopologyFlag&&!fromPrev"
:key="index" :key="index"
v-show="(item.rect.y + offsetY - (48*(fromOverView?penToolTipScale:1)) > -10) && (item.rect.center.x + offsetX - (24*(fromOverView?penToolTipScale:1)) > - 10)" v-show="(item.rect.y + offsetY - (48*(fromOverView?penToolTipScale:1)) > -10) && (item.rect.center.x + offsetX - (24*(fromOverView?penToolTipScale:1)) > - 10)"
:style="{position: 'absolute',top:item.rect.y + offsetY - (48*(fromOverView?penToolTipScale:1))+'px',left:item.rect.center.x + offsetX - (24*(fromOverView?penToolTipScale:1)) +'px',transform:'scale('+(fromOverView?penToolTipScale:1)+')'}" :style="{position: 'absolute',top:item.rect.y + offsetY - (48*(fromOverView?penToolTipScale:1))+'px',left:item.rect.center.x + offsetX - (24*(fromOverView?penToolTipScale:1)) +'px',transform:'scale('+(fromOverView?penToolTipScale:1)+')'}"
@@ -362,7 +362,7 @@ import alertTable from './popData/alertTable'
import assetTable from './popData/assetTable' import assetTable from './popData/assetTable'
import endpointTable from './popData/endpointTable' import endpointTable from './popData/endpointTable'
import topoTooltip from './L5/topoTooltip' import topoTooltip from './L5/topoTooltip'
import { getMetricTypeValue } from '../js/tools' import { getMetricTypeValue, dealLegendAlias } from '../js/tools'
import bus from '../../../libs/bus' import bus from '../../../libs/bus'
// 注册到画布 // 注册到画布
registerNode('rectangleImg', myShape, myAnchors, myIconRect, myTextRect) registerNode('rectangleImg', myShape, myAnchors, myIconRect, myTextRect)
@@ -373,7 +373,7 @@ const canvasOptions = {
translateKey: 'None', translateKey: 'None',
disableEmptyLine: true, disableEmptyLine: true,
autoExpandDistance: 0, autoExpandDistance: 0,
minScale: 0.01, minScale: 0.2,
scaleKey: -1 scaleKey: -1
} }
export default { export default {
@@ -686,7 +686,8 @@ export default {
resolve({ data: '', status: 'no query' }) resolve({ data: '', status: 'no query' })
}) })
} }
query += '&nullType=' + 'connected' query = encodeURIComponent(query)
query += '&nullType=' + 'null'
return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step) return this.$get('/prom/api/v1/query_range?query=' + query + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step)
}) })
} }
@@ -694,6 +695,9 @@ export default {
promiseArr.push(pensPromise(item, arr, index)) promiseArr.push(pensPromise(item, arr, index))
}) })
Promise.all(promiseArr).then((res) => { Promise.all(promiseArr).then((res) => {
if (!getTopology(this.topologyIndex)) {
return
}
getTopology(this.topologyIndex).open(data) getTopology(this.topologyIndex).open(data)
getTopology(this.topologyIndex).lock(1) getTopology(this.topologyIndex).lock(1)
this.objChange = false this.objChange = false
@@ -718,7 +722,7 @@ export default {
getTopology(this.topologyIndex).centerView() getTopology(this.topologyIndex).centerView()
this.penToolTipScale = getTopology(this.topologyIndex).data.scale this.penToolTipScale = getTopology(this.topologyIndex).data.scale
setTimeout(() => { setTimeout(() => {
getTopology(this.topologyIndex).data.pens.forEach(item => { getTopology(this.topologyIndex) && getTopology(this.topologyIndex).data.pens.forEach(item => {
if (item.animatePlay) { if (item.animatePlay) {
item.stopAnimate() item.stopAnimate()
setTimeout(() => { setTimeout(() => {
@@ -767,7 +771,10 @@ export default {
}, },
// 打开topology数据 // 打开topology数据
openTopologyData (data) { openTopologyData (data) {
return new Promise(resolve => { return new Promise((resolve, reject) => {
if (!document.getElementById('topology-canvas' + this.topologyIndexF)) {
return
}
if (!getTopology(this.topologyIndex)) { if (!getTopology(this.topologyIndex)) {
const canvas = new Topology('topology-canvas' + this.topologyIndexF, canvasOptions) const canvas = new Topology('topology-canvas' + this.topologyIndexF, canvasOptions)
canvas.open(data) canvas.open(data)
@@ -1008,7 +1015,7 @@ export default {
host = pen.data.expressArr[innerPos] host = pen.data.expressArr[innerPos]
} }
// 处理legend别名 // 处理legend别名
let alias = this.dealLegendAlias(host, pen.data.legends[innerPos]) let alias = dealLegendAlias(host, pen.data.legends[innerPos])
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -1022,23 +1029,6 @@ export default {
} }
return res return res
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
// 获取project Info // 获取project Info
getProjectData (n) { getProjectData (n) {
// 获取projectInfo // 获取projectInfo
@@ -1099,7 +1089,7 @@ export default {
// 摘除已选择的module // 摘除已选择的module
modulesDiff (data) { modulesDiff (data) {
this.modules = this.allModules this.modules = this.allModules
if (getTopology(this.topologyIndex).data.pens) { if (getTopology(this.topologyIndex) && getTopology(this.topologyIndex).data.pens) {
getTopology(this.topologyIndex).data.pens.forEach(item => { getTopology(this.topologyIndex).data.pens.forEach(item => {
if (item.type == 0) { if (item.type == 0) {
this.modules = this.modules.filter(item1 => item.data.moduleId !== item1.id) this.modules = this.modules.filter(item1 => item.data.moduleId !== item1.id)
@@ -1441,7 +1431,8 @@ export default {
} }
break break
case 'resize': { case 'resize': {
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
if (getTopology(this.topologyIndex)) { if (getTopology(this.topologyIndex)) {
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
} }
@@ -1451,7 +1442,8 @@ export default {
if (this.$refs.topTool) { if (this.$refs.topTool) {
this.$refs.topTool.scaleNum = parseInt(data * 100) this.$refs.topTool.scaleNum = parseInt(data * 100)
} }
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
if (getTopology(this.topologyIndex)) { if (getTopology(this.topologyIndex)) {
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
} }
@@ -1911,7 +1903,8 @@ export default {
index: 0, index: 0,
list: [JSON.parse(JSON.stringify(getTopology(this.topologyIndex).data))] list: [JSON.parse(JSON.stringify(getTopology(this.topologyIndex).data))]
} }
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
}) })
}, },
@@ -2013,7 +2006,8 @@ export default {
this.$store.commit('setShowTopoScreen', this.topoScreenState) this.$store.commit('setShowTopoScreen', this.topoScreenState)
this.$nextTick(() => { this.$nextTick(() => {
getTopology(this.topologyIndex).lock(1) getTopology(this.topologyIndex).lock(1)
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
this.reload() this.reload()
}) })
@@ -2040,7 +2034,8 @@ export default {
this.editTopologyFlag = false this.editTopologyFlag = false
this.$nextTick(() => { this.$nextTick(() => {
getTopology(this.topologyIndex).lock(1) getTopology(this.topologyIndex).lock(1)
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
this.$store.commit('setShowTopoScreen', this.topoScreenState) this.$store.commit('setShowTopoScreen', this.topoScreenState)
}) })
@@ -2087,7 +2082,8 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
this.previewData = topologyData this.previewData = topologyData
getTopology(this.topologyIndex).lock(1) getTopology(this.topologyIndex).lock(1)
const domRect = document.getElementById('topology-canvas' + this.topologyIndexF).getBoundingClientRect() const dom = document.getElementById('topology-canvas' + this.topologyIndexF)
const domRect = dom ? dom.getBoundingClientRect() : {}
getTopology(this.topologyIndex).canvasPos = domRect getTopology(this.topologyIndex).canvasPos = domRect
this.initPens(topologyData) this.initPens(topologyData)
// this.reload() // this.reload()

View File

@@ -112,7 +112,7 @@
</el-form-item> </el-form-item>
<!--inr--> <!--inr-->
<el-form-item v-if="showSnmpTrap" :label="$t('alert.config.inr')" prop="inr" class="half-form-item"> <el-form-item v-if="showSnmpTrap" :label="$t('alert.config.inr')" prop="inr" class="half-form-item">
<el-input id="alert-box-input-inr" v-model.number="editAlertRule.inr" :placeholder="$t('alert.config.inrPlaceholder')" size="small" type="text" :disabled="!showSnmpTrap"></el-input> <el-input-number id="alert-box-input-inr" :controls="false" v-model="editAlertRule.inr" :placeholder="$t('alert.config.inrPlaceholder')" size="small" type="text" :disabled="!showSnmpTrap"></el-input-number>
</el-form-item> </el-form-item>
<!--last--> <!--last-->
<el-form-item v-if="showSnmpTrap" :label="$t('alert.config.for')" prop="last" class="half-form-item alert-box-duration" :rules=" [ <el-form-item v-if="showSnmpTrap" :label="$t('alert.config.for')" prop="last" class="half-form-item alert-box-duration" :rules=" [
@@ -372,7 +372,7 @@ export default {
} }
} }
const nzInr = (rule, value, callback) => { const nzInr = (rule, value, callback) => {
if (!this.showSnmpTrap) { if (!this.showSnmpTrap || (!value && isNaN(value))) {
callback() callback()
} }
if (value < 15) { if (value < 15) {

View File

@@ -614,6 +614,14 @@ export default {
selectType (type) { selectType (type) {
this.editAsset.type = { ...type } this.editAsset.type = { ...type }
this.editAsset.typeId = type.id ? type.id : '' this.editAsset.typeId = type.id ? type.id : ''
this.editAsset.authType = ''
this.editAsset.authUsername = ''
this.editAsset.authPin = ''
this.editAsset.authUserTip = ''
this.editAsset.authPinTip = ''
this.editAsset.snmpCredentialId = ''
this.editAsset.authProtocolPort = ''
this.editAsset.pid = ''
}, },
addLabel ([groupId, metaId]) { addLabel ([groupId, metaId]) {
const label = this.options.metaOptions.find(m => m.id === metaId) const label = this.options.metaOptions.find(m => m.id === metaId)
@@ -649,7 +657,9 @@ export default {
this.editAsset.brandId = parseInt(this.editAsset.brandAndModel[0]) this.editAsset.brandId = parseInt(this.editAsset.brandAndModel[0])
this.editAsset.modelId = parseInt(this.editAsset.brandAndModel[1]) this.editAsset.modelId = parseInt(this.editAsset.brandAndModel[1])
} }
if (this.editAsset.type.authProtocol !== assetConstants.authProtocolData.ssh) {
this.editAsset.authType = ''
}
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid) => {
if (valid) { if (valid) {
const params = JSON.parse(JSON.stringify(this.editAsset)) const params = JSON.parse(JSON.stringify(this.editAsset))

View File

@@ -160,7 +160,7 @@ export default {
groupData: [], groupData: [],
rules: { rules: {
name: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }], name: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }],
metaKey: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }, { pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: this.$t('validate.onlyWord'), trigger: 'change' }], metaKey: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }, { pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: this.$t('overall.ASCIIKey'), trigger: 'change' }],
groupId: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }], groupId: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }],
type: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }] type: [{ required: true, message: this.$t('validate.required'), trigger: 'change' }]
}, },

View File

@@ -200,8 +200,9 @@ export default {
data: function (row) { data: function (row) {
if (row.project && row.project.name.length > 15) { if (row.project && row.project.name.length > 15) {
return row.project.name.substring(0, 12) + '...' return row.project.name.substring(0, 12) + '...'
} else {
return row.project.name
} }
return ''
} }
}, },
{ {

View File

@@ -196,7 +196,7 @@
<el-tab-pane :label="$t('project.endpoint.parameter')" name="Parameter"> <el-tab-pane :label="$t('project.endpoint.parameter')" name="Parameter">
<div id="module-box-params" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;"> <div id="module-box-params" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;">
<div v-for="(item, index) in editEndpoint.paramObj" :key="index" class="param-box-row"> <div v-for="(item, index) in editEndpoint.paramObj" :key="index" class="param-box-row">
<el-form-item :prop="'paramObj.' + index + '.key'" class="param-box-row-key" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('validate.key') ,trigger: 'blur'}]"> <el-form-item :prop="'paramObj.' + index + '.key'" class="param-box-row-key" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]">
<el-input v-model="item.key" placeholder="key" size="mini" ></el-input> <el-input v-model="item.key" placeholder="key" size="mini" ></el-input>
</el-form-item> </el-form-item>
<span class="param-box-row-eq">=</span> <span class="param-box-row-eq">=</span>
@@ -221,7 +221,7 @@
<el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels"> <el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels">
<div id="module-box-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;"> <div id="module-box-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;">
<div v-for="(item, index) in editEndpoint.labelModule" :key="index" class="param-box-row"> <div v-for="(item, index) in editEndpoint.labelModule" :key="index" class="param-box-row">
<el-form-item :prop="'labelModule.' + index + '.key'" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('validate.key') ,trigger: 'blur'}]" class="param-box-row-key"> <el-form-item :prop="'labelModule.' + index + '.key'" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]" class="param-box-row-key">
<el-input v-model="item.key" placeholder="key" size="mini"></el-input> <el-input v-model="item.key" placeholder="key" size="mini"></el-input>
</el-form-item> </el-form-item>
<span class="param-box-row-eq">=</span> <span class="param-box-row-eq">=</span>
@@ -276,7 +276,7 @@
class="half-form-item" :label="'Target label'" class="half-form-item" :label="'Target label'"
:rules="[ :rules="[
{ required: item.action === 'replace', message: $t('validate.required'), trigger: 'blur' }, { required: item.action === 'replace', message: $t('validate.required'), trigger: 'blur' },
{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('validate.key') ,trigger: 'blur'}]" { pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]"
> >
<el-input id="module-box-input-target_label" v-model="item.target_label" placeholder='' size="small"></el-input> <el-input id="module-box-input-target_label" v-model="item.target_label" placeholder='' size="small"></el-input>
</el-form-item> </el-form-item>
@@ -396,7 +396,7 @@
<el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels"> <el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels">
<div id="module-box-logs-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;"> <div id="module-box-logs-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;">
<div v-for="(item1, i) in item.labelModule" :key="i" class="param-box-row"> <div v-for="(item1, i) in item.labelModule" :key="i" class="param-box-row">
<el-form-item :prop="'configs.1.config.'+ index +'.labelModule.' + i + '.key'" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('validate.key') ,trigger: 'blur'}]" class="param-box-row-key"> <el-form-item :prop="'configs.1.config.'+ index +'.labelModule.' + i + '.key'" :rules="[{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]" class="param-box-row-key">
<el-input v-model="item1.key" placeholder="key" size="mini" @input="$forceUpdate()"></el-input> <el-input v-model="item1.key" placeholder="key" size="mini" @input="$forceUpdate()"></el-input>
</el-form-item> </el-form-item>
<span class="param-box-row-eq">=</span> <span class="param-box-row-eq">=</span>
@@ -442,7 +442,7 @@
<div v-for="(expressions, eindex) in item2.expressions" :key="eindex" style="display: flex;justify-content: space-around;align-items: center;margin-bottom: 16px"> <div v-for="(expressions, eindex) in item2.expressions" :key="eindex" style="display: flex;justify-content: space-around;align-items: center;margin-bottom: 16px">
<el-form-item <el-form-item
:prop="'configs.1.config.'+ index +'.pipeline.' + index2 + '.expressions.'+eindex+'.key'" :prop="'configs.1.config.'+ index +'.pipeline.' + index2 + '.expressions.'+eindex+'.key'"
:rules="[{ required: true, message: $t('validate.required'), trigger: 'blur' },{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('validate.key') ,trigger: 'blur'}]" :rules="[{ required: true, message: $t('validate.required'), trigger: 'blur' },{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]"
style="width: 45%;margin: 0" style="width: 45%;margin: 0"
> >
<el-input v-model="item2.expressions[eindex].key" placeholder="key" size="mini" ></el-input> <el-input v-model="item2.expressions[eindex].key" placeholder="key" size="mini" ></el-input>
@@ -506,7 +506,7 @@
<div v-for="(expressions, eindex) in item2.labels" :key="eindex" style="display: flex;justify-content: space-around;align-items: center;margin-bottom: 16px"> <div v-for="(expressions, eindex) in item2.labels" :key="eindex" style="display: flex;justify-content: space-around;align-items: center;margin-bottom: 16px">
<el-form-item <el-form-item
:prop="'configs.1.config.'+ index +'.pipeline.' + index2 + '.labels.'+eindex+'.key'" :prop="'configs.1.config.'+ index +'.pipeline.' + index2 + '.labels.'+eindex+'.key'"
:rules="[{ required: true, message: $t('validate.required'), trigger: 'blur' },{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('validate.key') ,trigger: 'blur'}]" :rules="[{ required: true, message: $t('validate.required'), trigger: 'blur' },{ pattern: /[a-zA-Z_][a-zA-Z0-9_]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]"
style="width: 45%;margin: 0" style="width: 45%;margin: 0"
> >
<el-input v-model="item2.labels[eindex].key" placeholder="key" size="mini" ></el-input> <el-input v-model="item2.labels[eindex].key" placeholder="key" size="mini" ></el-input>

View File

@@ -202,7 +202,7 @@
<el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels"> <el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels">
<div id="module-box-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;"> <div id="module-box-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;">
<div v-for="(item, index) in editModule.labelModule" :key="index" class="param-box-row"> <div v-for="(item, index) in editModule.labelModule" :key="index" class="param-box-row">
<el-form-item :prop="'labelModule.' + index + '.key'" :rules="[{ pattern: /[a-zA-Z_:][a-zA-Z0-9_:]*/, message: $t('validate.key') ,trigger: 'blur'}]" class="param-box-row-key"> <el-form-item :prop="'labelModule.' + index + '.key'" :rules="[{ pattern: /[a-zA-Z_:][a-zA-Z0-9_:]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]" class="param-box-row-key">
<el-input v-model="item.key" placeholder="key" size="mini"></el-input> <el-input v-model="item.key" placeholder="key" size="mini"></el-input>
</el-form-item> </el-form-item>
<span class="param-box-row-eq">=</span> <span class="param-box-row-eq">=</span>
@@ -257,7 +257,7 @@
class="half-form-item" :label="'Target label'" class="half-form-item" :label="'Target label'"
:rules="[ :rules="[
{ required: item.action === 'replace', message: $t('validate.required'), trigger: 'blur' }, { required: item.action === 'replace', message: $t('validate.required'), trigger: 'blur' },
{ pattern: /[a-zA-Z_:][a-zA-Z0-9_:]*/, message: $t('validate.key') ,trigger: 'blur'}]" { pattern: /[a-zA-Z_:][a-zA-Z0-9_:]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]"
> >
<el-input id="module-box-input-target_label" v-model="item.target_label" placeholder='' size="small"></el-input> <el-input id="module-box-input-target_label" v-model="item.target_label" placeholder='' size="small"></el-input>
</el-form-item> </el-form-item>
@@ -376,7 +376,7 @@
<el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels"> <el-tab-pane :label="$t('project.endpoint.labels2')" name="Labels">
<div id="module-box-logs-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;"> <div id="module-box-logs-labels" ref="labelBoxScrollbar" style="height: 100%; overflow: auto;">
<div v-for="(item1, i) in item.labelModule" :key="i" class="param-box-row"> <div v-for="(item1, i) in item.labelModule" :key="i" class="param-box-row">
<el-form-item :prop="'configs.1.config.'+ index +'.labelModule.' + i + '.key'" :rules="[{ pattern: /[a-zA-Z_:][a-zA-Z0-9_:]*/, message: $t('validate.key') ,trigger: 'blur'}]" class="param-box-row-key"> <el-form-item :prop="'configs.1.config.'+ index +'.labelModule.' + i + '.key'" :rules="[{ pattern: /[a-zA-Z_:][a-zA-Z0-9_:]*/, message: $t('overall.ASCIIKey') ,trigger: 'blur'}]" class="param-box-row-key">
<el-input v-model="item1.key" placeholder="key" size="mini"></el-input> <el-input v-model="item1.key" placeholder="key" size="mini"></el-input>
</el-form-item> </el-form-item>
<span class="param-box-row-eq">=</span> <span class="param-box-row-eq">=</span>

View File

@@ -32,7 +32,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item :label='$t("config.menus.value")' prop="value"> <el-form-item :label='$t("config.menus.value")' prop="value">
<el-input placeholder="" maxlength="256" show-word-limit v-model="editGlobalization.value" size="small" id="dc-box-input-value"></el-input> <el-input placeholder="" maxlength="128" show-word-limit v-model="editGlobalization.value" size="small" id="dc-box-input-value"></el-input>
</el-form-item> </el-form-item>
<!-- <el-form-item :label='$t("i18n.remark")' prop="remark">--> <!-- <el-form-item :label='$t("i18n.remark")' prop="remark">-->
<!-- <el-input placeholder="" maxlength="64" show-word-limit v-model="editGlobalization.value" size="small" id="dc-box-input-value"></el-input>--> <!-- <el-input placeholder="" maxlength="64" show-word-limit v-model="editGlobalization.value" size="small" id="dc-box-input-value"></el-input>-->

View File

@@ -8,7 +8,7 @@
<span class="param-box-row-eq">=</span> <span class="param-box-row-eq">=</span>
<el-input placeholder="value" class="param-box-row-value input-x-mini-22" v-model="item.value"></el-input> <el-input placeholder="value" class="param-box-row-value input-x-mini-22" v-model="item.value"></el-input>
<span class="param-box-row-symbol" :id="'remove-param-'+index" @click="removeTags(index)"><i class="nz-icon nz-icon-shanchu1"></i></span> <span class="param-box-row-symbol" :id="'remove-param-'+index" @click="removeTags(index)"><i class="nz-icon nz-icon-shanchu1"></i></span>
<span style="color: #F56C6C;font-size: 12px;" v-if="inputKeyErr[index]">{{$t('validate.key')}}</span> <span style="color: #F56C6C;font-size: 12px;" v-if="inputKeyErr[index]">{{$t('overall.ASCIIKey')}}</span>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -39,7 +39,7 @@
<i class="nz-icon nz-icon-close" style="cursor: pointer" @click="close_selcet_list(ind,$event)"></i> <i class="nz-icon nz-icon-close" style="cursor: pointer" @click="close_selcet_list(ind,$event)"></i>
</div> </div>
<div v-else-if="!change_sreach_show && ind==sreach_num && val.id!==7 " class="select_input"> <div v-else-if="!change_sreach_show && ind==sreach_num && val.id!==7 " class="select_input">
<input type="text" autocomplete="off" id="sreach_input" v-model="input_sreach" :readonly="val.readonly" @keyup="enter(val, $event)" @click="stop_click"> <input type="text" autocomplete="off" id="sreach_input" v-model="input_sreach" :readonly="val.readonly" @keydown="enter(val, $event)" @click="stop_click">
<div class="select_info_list" :style="'top:' + selectDom.top +'; left:'+selectDom.left " v-if="val.type == 'select'"> <div class="select_info_list" :style="'top:' + selectDom.top +'; left:'+selectDom.left " v-if="val.type == 'select'">
<el-scrollbar v-if="selectInfoList[val.label].length > 8" class="el-scrollbar-small" style="height: 240px;"> <el-scrollbar v-if="selectInfoList[val.label].length > 8" class="el-scrollbar-small" style="height: 240px;">
<ul> <ul>
@@ -227,7 +227,7 @@
</li> </li>
<!-- 最开始的input框--> <!-- 最开始的input框-->
<li class="select_input" v-if="change_sreach_show"> <li class="select_input" v-if="change_sreach_show">
<input type="text" @click="read_input" v-model="no_condition" @keyup="enter_one" id="one-input" @keydown="clear_search_list" :placeholder="placeholder"> <input type="text" @click="read_input" v-model="no_condition" @keyup="enter_one" :id="'one-input' + position" @keydown="clear_search_list" :placeholder="placeholder">
</li> </li>
</ul> </ul>
</el-scrollbar> </el-scrollbar>
@@ -456,7 +456,10 @@ export default {
defaultItem: {}, defaultItem: {},
defaultValue: {}, defaultValue: {},
inTransform: {}, inTransform: {},
position: {}, position: {
type: String,
default: ''
},
single: {}, single: {},
showHistory: { showHistory: {
type: Boolean, type: Boolean,
@@ -528,7 +531,9 @@ export default {
this.change_sreach_show = true this.change_sreach_show = true
this.input_list = false this.input_list = false
const _this = this const _this = this
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
setTimeout(function () { setTimeout(function () {
_this.getHeight() _this.getHeight()
}) })
@@ -700,7 +705,9 @@ export default {
this.change_sreach_show = true this.change_sreach_show = true
this.input_list = false this.input_list = false
const _this = this const _this = this
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
setTimeout(function () { setTimeout(function () {
_this.getHeight() _this.getHeight()
}) })
@@ -719,7 +726,9 @@ export default {
this.change_sreach_show = true this.change_sreach_show = true
this.input_list = false this.input_list = false
const _this = this const _this = this
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
setTimeout(function () { setTimeout(function () {
_this.getHeight() _this.getHeight()
}) })
@@ -954,7 +963,7 @@ export default {
this.sreach_num = this.select_list.length this.sreach_num = this.select_list.length
this.select_list.forEach(val => { this.select_list.forEach(val => {
this.searchLabelList.forEach((item, index) => { this.searchLabelList.forEach((item, index) => {
if (val.id == item.id) { if (val.label == item.label) {
this.searchLabelList.splice(index, 1) this.searchLabelList.splice(index, 1)
} }
}) })
@@ -1053,6 +1062,7 @@ export default {
}, },
// input框监听是按删除还是回车 // input框监听是按删除还是回车
enter (val, e) { enter (val, e) {
console.log(val, e)
const keyCode = window.event ? e.keyCode : e.which const keyCode = window.event ? e.keyCode : e.which
if (val == 'ID' && keyCode == 13) { if (val == 'ID' && keyCode == 13) {
const id = /^[0-9]*$/ const id = /^[0-9]*$/
@@ -1078,14 +1088,19 @@ export default {
}) })
this.select_list.splice(this.sreach_num, 1) this.select_list.splice(this.sreach_num, 1)
this.change_sreach_show = true this.change_sreach_show = true
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
this.input_list = false this.input_list = false
this.delBool = false this.delBool = false
} else if (this.searchMsg.searchLabelList.find(key => this.select_list[this.sreach_num].label == key.label).readonly) {
this.input_sreach = ''
} }
} }
} else { } else {
console.log(this.searchMsg.searchLabelList.find(key => this.select_list[this.sreach_num].label == key.label))
if (keyCode == 8) { if (keyCode == 8) {
if (this.delcriteriaBool) { if (this.delcriteriaBool || !this.input_sreach) {
this.searchMsg.searchLabelList.forEach((val, k) => { this.searchMsg.searchLabelList.forEach((val, k) => {
if (this.select_list[this.sreach_num].label == val.label) { if (this.select_list[this.sreach_num].label == val.label) {
this.searchLabelList.splice(k + 1, 0, val) this.searchLabelList.splice(k + 1, 0, val)
@@ -1094,9 +1109,13 @@ export default {
}) })
this.select_list.splice(this.sreach_num, 1) this.select_list.splice(this.sreach_num, 1)
this.change_sreach_show = true this.change_sreach_show = true
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
this.input_list = false this.input_list = false
this.delcriteriaBool = false this.delcriteriaBool = false
} else if (this.searchMsg.searchLabelList.find(key => this.select_list[this.sreach_num].label == key.label).readonly) {
this.input_sreach = ''
} else { } else {
if (this.input_sreach == '') { if (this.input_sreach == '') {
this.delcriteriaBool = true this.delcriteriaBool = true
@@ -1109,7 +1128,9 @@ export default {
if (this.select_list[this.sreach_num].type !== 'select') { if (this.select_list[this.sreach_num].type !== 'select') {
if (this.input_sreach !== '') { if (this.input_sreach !== '') {
this.zhezhao_click() this.zhezhao_click()
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
this.input_list = false this.input_list = false
} }
} else { } else {
@@ -1164,7 +1185,7 @@ export default {
this.input_list = true this.input_list = true
this.change_sreach_show = false this.change_sreach_show = false
this.sreach_num = ind this.sreach_num = ind
this.input_sreach = this.select_list[ind].val this.input_sreach = this.select_list[ind].val ? this.select_list[ind].val : ''
if (this.select_list[ind].type == 'input') { if (this.select_list[ind].type == 'input') {
this.downBool = true this.downBool = true
} else { } else {
@@ -1299,7 +1320,9 @@ export default {
this.no_condition = '' this.no_condition = ''
this.sreach_num = this.select_list.length this.sreach_num = this.select_list.length
} }
setTimeout('document.getElementById("one-input").focus()', 500) setTimeout(() => {
document.getElementById('one-input' + this.position).focus()
}, 500)
this.input_list = !this.input_list this.input_list = !this.input_list
const _this = this const _this = this
setTimeout(function () { setTimeout(function () {

View File

@@ -240,12 +240,12 @@ const searchSelectInfo = { // value: 传给后台的值label显示给用
searchMetrics: [ searchMetrics: [
{ {
id: 1, id: 1,
name: i18n.t('project.metrics.metrics'), name: 'Metrics',
searchType: 'alertTypes' searchType: 'alertTypes'
}, },
{ {
id: 2, id: 2,
name: i18n.t('overall.logs'), name: 'Logs',
searchType: 'alertTypes' searchType: 'alertTypes'
}, },
{ {

View File

@@ -10,7 +10,7 @@
@header-dragend="dragend" @header-dragend="dragend"
@sort-change="tableDataSort" @sort-change="tableDataSort"
@selection-change="selectionChange" @selection-change="selectionChange"
@row-dblclick="(row)=>{$emit('messageDetail', row)}" @row-dblclick="(row)=>{rowDblclick(row)}"
> >
<el-table-column <el-table-column
:resizable="false" :resizable="false"
@@ -42,7 +42,7 @@
@hide="alertMessageHover(scope.row.alertRule, false)" @hide="alertMessageHover(scope.row.alertRule, false)"
trigger="hover"> trigger="hover">
<alertRuleInfo v-if="scope.row.alertRule.loading" :id="scope.row.alertRule.id" :severity-data="severityData" :that="scope.row.alertRule" @showText="$emit('showText',scope.row)"></alertRuleInfo> <alertRuleInfo v-if="scope.row.alertRule.loading" :id="scope.row.alertRule.id" :severity-data="severityData" :that="scope.row.alertRule" @showText="$emit('showText',scope.row)"></alertRuleInfo>
<span slot="reference" class="data-column__span">{{scope.row.alertRule?scope.row.alertRule.name : '--'}}</span> <span slot="reference">{{scope.row.alertRule?scope.row.alertRule.name : '--'}}</span>
</el-popover> </el-popover>
</div> </div>
<template v-else>-</template> <template v-else>-</template>
@@ -110,7 +110,7 @@
fixed="right"> fixed="right">
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div> <div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
<div slot-scope="scope" class="table-operation-items"> <div slot-scope="scope" class="table-operation-items">
<button v-if="scope.row.alertRule&&scope.row.alertRule.type !== 3" class="table-operation-item" @click="$emit('messageDetail', scope.row)" :disabled="scope.row.alertRule.type !== 1" :class="{'table-operation-item--disable': scope.row.alertRule.type !== 1}"><i class="nz-icon nz-icon-view1"></i></button> <button v-if="scope.row.alertRule&&scope.row.alertRule.type !== 3" class="table-operation-item" @click="$emit('messageDetail', scope.row)"><i class="nz-icon nz-icon-view1"></i></button>
<el-dropdown v-has="['alertMessage_expired', 'alertSilence_add']" size="medium" trigger="click" @command="tableOperation"> <el-dropdown v-has="['alertMessage_expired', 'alertSilence_add']" size="medium" trigger="click" @command="tableOperation">
<div class="table-operation-item table-operation-item--more"> <div class="table-operation-item table-operation-item--more">
<i class="nz-icon nz-icon-more3"></i> <i class="nz-icon nz-icon-more3"></i>
@@ -585,6 +585,12 @@ export default {
// Severity Label // Severity Label
returnSeverityLabel (key) { returnSeverityLabel (key) {
return this.$t(this.$CONSTANTS.alertMessage.severityData.find(s => { return s.value == key }).label) return this.$t(this.$CONSTANTS.alertMessage.severityData.find(s => { return s.value == key }).label)
},
rowDblclick (row) {
if (!this.showOption) {
return
}
this.$emit('messageDetail', row)
} }
} }
} }

View File

@@ -85,14 +85,20 @@
<template v-else-if="item.prop === 'clientState'"> <template v-else-if="item.prop === 'clientState'">
<div v-if="scope.row[item.prop]===1"> <div v-if="scope.row[item.prop]===1">
<div class="active-icon green-bg inline-block"></div> <div class="active-icon green-bg inline-block"></div>
{{ $t('overall.normal') }} OK
</div> </div>
<div v-else-if="scope.row[item.prop]===0"> <div v-else-if="scope.row[item.prop]===0">
<div class="active-icon red-bg inline-block"></div> {{ $t('overall.unusual') }} <div class="active-icon gray-bg inline-block"></div> {{ $t('config.user.disable') }}
</div> </div>
<div v-else-if="scope.row[item.prop]===-1"> <div v-else-if="scope.row[item.prop]===2">
<div class="active-icon red-bg inline-block"></div> {{ $t('asset.connectionTimedOut') }}
</div>
<div v-else-if="scope.row[item.prop]===3">
<div class="active-icon red-bg inline-block"></div> {{ $t('overall.AuthenticationFailed') }} <div class="active-icon red-bg inline-block"></div> {{ $t('overall.AuthenticationFailed') }}
</div> </div>
<div v-else-if="scope.row[item.prop]===4">
<div class="active-icon red-bg inline-block"></div> {{ $t('config.terminallog.statusItem.unknownError') }}
</div>
<template v-else>-</template> <template v-else>-</template>
</template> </template>
<template v-else-if="item.prop === 'brand'">{{scope.row.brand ? scope.row.brand.name : '-'}}</template> <template v-else-if="item.prop === 'brand'">{{scope.row.brand ? scope.row.brand.name : '-'}}</template>

View File

@@ -11,7 +11,7 @@
</div> </div>
<div :class="{'top-tool-main-right-to-left': bottomBox.showSubList}" class="top-tool-right"> <div :class="{'top-tool-main-right-to-left': bottomBox.showSubList}" class="top-tool-right">
<div v-if="showLayout.indexOf('searchInput') > -1" class="top-tool-search margin-r-20" :class="{'project-search alert-table asset-table endpoint-table': searchRight}"> <div v-if="showLayout.indexOf('searchInput') > -1" class="top-tool-search margin-r-20" :class="{'project-search alert-table asset-table endpoint-table': searchRight}">
<search-input ref="searchInput" :from="from" :inTransform="bottomBox.inTransform" :searchMsg="searchMsg" @search="search"></search-input> <search-input ref="searchInput" :from="from" :position='from' :inTransform="bottomBox.inTransform" :searchMsg="searchMsg" @search="search"></search-input>
</div> </div>
<slot name="top-tool-right"></slot> <slot name="top-tool-right"></slot>
<button v-if="showLayout.indexOf('elementSet') > -1" class="top-tool-btn table-column-setting" <button v-if="showLayout.indexOf('elementSet') > -1" class="top-tool-btn table-column-setting"

View File

@@ -263,8 +263,7 @@ export default {
label: this.$t('project.endpoint.state'), label: this.$t('project.endpoint.state'),
prop: 'state', prop: 'state',
show: true, show: true,
minWidth: 200, minWidth: 200
sortable: 'custom'
} }
// { // {
// label: this.$t('project.endpoint.status'), // label: this.$t('project.endpoint.status'),

View File

@@ -168,7 +168,7 @@ export default {
this.tableData = [] this.tableData = []
this.tableDataCopy = '' this.tableDataCopy = ''
setTimeout(() => { setTimeout(() => {
this.$get("/prom/api/v1/query?query={endpoint_id='" + this.currentEndpoint.id + "'}&time=" + this.$stringTimeParseToUnix(new Date(this.formatTime).getTime())).then(response => { this.$get('/prom/api/v1/query?query=' + encodeURIComponent("{endpoint_id='" + this.currentEndpoint.id + "'}") + '&time=' + this.$stringTimeParseToUnix(new Date(this.formatTime).getTime())).then(response => {
this.loading = false this.loading = false
if (response.status === 'success') { if (response.status === 'success') {
const results = response.data.result const results = response.data.result
@@ -378,13 +378,13 @@ export default {
} }
const axiosArr = [] const axiosArr = []
for (const endpoint of this.batchDeleteObjs) { for (const endpoint of this.batchDeleteObjs) {
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + endpoint.element + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(endpoint.element) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step))
} }
if (this.$refs.pickTime && this.$refs.pickTime.$refs.multipleTime && this.$refs.pickTime.$refs.multipleTime.searchTime.length) { // 判断是否需要添加比较 if (this.$refs.pickTime && this.$refs.pickTime.$refs.multipleTime && this.$refs.pickTime.$refs.multipleTime.searchTime.length) { // 判断是否需要添加比较
const startTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[0], 'yyyy-MM-dd hh:mm:ss') const startTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
const endTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[1], 'yyyy-MM-dd hh:mm:ss') const endTime = bus.timeFormate(this.$refs.pickTime.$refs.multipleTime.searchTime[1], 'yyyy-MM-dd hh:mm:ss')
for (const endpoint of this.batchDeleteObjs) { for (const endpoint of this.batchDeleteObjs) {
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + endpoint.element + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(endpoint.element) + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step))
} }
} }
this.legend = [] this.legend = []

View File

@@ -15,7 +15,7 @@ export default {
'sp-select': () => import('v-selectpage/src/components/Select'), 'sp-select': () => import('v-selectpage/src/components/Select'),
'sp-page': () => import('./Pagination'), 'sp-page': () => import('./Pagination'),
'sp-list': () => import('v-selectpage/src/components/List'), 'sp-list': () => import('v-selectpage/src/components/List'),
'sp-table': () => import('v-selectpage/src/components/Table') 'sp-table': () => import('./Table')
}, },
provide () { provide () {
return { return {

View File

@@ -0,0 +1,52 @@
import view from 'v-selectpage/src/mixins/view'
export default {
name: 'SelectPageTable',
mixins: [view],
props: {
tbColumns: Array
},
render (h) {
return h('table', { class: 'sp-table' }, [
// table thead
h('thead', [h('tr', {
class: { 'sp-rtl': this.rtl }
}, this.tbColumns.map(val => h('th', val.title)))]),
// table tbody
h('tbody', {
on: {
mouseleave: () => this.highlight(-1)
}
}, this.list.map((val, index) => {
// table row
return h('tr', {
key: index,
class: this.rowClass(val, index),
on: {
click: e => {
e.stopPropagation()
this.rowClick(val)
},
mouseenter: () => this.highlight(this.inPicked(val) ? -1 : index)
}
}, this.tbColumns.map((col, idx) => { // table cells
return h('td', {
key: idx,
domProps: {
innerHTML: this.renderColumn(val, col),
title: val[col.title]
}
})
}))
}))
])
},
methods: {
renderColumn (row, col) {
if (!row || !Object.keys(row).length || !col || !col.data) return ''
switch (typeof col.data) {
case 'string': return row[col.data]
case 'function': return col.data(row)
}
}
}
}

View File

@@ -4,7 +4,7 @@ const RIGHT = 39
const DOWN = 40 const DOWN = 40
const TAB = 9 const TAB = 9
const ENTER = 13 const ENTER = 13
const ESCAPE = 27 const encodeURIComponent = 27
export default { export default {
methods: { methods: {
@@ -82,10 +82,10 @@ export default {
} }
}, },
processKey (e) { processKey (e) {
if (![LEFT, UP, RIGHT, DOWN, ESCAPE, ENTER, TAB].includes(e.keyCode)) this.populate() if (![LEFT, UP, RIGHT, DOWN, encodeURIComponent, ENTER, TAB].includes(e.keyCode)) this.populate()
}, },
processControl (e) { processControl (e) {
if ([LEFT, UP, RIGHT, DOWN, ESCAPE, ENTER, TAB].includes(e.keyCode)) { if ([LEFT, UP, RIGHT, DOWN, encodeURIComponent, ENTER, TAB].includes(e.keyCode)) {
switch (e.keyCode) { switch (e.keyCode) {
case LEFT: case LEFT:
if (this.pagination) this.$refs.page.switchPage('previous') if (this.pagination) this.$refs.page.switchPage('previous')
@@ -103,7 +103,7 @@ export default {
case ENTER: case ENTER:
if (this.highlight !== -1) this.selectItem(this.list[this.highlight]) if (this.highlight !== -1) this.selectItem(this.list[this.highlight])
break break
case ESCAPE: case encodeURIComponent:
this.close() this.close()
break break
} }

View File

@@ -74,7 +74,7 @@ export default {
}, },
data () { data () {
return { return {
username: sessionStorage.getItem('nz-username'), username: localStorage.getItem('nz-username'),
name: localStorage.getItem('nz-user-name'), name: localStorage.getItem('nz-user-name'),
language: localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en', language: localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en',
// 顶部菜单相关 // 顶部菜单相关
@@ -168,7 +168,7 @@ export default {
initEvent () { initEvent () {
bus.$on('login', () => { bus.$on('login', () => {
this.username = sessionStorage.getItem('nz-username') this.username = localStorage.getItem('nz-username')
// this.refreshLang() // this.refreshLang()
}) })
if (window.history && window.history.pushState) { if (window.history && window.history.pushState) {
@@ -181,14 +181,20 @@ export default {
}, },
shrink () { shrink () {
this.$store.commit('isShrink') this.$store.commit('isShrink')
},
testUser () {
if (this.username != localStorage.getItem('nz-username')) {
window.location.reload()
}
} }
}, },
mounted () { mounted () {
this.$i18n.locale = this.language this.$i18n.locale = this.language
if (sessionStorage.getItem('nz-token')) { if (localStorage.getItem('nz-token')) {
this.initEvent() this.initEvent()
this.getLinkData() this.getLinkData()
} }
window.addEventListener('visibilitychange', this.testUser)
}, },
computed: { computed: {
linkData () { linkData () {

View File

@@ -109,6 +109,18 @@
class="line-chart-block-modal nz-dialog endpoint-dialog" class="line-chart-block-modal nz-dialog endpoint-dialog"
width="90%" width="90%"
@close="dialogClose"> @close="dialogClose">
<el-popover
v-if="isError"
placement="top-start"
:close-delay=10
trigger="hover"
popper-class="chart-error-popper">
<div >{{errorContent}}</div>
<span slot="reference" class="panel-info-corner panel-info-corner--error">
<i class="nz-icon nz-icon-warning fa-model" ></i>
<span class="panel-info-corner-inner"></span>
</span>
</el-popover>
<div slot="title"> <div slot="title">
{{$t("project.endpoint.dialogTitle")}} {{$t("project.endpoint.dialogTitle")}}
<div class="float-right panel-calendar dialog-tool" style="display: flex"> <div class="float-right panel-calendar dialog-tool" style="display: flex">
@@ -176,7 +188,7 @@ export default {
dialogText: '', dialogText: '',
url: 'alert/message', url: 'alert/message',
// 导出相关 // 导出相关
importBox: { show: false, title: this.$t('overall.importExcel'), type: 1, record: 'all', format: 1 }, importBox: { show: false, title: this.$t('overall.exportExcel'), type: 1, record: 'all', format: 1 },
deleteBox: { show: false, ids: '', remark: '', state: 2 }, deleteBox: { show: false, ids: '', remark: '', state: 2 },
// 详情相关 // 详情相关
graphShow: false, graphShow: false,
@@ -347,7 +359,9 @@ export default {
{ name: 'XLSX', value: 1 }, { name: 'XLSX', value: 1 },
{ name: 'CSV', value: 2 }, { name: 'CSV', value: 2 },
{ name: 'JSON', value: 3 } { name: 'JSON', value: 3 }
] ],
errorContent: '',
isError: false
} }
}, },
computed: { computed: {
@@ -445,16 +459,13 @@ export default {
}) })
}, },
messageDetail (row) { messageDetail (row) {
console.log(row)
if (row.alertRule.type == 3) { if (row.alertRule.type == 3) {
return return
} }
this.$get('/alert/rule/' + row.alertRule.id).then(res => { this.$get('/alert/rule/' + row.alertRule.id).then(res => {
this.currentMsg = { ...row, alertRule: { ...res.data } } this.currentMsg = { ...row, alertRule: { ...res.data } }
if (row.alertRule.type !== 1) { this.graphShow = true
this.graphShow = false
} else {
this.graphShow = true
}
this.$nextTick(() => { this.$nextTick(() => {
this.searchTimeDialog = [bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000), bus.computeTimezoneTime(new Date().getTime())] this.searchTimeDialog = [bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000), bus.computeTimezoneTime(new Date().getTime())]
this.queryDate() this.queryDate()
@@ -475,7 +486,7 @@ export default {
this.queryChartDate() this.queryChartDate()
}) })
} else if (this.currentMsg.alertRule.type === 2) { } else if (this.currentMsg.alertRule.type === 2) {
this.queryLogData(1000) this.queryLogData(100)
} }
}, },
queryChartDate () { queryChartDate () {
@@ -497,8 +508,7 @@ export default {
if (this.$refs.messageChart) { if (this.$refs.messageChart) {
this.$refs.messageChart.startLoading() this.$refs.messageChart.startLoading()
const axiosArr = [] const axiosArr = []
const paramStr = JSON.stringify(this.promQueryParamConvert(this.currentMsg)) axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + encodeURIComponent(this.currentMsg.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '')) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step + '&filter=' + encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))))
axiosArr.push(axios.get('/prom/api/v1/query_range?query=' + paramStr.substring(1, paramStr.length - 1) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&step=' + step))
this.legend = [] this.legend = []
this.chartDatas = [] this.chartDatas = []
axios.all(axiosArr).then(res => { axios.all(axiosArr).then(res => {
@@ -571,6 +581,17 @@ export default {
} else { } else {
this.$message.error(response.data.error) this.$message.error(response.data.error)
} }
} else {
this.$refs.messageChart.endLoading()
this.chartLoading = false
this.isError = true
if (response.msg) {
this.errorContent = response.msg
} else if (response.error) {
this.errorContent = response.error
} else {
this.errorContent = response
}
} }
}) })
this.$nextTick(() => { this.$nextTick(() => {
@@ -630,12 +651,12 @@ export default {
}, },
queryLogData (limit) { // log的chart和table是一个请求 queryLogData (limit) { // log的chart和table是一个请求
if (!limit) { if (!limit) {
limit = 1000 limit = 100
} }
const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000) const start = this.searchTimeDialog[0] ? this.searchTimeDialog[0] : bus.computeTimezoneTime(new Date().getTime() - 1 * 60 * 60 * 1000)
const end = this.searchTimeDialog[1] ? this.searchTimeDialog[1] : bus.computeTimezoneTime(new Date().getTime()) const end = this.searchTimeDialog[1] ? this.searchTimeDialog[1] : bus.computeTimezoneTime(new Date().getTime())
this.expressions = [this.currentMsg.alertRule.expr] this.expressions = [this.currentMsg.alertRule.expr]
this.$get('/logs/loki/api/v1/query_range?format=1&query=' + this.currentMsg.alertRule.expr + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit).then(res => { this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(this.currentMsg.alertRule.expr) + '&start=' + this.$stringTimeParseToUnix(start) + '&end=' + this.$stringTimeParseToUnix(end) + '&limit=' + limit + '&filter=' + encodeURIComponent(decodeURIComponent(this.promQueryParamLabels(this.currentMsg.labels)))).then(res => {
this.chartLoading = false this.chartLoading = false
const logData = [res.data] const logData = [res.data]
this.resultType = res.data.resultType this.resultType = res.data.resultType
@@ -855,6 +876,7 @@ export default {
this.getTableData() this.getTableData()
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = '' this.timer = ''
this.scrollbarToTop()
}, 1000) }, 1000)
} else { } else {
clearTimeout(this.timer) clearTimeout(this.timer)
@@ -862,12 +884,24 @@ export default {
this.getTableData() this.getTableData()
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = '' this.timer = ''
this.scrollbarToTop()
}, 1000) }, 1000)
} }
}, },
scrollbarToTop () {
this.$nextTick(() => {
const wraps = document.querySelectorAll('.el-table__body-wrapper')
wraps.forEach(wrap => {
if (wrap) {
wrap.scrollTop = 0
wrap.scrollLeft = 0
}
})
})
},
promQueryParamConvert (alert) { promQueryParamConvert (alert) {
const obj = { ...alert } const obj = { ...alert }
let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'') + ')' let r = '(' + obj.alertRule.expr.replace(/\"/g, '\'').replace(/\r|\n+/g, '') + ')'
let intoLabels = false let intoLabels = false
obj.labels = JSON.parse(obj.labels) obj.labels = JSON.parse(obj.labels)
if (Object.keys(obj.labels).length > 0) { if (Object.keys(obj.labels).length > 0) {
@@ -898,6 +932,14 @@ export default {
} }
return r return r
}, },
promQueryParamLabels (labels) {
const obj = JSON.parse(labels)
const filterArr = ['alertname', 'severity_id', 'severity', 'rule_type']
filterArr.forEach(key => {
delete obj[key]
})
return JSON.stringify(obj)
},
// asset弹框控制 // asset弹框控制
tabControl (data) { tabControl (data) {
if (data === 'close') { if (data === 'close') {
@@ -929,8 +971,21 @@ export default {
const searchLabel = Object.assign({}, this.searchLabel) const searchLabel = Object.assign({}, this.searchLabel)
searchLabel.format = this.importBox.format searchLabel.format = this.importBox.format
delete searchLabel.statistics delete searchLabel.statistics
if (this.searchCheckBox) {
Object.keys(this.searchCheckBox).forEach(key => {
if (searchLabel[key]) {
if (searchLabel[key].prototype.toString.call(val) === '[object Object]') {
Object.assign(searchLabel[key], this.searchCheckBox[key])
} else if (searchLabel[key].prototype.toString.call(val) === '[object Array]') {
searchLabel[key].concat(this.searchCheckBox[key])
}
} else {
searchLabel[key] = this.searchCheckBox[key]
}
})
}
this.$set(searchLabel, 'language', localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en') this.$set(searchLabel, 'language', localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en')
this.exportExcel({ ...searchLabel, state: this.state }) this.exportExcel('alert/message/export', { ...searchLabel, state: this.state })
this.closeDialog() this.closeDialog()
}, },
exportAll () { exportAll () {
@@ -938,8 +993,21 @@ export default {
temp.pageSize = -1 temp.pageSize = -1
delete temp.statistics delete temp.statistics
temp.format = this.importBox.format temp.format = this.importBox.format
if (this.searchCheckBox) {
Object.keys(this.searchCheckBox).forEach(key => {
if (temp[key]) {
if (temp[key].prototype.toString.call(val) === '[object Object]') {
Object.assign(temp[key], this.searchCheckBox[key])
} else if (temp[key].prototype.toString.call(val) === '[object Array]') {
temp[key].concat(this.searchCheckBox[key])
}
} else {
temp[key] = this.searchCheckBox[key]
}
})
}
this.$set(temp, 'language', localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en') this.$set(temp, 'language', localStorage.getItem('nz-language') ? localStorage.getItem('nz-language') : 'en')
this.exportExcel({ ...temp, state: this.state }) this.exportExcel('alert/message/export', { ...temp, state: this.state })
this.closeDialog() this.closeDialog()
}, },
getTimeString () { getTimeString () {
@@ -956,7 +1024,7 @@ export default {
formatNum (num) { formatNum (num) {
return num > 9 ? num : '0' + num return num > 9 ? num : '0' + num
}, },
exportExcel (params) { exportExcel (url, params, fileName) {
for (const item in params) { for (const item in params) {
if (params[item]) { if (params[item]) {
if (item === 'alertMessageState') { if (item === 'alertMessageState') {
@@ -1058,16 +1126,16 @@ export default {
const params = JSON.parse(JSON.stringify(this.searchLabel)) const params = JSON.parse(JSON.stringify(this.searchLabel))
params.format = this.importBox.format params.format = this.importBox.format
delete params.statistics delete params.statistics
if (this.params2) { if (this.searchCheckBox) {
Object.keys(this.params2).forEach(key => { Object.keys(this.searchCheckBox).forEach(key => {
if (params[key]) { if (params[key]) {
if (params[key].prototype.toString.call(val) === '[object Object]') { if (params[key].prototype.toString.call(val) === '[object Object]') {
Object.assign(params[key], this.params2[key]) Object.assign(params[key], this.searchCheckBox[key])
} else if (params[key].prototype.toString.call(val) === '[object Array]') { } else if (params[key].prototype.toString.call(val) === '[object Array]') {
params[key].concat(this.params2[key]) params[key].concat(this.searchCheckBox[key])
} }
} else { } else {
params[key] = this.params2[key] params[key] = this.searchCheckBox[key]
} }
}) })
} }

View File

@@ -308,6 +308,9 @@ export default {
schedDays: response.data.schedDays ? response.data.schedDays.split(',').map(item => Number(item)) : [], schedDays: response.data.schedDays ? response.data.schedDays.split(',').map(item => Number(item)) : [],
receiverShow: response.data.receiver ? response.data.receiver.split(',').map(item => Number(item)) : [] receiverShow: response.data.receiver ? response.data.receiver.split(',').map(item => Number(item)) : []
} }
if (this.object.inr == 0) {
this.object.inr = undefined
}
if (copyFlag) { if (copyFlag) {
this.object.id = '' this.object.id = ''
this.object.name = this.object.name + '-copy' this.object.name = this.object.name + '-copy'

View File

@@ -517,6 +517,7 @@ export default {
this.getTableData() this.getTableData()
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = '' this.timer = ''
this.scrollbarToTop()
}, 1000) }, 1000)
} else { } else {
clearTimeout(this.timer) clearTimeout(this.timer)
@@ -524,9 +525,21 @@ export default {
this.getTableData() this.getTableData()
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = '' this.timer = ''
this.scrollbarToTop()
}, 1000) }, 1000)
} }
}, },
scrollbarToTop () {
this.$nextTick(() => {
const wraps = document.querySelectorAll('.el-table__body-wrapper')
wraps.forEach(wrap => {
if (wrap) {
wrap.scrollTop = 0
wrap.scrollLeft = 0
}
})
})
},
getDcData () { getDcData () {
return new Promise(resolve => { return new Promise(resolve => {
this.$get('dc', { pageSize: -1 }).then(response => { this.$get('dc', { pageSize: -1 }).then(response => {
@@ -673,7 +686,7 @@ export default {
} }
this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo) this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo)
this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize) this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize)
if (this.$route.path === '/asset' && !this.titleSearchList.model.children.length) { if (this.$route.path === '/asset' && this.titleSearchList) {
this.$set(this.searchLabel, 'statistics', 1) this.$set(this.searchLabel, 'statistics', 1)
}/* else { }/* else {
delete this.searchLabel.statistics delete this.searchLabel.statistics

View File

@@ -190,7 +190,7 @@ export default {
toDownloadAgent: function () { toDownloadAgent: function () {
this.getAllDc() this.getAllDc()
this.showAgentDownload = true this.showAgentDownload = true
this.token = sessionStorage.getItem('nz-token') this.token = localStorage.getItem('nz-token')
axios.get('/healthy').then(response => { axios.get('/healthy').then(response => {
const url = response.request.responseURL const url = response.request.responseURL
this.ipAddr = url.split('/healthy')[0] this.ipAddr = url.split('/healthy')[0]

View File

@@ -0,0 +1,125 @@
<template>
<div>
<el-dialog class="nz-dialog" :title="$t('overall.changePin')" :visible.sync="visible" @open="dialogOpened" :modal-append-to-body='false' @closed="dialogClosed" width="600px" :show-close="false" >
<el-form :model="user" label-position = "top" label-width="150px" :rules="rules" ref="changePinForm" size="mini">
<el-form-item :label="$t('config.user.account')" prop="username" v-show="curUser != sysUser">
<el-input type="text" autocomplete="false" v-model="user.username" disabled id="change-pin-username"></el-input>
</el-form-item>
<el-form-item :label="$t('config.user.oldPin')" prop="pin">
<el-input type="password" autocomplete="false" :show-password="true" v-model="user.pin" maxlength="20" :placeholder="$t('config.user.inputOldPin')" id="change-pin-pin"></el-input>
</el-form-item>
<el-form-item :label="$t('config.user.newPin')" prop="newPin">
<el-input type="password" autocomplete="false" :show-password="true" v-model="user.newPin" maxlength="20" :placeholder="$t('config.user.inputNewPin')" id="change-pin-newPin"></el-input>
</el-form-item>
<el-form-item :label="$t('config.user.confirmPin')" prop="confirmPin">
<el-input type="password" autocomplete="false" :show-password="true" v-model="user.confirmPin" maxlength="20" :placeholder="$t('config.user.inputConfirmPin')" id="change-pin-confirmPin"></el-input>
</el-form-item>
</el-form>
<!--底部按钮-->
<template slot="footer">
<div class="right-box-bottom-btns" >
<button @click="close" id="change-pin-esc"
class="nz-btn nz-btn-size-normal-new nz-btn-style-light-new">
<span>{{$t('overall.cancel')}}</span>
</button>
<button @click="changePin" id="change-pin-save"
class="nz-btn nz-btn-size-normal-new nz-btn-style-normal-new">
<span>{{$t('overall.save')}}</span>
</button>
</div>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'changePin',
props: {
curUser: { type: String },
showDialog: { type: Boolean, default: false }
},
data () {
const temp = this
const validatePass = (rule, value, callback) => {
if (value && value != '') {
callback()
} else {
callback(new Error(temp.$t('config.user.invalidPin')))
}
}
const validateConfirmPass = (rule, value, callback) => {
if (value && value != '' && value == temp.user.newPin) {
callback()
} else {
callback(new Error(temp.$t('config.user.confirmPinErr')))
}
}
return {
user: {
username: '',
pin: '',
newPin: '',
confirmPin: ''
},
sysUser: localStorage.getItem('nz-username'),
rules: {
pin: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }],
newPin: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }, { validator: validatePass, trigger: 'blur' }],
confirmPin: [{ required: true, message: this.$t('config.user.reinputPin'), trigger: 'blur' }, { validator: validateConfirmPass, trigger: 'blur' }]
},
visible: false
}
},
created () {
this.user.username = this.curUser && this.curUser != '' ? this.curUser : localStorage.getItem('nz-username')
},
methods: {
dialogOpened: function () {
if (this.$refs.changePinForm) {
this.$refs.changePinForm.resetFields()
}
},
dialogClosed: function () {
this.$emit('dialogClosed')
},
close: function () {
this.visible = false
},
changePin: function () {
this.$refs.changePinForm.validate((valid) => {
if (valid) {
const paramObj = {
pin: this.user.pin,
newPin: this.user.newPin
}
this.$get('/sys/user/pin?oldPin=' + paramObj.pin + '&newPin=' + paramObj.newPin).then(response => {
if (response && response.code == 200) {
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
this.close()
} else {
this.$message.error(response.msg)
}
})
}
})
}
},
watch: {
showDialog: function (n, o) {
this.visible = n
}
}
}
</script>
<style >
.el-dialog__footer {
margin-top: 30px;
padding: 10px 20px 20px;
text-align: right;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
</style>

View File

@@ -60,7 +60,7 @@ export default {
url: 'sys/log', url: 'sys/log',
tableId: 'operationLogTable', // 需要分页的table的id用于记录每页数量, tableId: 'operationLogTable', // 需要分页的table的id用于记录每页数量,
mainTableHeight: this.$tableHeight.profile, mainTableHeight: this.$tableHeight.profile,
username: sessionStorage.getItem('nz-username'), username: localStorage.getItem('nz-username'),
layout: [], layout: [],
searchMsg: { // 给搜索框子组件传递的信息 searchMsg: { // 给搜索框子组件传递的信息
searchLabelList: [ searchLabelList: [

View File

@@ -151,7 +151,7 @@ export default {
}, },
data () { data () {
return { return {
username: sessionStorage.getItem('nz-username'), username: localStorage.getItem('nz-username'),
mfaEnable: localStorage.getItem('nz-mfa-enable'), mfaEnable: localStorage.getItem('nz-mfa-enable'),
authBindShow: false, authBindShow: false,
fileShow: false, fileShow: false,
@@ -369,7 +369,7 @@ export default {
}, },
downloadTxt () { downloadTxt () {
const element = document.createElement('a') const element = document.createElement('a')
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(this.fileContent)) element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponentComponent(this.fileContent))
element.setAttribute('download', 'Nezha recovery codes') element.setAttribute('download', 'Nezha recovery codes')
element.style.display = 'none' element.style.display = 'none'
element.click() element.click()

View File

@@ -224,6 +224,7 @@
:expression-list="expressions" :expression-list="expressions"
:id="promqlKeys[index-1]" :id="promqlKeys[index-1]"
:index="index-1" :index="index-1"
:required = 'true'
:type="promqlType" :type="promqlType"
:key="promqlKeys[index-1]" :key="promqlKeys[index-1]"
:plugins="['metric-selector', 'metric-input', 'remove']" :plugins="['metric-selector', 'metric-input', 'remove']"
@@ -500,6 +501,9 @@ export default {
spanList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], spanList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
limitOptions: [100, 200, 500, 1000, 2000], limitOptions: [100, 200, 500, 1000, 2000],
nullTypeList: [{ nullTypeList: [{
label: 'connected',
value: 'connected'
}, {
label: 'null', label: 'null',
value: 'null' value: 'null'
}, { }, {
@@ -618,7 +622,14 @@ export default {
this.$set(this.editChart, 'unit', Number.parseInt(unit)) this.$set(this.editChart, 'unit', Number.parseInt(unit))
}, },
expressionChange: function () { expressionChange: function () {
if (this.expressions[0]) {
this.editChart.elements = []
this.expressions.forEach((expr, i) => {
this.editChart.elements.push({ id: this.elementIds[i], expression: expr, type: 'expert', legend: this.legends[i] })
})
} else {
this.editChart.elements = []
}
}, },
addExpression () { addExpression () {
this.expressions.push('') this.expressions.push('')

View File

@@ -0,0 +1,975 @@
<template>
<div v-clickoutside="clickout" :class="{'metric-editor-rb': styleType === 2}" class="metric-editor">
<div :id="id" ref="editor" :style="{height: styleType === 2 ? 'auto' : ''}" class="editor-core"></div>
<span class="nz-input-append editor-clear" style="display: none" @click="clearContent"><i class="nz-icon nz-icon-circle-close"></i></span>
<div class="metric-editor-popper" :style="{left:popperPos.left+'px'}" v-show="false">
<div class="metric-popper-main" v-show="showType">
<div ref="scroll" style="height: 100%;width:100%; overflow: auto;">
<div v-for="(key, index) in orders" :key="index">
<div v-html="key" class="popper-group" v-show="showSuggestions[key]"></div>
<div v-for="(item) in showSuggestions[key]" :key="item.insertText" :type="key" :value="item.insertText" class="popper-item" @mouseout="itemOut(item)" @mouseover="itemHover(item)" v-html="item.label" @click.stop="handleItemClick(key,item,$event)"></div>
</div>
</div>
</div>
<div class="metric-popper-desc" v-if="showType&&Object.keys(showSuggestions).length>0&&showDescription && detailItem && detailItem.documentation">
<div><b>{{detailItem.insertText}}</b></div>
<hr/>
<div>{{detailItem.documentation}}</div>
</div>
</div>
</div>
</template>
<script>
import 'quill/dist/quill.snow.css'
import Quill from 'quill'
import suggestions from './suggestions'
export default {
name: 'editor',
props: {
value: String,
metricList: { type: Array },
styleType: Number,
historyParam: Object
},
model: {
prop: 'value',
event: 'expression-change'
},
components: {
},
data () {
return {
id: 'editor-' + this.guid(),
cursorIndex: 0,
pivotalCursorIndex: 0, // 用于记录输入特殊符号后当前光标的位置,方便选择后覆盖
newExpressionIndex: 0,
editRange: { start: 0, end: 0 },
noStyleSuggestions: {}, // 存储最原始的item数据
orders: ['history', 'operators', 'functions', 'metrics', 'labels', 'values', 'range'],
showSuggestions: {}, // 存储显示的item数据包含mark样式
storedSuggestions: [], // 存储每个item的dom
toggleSelectIndex: -1,
content: '',
popperPos: { left: '20px' },
options: {
theme: 'snow',
modules: {
toolbar: null
},
placeholder: this.$t('dashboard.metricPreview.inputTip')
},
labelValues: {},
tempStoreMetric: {},
showType: false,
showDescription: false,
detailItem: {},
formatTimer: null,
userChangeTimer: null,
filterTimer: null
}
},
created () {
this.queryMetrics()
},
methods: {
userChange (char, operation, newContent, oldContent) {
this.changeSuggestions('type')
this.dealSpecilChar(char, operation)
if (this.pivotalCursorIndex !== 0) {
// console.log('pivotalCursorIndex',this.pivotalCursorIndex,'cursorIndex',this.cursorIndex)
newContent = newContent.substring(this.pivotalCursorIndex, this.cursorIndex)
}
clearTimeout(this.filterTimer)
this.filterTimer = setTimeout(() => {
this.filterItems(newContent)
}, 200)
},
dealSpecilChar (char, operation) { // 控制括号的成对添加和删除
// console.log('specil char',char)
if (/^[\{\(\[\,]$/g.test(char)) {
if (operation === 'insert') {
if (char === '{' || char === ',') {
if (char === '{') {
this.addDoubleChar('}')
}
this.changeSuggestions('label')
} else if (char === '(') {
this.addDoubleChar(')')
this.queryTypeInfos()
} else if (char === '[') {
this.addDoubleChar(']')
this.changeSuggestions('range')
}
} else {
this.delDoubleChar(char)
}
} else if (/^[(=|!=|=~|!~)\"]/g.test(char)) {
if (operation === 'insert') {
if (char === '"') {
this.addDoubleChar('"')
}
this.changeSuggestions('values')
} else {
if (char === '"') {
this.delDoubleChar(char)
}
}
}
},
addDoubleChar (char) {
this.insertTextAtIndex(char, this.cursorIndex)
this.quill.setSelection(this.cursorIndex)
},
delDoubleChar (leftChar) {
const char = this.content.charAt(this.cursorIndex)
const temp = leftChar + char
if (/(\{\})|(\(\))|(\[\])|(\"\")/.test(temp)) {
this.quill.deleteText(this.cursorIndex, 1, 'api')
}
let tempIndex = this.pivotalCursorIndex
let tempChar = this.content.charAt(tempIndex - 1)
// 向前查找,找到边界
while (!/[\{\(\[,= ]/.test(tempChar) && tempIndex > 0) {
tempIndex--
tempChar = this.content.charAt(tempIndex)
}
// console.log('tempIndex =====',tempIndex)
this.pivotalCursorIndex = tempIndex === 0 ? -1 : tempIndex + 1
// console.log('after del double char',this.pivotalCursorIndex)
},
changeSuggestions (type) {
if (type === 'label') {
this.queryLabels()
} else if (type === 'values') {
this.queryValues()
} else if (type === 'type') {
this.packageTypeInfo()
} else if (type === 'range') {
this.noStyleSuggestions = { range: suggestions.getRateRange() }
}
},
packageTypeInfo () {
const functionReg = /[a-zA-Z_]\w*?\(.*?\)/g
if (functionReg.test(this.content)) {
functionReg.lastIndex = 0
const funcMatch = functionReg.exec(this.content)
const funcContent = funcMatch[0]
const funcReg = /\(.*\)/g
const match = funcReg.exec(funcContent)
const funcBody = match[0].substring(1, match[0].length - 1)
this.matchMetric(funcBody, funcMatch.index + match.index)
} else {
this.matchMetric()
}
},
formatContent () {
const punctuationReg = /[\{\}\(\)\[\]]/g
this.formatText(punctuationReg, { color: '#ff7941' })
const labelKeyReg = /[a-z_]\w*(?=\s*(=|!=|=~|!~))/g
this.formatText(labelKeyReg, { color: '#3274d9' })
const labelValueReg = /"(?:\\.|[^\\"])*"/g
this.formatText(labelValueReg, { color: '#3eb15b' })
const metricReg = /([A-Za-z:][\w:]*)\b(?![\(\]{=!",])/g
this.formatText(metricReg, { color: '#52545c' })
// let rangeReg=/(?<=\[)\b\d+[smdwy]\b(?=\])/ig
// this.formatText(rangeReg,{'color':'#9954bb'})
const rangeReg = /\[\b(\d+[smdwy])\b\]/ig
if (rangeReg.test(this.content)) {
const matchs = this.globalMatch(rangeReg, this.content)
// console.log('matchs',matchs)
matchs.forEach(item => {
this.quill.formatText(item.index + 1, item[1].length, { color: '#9954bb' }, 'silent')
})
}
},
formatText (pattern, style) {
if (pattern.test(this.content)) {
const matchs = this.globalMatch(pattern, this.content)
matchs.forEach(item => {
this.quill.formatText(item.index, item[0].length, style, 'silent')
})
}
},
matchMetric () {
const metricReg = /[a-zA-Z_]\w*?\b\{.*?\}/g
if (metricReg.test(this.content)) {
const match = this.globalMatch(metricReg, this.content)
if (match && match.length > 0) {
let isInnerExpression = false
let editExpression = null
match.forEach(item => {
const content = item[0]
const index = item.index
const length = content.length
if (index < this.cursorIndex && index + length > this.cursorIndex) { // 判断是否在一个完整子表达式中
isInnerExpression = true
editExpression = item
}
})
// console.log('match',match,'isInnerExpress',isInnerExpression)
if (isInnerExpression && editExpression) {
const expression = editExpression[0]
const labelValuesReg = /\{((\w*?(=|!=|=~|!~).*?,{0,1})+?)\}/
if (labelValuesReg.test(expression)) {
const match = labelValuesReg.exec(expression)
if (editExpression.index + match.index > this.cursorIndex) {
this.queryTypeInfos()
}
}
} else {
let tempIndex = this.cursorIndex
let tempChar = this.content.charAt(tempIndex - 1)
// 向前查找,找到边界
while (tempIndex > 0 && /[a-zA-Z_]/.test(tempChar)) {
tempIndex--
tempChar = this.content.charAt(tempIndex)
}
this.queryTypeInfos()
}
}
} else {
// console.log('mo match metric')
this.queryTypeInfos()
}
},
queryTypeInfos () {
this.noStyleSuggestions = {}
if (this.historyParam && this.historyParam.useHistory) {
const username = localStorage.getItem('nz-username')
const historyJson = localStorage.getItem(this.historyParam.key)
if (historyJson && historyJson !== 'undefined') {
const historyObj = JSON.parse(historyJson)
let history = historyObj[username]
history = history.filter(item => {
return item.time + item.expire >= new Date().getTime()
})
this.$set(this.noStyleSuggestions, 'history', history.slice(0, 10))
}
}
this.$set(this.noStyleSuggestions, 'metrics', this.tempStoreMetric)
// this.$set(this.noStyleSuggestions,'operators',suggestions.getOperators())
this.$set(this.noStyleSuggestions, 'functions', suggestions.getFunctions())
},
queryValues () {
const labelValuesReg = /\{((\w*?(=|!=|=~|!~).*?,{0,1})+?)\}/
if (labelValuesReg.test(this.content)) {
const match = labelValuesReg.exec(this.content)
const labelValues = match[0]
const index = match.index
if (labelValues) {
let tempCounter = this.cursorIndex
let equalIndex = -1
let boundaryIndex = -1
while (tempCounter >= index) {
const char = this.content.charAt(tempCounter)
if (/(=|!)/.test(char)) {
equalIndex = tempCounter
}
if (char === ',' || char === '{') {
boundaryIndex = tempCounter + 1
break
}
tempCounter--
}
const label = this.content.substring(boundaryIndex, equalIndex)
// console.log('label',this.content.substring(boundaryIndex,equalIndex))
const values = this.labelValues.get(label)
this.noStyleSuggestions = { values: values }
}
}
},
queryLabels () {
const labels = /\{.*\}/
if (labels.test(this.content)) {
const match = labels.exec(this.content)
const index = match.index
const matchContent = match[0]
if (this.cursorIndex < index || this.cursorIndex > index + matchContent.length) {
return
}
} else {
this.queryTypeInfos()
return
}
const metricReg = /([a-zA-Z_]\w*)\b\{.*?\}/g
let editMetricExpression = ''
const match = this.globalMatch(metricReg, this.content)
if (match && match.length > 0) {
for (let i = 0; i < match.length; i++) {
const temp = match[i]
if (temp.index < this.cursorIndex && temp.index + temp[0].length > this.cursorIndex) {
editMetricExpression = temp[0]
break
}
}
}
// console.log('query metric',editMetricExpression)
const metric = /([a-zA-Z_]\w*)\b(?=\{)/.exec(editMetricExpression)[0]
const timeRange = this.getDefaultTimeRange()
this.$get('/prom/api/v1/series?match[]={__name__="' + metric + '"}&start=' + timeRange[0] + '&end=' + timeRange[1]).then(response => {
if (response.status === 'success') {
const result = new Map()
response.data.forEach(item => {
for (const key in item) {
const value = item[key]
let values = result.get(key)
if (values) {
values.add(value)
} else {
values = new Set()
values.add(value)
}
result.set(key, values)
}
})
for (const key of result.keys()) {
let values = result.get(key)
values = Array.from(values).map(item => {
return { label: item, insertText: item }
})
result.set(key, values)
}
this.labelValues = result
const labels = Array.from(this.labelValues.keys()).map(item => {
return { label: item, insertText: item }
})
this.noStyleSuggestions = { labels: labels }
// console.log('change labels',this.showSuggestions)
} else {
this.noStyleSuggestions = {}
}
})
},
getDefaultTimeRange () {
const end = new Date()
const start = new Date()
start.setHours(new Date().getHours() - 1)
return [(start.getTime() / 1000).toFixed(0), (end.getTime() / 1000).toFixed(0)]
},
handleItemClick (type, item) {
// console.log(type,item,event)
if (type === 'metrics') {
this.handleMetricClick(item)
} else if (type === 'labels') {
this.handleLabelClick(item)
} else if (type === 'values') {
this.handleValueClick(item)
} else if (type === 'operators') {
this.handleOperatorClick(item)
} else if (type === 'functions') {
this.handleFunctionClick(item)
} else if (type === 'range') {
this.handleRangeClick(item)
} else if (type === 'history') {
this.handleHistoryClick(item)
}
},
handleHistoryClick (item) {
this.setContent(item.insertText)
this.showType = false
this.quill.blur()
this.$nextTick(() => {
this.$emit('on-blur')
})
},
handleRangeClick (item) {
this.quill.setSelection(this.pivotalCursorIndex, this.cursorIndex - this.pivotalCursorIndex, 'api')
this.deleteTextInRange(this.pivotalCursorIndex, this.cursorIndex)
this.insertTextAtIndex(item.insertText, this.pivotalCursorIndex)
this.showType = false
},
handleOperatorClick (item) {
this.deleteTextInRange(this.pivotalCursorIndex, this.cursorIndex)
this.$nextTick(() => {
this.insertTextAtIndex(item.insertText, this.pivotalCursorIndex, 'user')
this.quill.setSelection(this.pivotalCursorIndex + item.insertText.length)
this.storeCursor()
})
this.showType = false
},
handleFunctionClick (item) {
this.deleteTextInRange(this.pivotalCursorIndex, this.cursorIndex)
this.$nextTick(() => {
this.insertTextAtIndex(item.insertText, this.pivotalCursorIndex, 'user')
this.quill.setSelection(this.pivotalCursorIndex + item.insertText.length)
this.storeCursor()
})
this.showType = false
},
handleMetricClick (item) {
this.deleteTextInRange(this.pivotalCursorIndex, this.cursorIndex)
this.$nextTick(() => {
this.insertTextAtIndex(item.insertText, this.pivotalCursorIndex, 'user')
this.quill.setSelection(this.pivotalCursorIndex + item.insertText.length)
this.storeCursor()
})
this.showType = false
},
handleLabelClick (item) {
this.quill.setSelection(this.pivotalCursorIndex, this.cursorIndex - this.pivotalCursorIndex, 'api')
this.deleteTextInRange(this.pivotalCursorIndex, this.cursorIndex)
this.insertTextAtIndex(item.insertText + '', this.pivotalCursorIndex)
this.storeCursor().then(() => {
this.insertTextAtIndex('=', null, 'user')
this.quill.setSelection(this.cursorIndex + 1)
this.changeSuggestions('value')
})
this.showType = true
},
handleValueClick (item) {
const preChar = this.content.substring(this.pivotalCursorIndex - 1, this.pivotalCursorIndex)
this.quill.setSelection(this.pivotalCursorIndex, this.cursorIndex - this.pivotalCursorIndex, 'api')
this.deleteTextInRange(this.pivotalCursorIndex, this.cursorIndex)
if (preChar === '=') {
this.insertTextAtIndex('"' + item.insertText + '"', this.pivotalCursorIndex)
} else {
this.insertTextAtIndex(item.insertText, this.pivotalCursorIndex)
}
this.showType = false
},
toggleSelect (event) { // 上下键选择
if (event.code === 'ArrowDown' || event.keyCode === 40) {
if (this.toggleSelectIndex !== -1) {
const oldSuggestion = this.storedSuggestions[this.toggleSelectIndex]
oldSuggestion.classList = 'popper-item'
}
const suggestion = this.storedSuggestions[this.toggleSelectIndex >= this.storedSuggestions.length - 1 ? this.storedSuggestions.length - 1 : ++this.toggleSelectIndex]
const classList = suggestion.classList
suggestion.classList = classList + ' toggle-bg'
this.moveScroll()
} else if (event.code === 'ArrowUp' || event.keyCode === 38) {
if (this.toggleSelectIndex >= 1) {
const oldSuggestion = this.storedSuggestions[this.toggleSelectIndex]
oldSuggestion.classList = 'popper-item'
const suggestion = this.storedSuggestions[this.toggleSelectIndex <= 0 ? 0 : --this.toggleSelectIndex]
const classList = suggestion.classList
suggestion.classList = classList + ' toggle-bg'
this.moveScroll()
}
}
const item = this.findItemByToggleIndex()
if (item && item.documentation) {
this.showDescription = true
this.detailItem = this.deepClone(item)
} else {
this.showDescription = false
this.detailItem = {}
}
},
findItemByToggleIndex () {
const selectedItem = this.storedSuggestions[this.toggleSelectIndex]
if (selectedItem) {
const insertText = selectedItem.getAttribute('value')
const keys = Object.keys(this.noStyleSuggestions)
for (let i = 0; i < keys.length; i++) {
const items = this.noStyleSuggestions[keys[i]]
const item = items.find(t => {
return t.insertText === insertText
})
if (item) {
return item
}
}
}
return null
},
pickItem () { // Tab键 获取选择
const selectedItem = this.storedSuggestions[this.toggleSelectIndex]
if (selectedItem) {
const type = selectedItem.getAttribute('type')
const insertText = selectedItem.getAttribute('value')
if (type === 'metrics') {
this.handleMetricClick({ insertText: insertText })
} else if (type === 'labels') {
this.handleLabelClick({ insertText: insertText })
} else if (type === 'values') {
this.handleValueClick({ insertText: insertText })
} else if (type === 'operators') {
this.handleOperatorClick({ insertText: insertText })
} else if (type === 'range') {
this.handleRangeClick({ insertText: insertText })
} else if (type === 'functions') {
this.handleFunctionClick({ insertText: insertText })
} else if (type === 'history') {
this.handleHistoryClick({ insertText: insertText })
}
}
},
filterItems (input) { // 过滤下拉选显示
const suggestions = this.deepClone(this.noStyleSuggestions)
new Promise(resolve => {
const result = {}
this.orders.forEach(key => {
const typeValues = suggestions[key]
result[key] = []
typeValues && typeValues.forEach(item => {
const index = item.insertText.toLowerCase().indexOf(input.toLowerCase())
// console.log('index',index,'input',input)
if (index !== -1) {
// console.log('item',item.label,'input',input)
// item.label=item.label.replace(input,`<mark>${input}</mark>`);
const label = item.label
const pre = label.substring(0, index)
const middle = label.substring(index, index + input.length)
const suf = label.substring(index + input.length, label.length)
item.label = `${pre}<mark>${middle}</mark>${suf}`
result[key].push(item)
}
})
if (result[key].length < 1) {
delete result[key]
}
})
this.showSuggestions = result
resolve()
}).then(() => {
this.showType = Object.keys(this.showSuggestions).length > 0
})
/* let scroll=this.$refs.scroll.wrap;
scroll.scrollTop=0; */
},
storeSuggestions () {
this.$nextTick(() => {
const suggestions = this.$el.querySelectorAll('.popper-item')
this.storedSuggestions = [...suggestions]
// console.log('storedSuggestions->',suggestions)
})
},
setContent (value) {
this.clearContent()
this.quill.setText(value)
},
clearContent () {
this.quill.deleteText(0, this.quill.getLength(), 'api')
this.cursorIndex = 0
this.pivotalCursorIndex = 0
},
insertTextAtIndex (content, index, source = 'api') {
this.quill.insertText(index || this.cursorIndex, content, source)
},
deleteTextInRange (from, to) {
return this.quill.deleteText(from, to - from, 'api')
},
setCursor (offset) {
this.$nextTick(() => {
if (!this.quill.hasFocus) {
this.quill.focus()
}
this.quill.setSelection(this.cursorIndex + offset, this.cursorIndex + offset, 'api')
this.storeCursor()
})
},
storeCursor (char) {
const $temp = this
return new Promise(function (resolve) {
$temp.$nextTick(() => {
const range = $temp.quill.getSelection()
// console.log('range',range)
if (range && range.length === 0) {
$temp.cursorIndex = range.index
// console.log('current cursor-->',$temp.cursorIndex)
if (/^[\{\(\[,= "]$/g.test(char)) {
$temp.pivotalCursorIndex = $temp.cursorIndex
// console.log('store pivotalCursorIndex',$temp.pivotalCursorIndex)
}
resolve()
}
})
})
},
moveCursorToEnd () {
setTimeout(() => {
this.$nextTick(() => {
const offset = this.quill.getLength()
this.setCursor(offset)
}, 100)
})
},
moveScroll () {
/* let scroll=this.$refs.scroll.wrap;
//console.log('scroll',scroll)
if(scroll){
let curScroll=scroll.scrollTop;//滚动条当前位置
let scrollLen=scroll.scrollHeight;//滚动条总长
let mainDom=this.$el.querySelector('.metric-popper-main');
let windowHeight=mainDom.clientHeight;
let highlightItem=this.storedSuggestions[this.toggleSelectIndex];
let itemHeight=highlightItem.clientHeight;
let itemPos=highlightItem.offsetTop; //高亮item距离父div顶部的距离
// console.log('curScroll',curScroll,'scrollLen',scrollLen,'windowHeight',windowHeight,'itemPos',itemPos,'itemHeight',itemHeight)
if(itemPos + itemHeight*2 > windowHeight){ //提前两个位置
scroll.scrollTop=itemPos-windowHeight+itemHeight*2
}else{
let interval = windowHeight/10;
let intervalFunc = setInterval(function(){ //花200ms分10次回到顶部模拟动画效果
if (curScroll == 0) {
clearInterval(intervalFunc);
} else {
curScroll = (curScroll - interval) < interval*0.5 ? 0 : curScroll - interval;
scroll.scrollTop = curScroll;
}
}, 20);
}
} */
},
clickout () {
if (this.quill && this.quill.hasFocus()) {
this.$emit('on-blur')
}
this.showType = false
},
itemHover (item) {
if (item && item.documentation) {
this.showDescription = true
this.detailItem = this.deepClone(item)
}
},
itemOut () {
if (this.toggleSelectIndex !== -1) {
const tempItem = this.findItemByToggleIndex()
if (tempItem && tempItem.documentation) {
this.showDescription = true
this.detailItem = this.deepClone(tempItem)
} else {
this.showDescription = false
this.detailItem = {}
}
} else {
this.showDescription = false
this.detailItem = {}
}
},
getContent (from, to) {
let content = this.quill.getText(from, to)
content = content.substring(0, content.length - 1)
return content
},
getPosition () {
this.$nextTick(() => {
this.popperPos = this.quill.getBounds(this.cursorIndex)
// console.log('position:',this.popperPos)
})
},
guid () {
function S4 () {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
}
return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())
},
registerKeydown () {
const $temp = this
$temp.$el.addEventListener('keydown', function (event) {
// console.log('keydown',event)
$temp.toggleSelect(event)
})
this.quill.keyboard.addBinding({
key: 'DOWN'
}, function () {
return false
})
this.quill.keyboard.addBinding({
key: 'UP'
}, function () {
return false
})
// this.quill.keyboard.addBinding({ key:'backspace'}, function(range,content) {
// console.log('quill tab binding',range,content)
// return false;
// });
},
deepClone (source) {
return JSON.parse(JSON.stringify(source))
},
globalMatch (pattern, content) {
const result = []
let temp
pattern.lastIndex = 0
while ((temp = pattern.exec(content)) != null) {
result.push(temp)
}
return result
},
queryMetrics () {
if (this.metricList && this.metricList.length > 0) {
this.tempStoreMetric = this.deepClone(this.metricList)
this.queryTypeInfos()
} else {
this.$get('/prom/api/v1/label/__name__/values').then(response => {
if (response.status === 'success') {
const metrics = response.data.map(item => {
return { label: item, insertText: item }
})
this.tempStoreMetric = this.deepClone(metrics)
this.queryTypeInfos()
}
})
}
}
},
computed: {
},
mounted () {
const $temp = this
const bindings = { // quill默认的键只能通过这种方式覆盖
tab: {
key: 9,
handler () {
$temp.pickItem()
}
},
enter: {
key: 13,
handler () {
if (!$temp.showType) {
$temp.showType = false
$temp.quill.blur()
$temp.$emit('on-enter')
return false
} else {
$temp.pickItem()
}
}
}
}
this.options.modules.keyboard = {}
this.options.modules.keyboard.bindings = bindings
this.quill = new Quill(this.$refs.editor, this.options)
$temp.$el.addEventListener('paste', function (even) {
/* let text='';
setTimeout(()=>{
text=$temp.getContent();
},100)//此值必须小于userChangeTimer的值
setTimeout(()=>{
$temp.setContent(text);
$temp.quill.setSelection($temp.cursorIndex+text.length);
},200)//此值必须大于userChangeTimer的值 */
})
this.quill.clipboard.addmatchers(Node.ELEMENT_NODE, (node, delta) => {
const ops = []
delta.ops.forEach(op => {
if (op.insert && typeof op.insert === 'string') {
ops.push({
insert: op.insert
})
}
})
delta.ops = ops
return delta
})
this.quill.on('text-change', function (delta, oldDelta, source) {
if (source !== 'silent') {
// console.log('delta',delta,'oldDelta',oldDelta,'source',source)
let char = ''; let operation = ''
let oldContent = ''
oldDelta.ops.forEach((item, index) => {
if (index !== oldDelta.ops.length - 1) {
oldContent += item.insert
}
})
if (delta.ops.length === 1) {
if (delta.ops[0].insert) {
char = delta.ops[0].insert
operation = 'insert'
} else if (delta.ops[0].delete) {
char = oldContent
operation = 'delete'
} else {
console.error('unknow operation')
}
} else if (delta.ops.length === 2) {
if (delta.ops[1].insert) {
char = delta.ops[1].insert
operation = 'insert'
} else if (delta.ops[1].delete) {
char = oldContent.substring(delta.ops[0].retain, delta.ops[0].retain + delta.ops[1].delete)
operation = 'delete'
} else {
console.error('unknow operation')
}
}
const promise = $temp.storeCursor(char)
if (source === 'user') {
// console.log(delta,oldDelta,oldContent)
// clearTimeout($temp.userChangeTimer)
// $temp.userChangeTimer=setTimeout(()=>{
const newContent = $temp.getContent()
promise.then(() => { // 存储完光标后再进行后面的操作
$temp.userChange(char, operation, newContent, oldContent)
})
// },100)
}
$temp.content = $temp.getContent()
// console.log('current content-->',$temp.content)
$temp.getPosition()
/* clearTimeout($temp.formatTimer)
$temp.formatTimer=setTimeout($temp.formatContent,100) */
$temp.formatContent()
}
})
this.registerKeydown()
},
watch: {
content (n) {
this.$emit('expression-change', n)
if (!n) {
this.cursorIndex = 0
this.pivotalCursorIndex = 0
}
},
showSuggestions: {
immediate: true,
deep: true,
handler () {
this.toggleSelectIndex = -1
this.storeSuggestions()
}
}
},
beforeDestroy () {
this.quill.off('text-change')
}
}
</script>
<style scoped lang="scss">
.metric-editor{
position: relative;
height: 36px;
}
.metric-editor-popper{
position: absolute;
height: 600px;
padding: 10px;
margin-top: 5px;
overflow: hidden;
z-index:2001;
}
.metric-editor-popper .metric-popper-main{
display: inline-block;
box-sizing: border-box;
border: 1px solid lightgrey;
height: 100%;
/*max-width: 66%;*/
min-width: 200px;
float: left;
border-radius: 3px;
box-shadow: 0 5px 10px 0 #dde4ed;
color: #52545c;
padding: 5px;
background-color: white;
overflow-x: hidden;
}
.metric-editor-popper .metric-popper-desc{
display: inline-block;
box-sizing: border-box;
border-top: 1px solid lightgrey;
border-bottom: 1px solid lightgrey;
border-right: 1px solid lightgrey;
max-width: 44%;
height: 100%;
border-radius: 3px;
box-shadow: 0 5px 10px 0 #dde4ed;
color: #52545c;
padding: 5px;
background-color: white;
}
.metric-editor-popper .popper-item{
height: 20px;
line-height: 20px;
font-size: 12px !important;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
text-overflow: ellipsis;
white-space: nowrap;
padding: 8px 8px 8px 16px;
transition: color 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s, border-color 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s, background 0.3s cubic-bezier(0.645, 0.045, 0.355, 1) 0s, padding 0.15s cubic-bezier(0.645, 0.045, 0.355, 1) 0s;
}
.metric-editor-popper .popper-group{
height: 20px;
line-height: 20px;
font-size: 16px !important;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
text-overflow: ellipsis;
white-space: nowrap;
padding: 8px 8px 8px 8px;
border-bottom: 1px solid #dcdcdc;
}
.toggle-bg{
background-color:rgb(233, 237, 242) ;
}
.editor-core:hover + .editor-clear{
display: inline-block !important;
}
.editor-clear {
padding-top: 8px;
}
.editor-clear:hover{
display: inline-block !important;
}
</style>
<style lang="scss">
mark{
color: rgb(255, 133, 27);
border-bottom: 1px solid rgb(255, 133, 27);
background: inherit;
padding: 0;
}
.metric-editor .ql-editor{
padding:7px 10px 10px 10px !important;
overflow: hidden;
}
.metric-editor.metric-editor-rb {
min-height: 32px;
border-radius: 4px;
height: auto;
border: 1px solid #DCDFE6;
box-sizing: border-box;
.editor-clear {
padding-top: 4px;
}
.ql-container.ql-snow {
border: none;
.ql-editor {
padding: 5px 0 !important;
>p {
padding: 0 26px 0 15px;
font-size: 12px;
color: rgb(96, 98, 102);
}
}
}
}
</style>

View File

@@ -464,11 +464,12 @@ export default {
if (!limit) { if (!limit) {
limit = this.$refs.logDetail ? this.$refs.logDetail.getLimit() : 100 limit = this.$refs.logDetail ? this.$refs.logDetail.getLimit() : 100
} }
this.$refs.logDetail && this.$refs.logDetail.resetOperation()
if (this.expressions.length > 0) { if (this.expressions.length > 0) {
const requestArr = [] const requestArr = []
this.expressions.forEach((item, index) => { this.expressions.forEach((item, index) => {
if (item != '') { if (item != '') {
requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + item + '&start=' + this.$stringTimeParseToUnix(this.filterTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.filterTime[1]) + '&limit=' + limit)) requestArr.push(this.$get('/logs/loki/api/v1/query_range?format=1&query=' + encodeURIComponent(item) + '&start=' + this.$stringTimeParseToUnix(this.filterTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.filterTime[1]) + '&limit=' + limit))
} }
}) })
if (requestArr.length > 0) { if (requestArr.length > 0) {
@@ -611,7 +612,7 @@ export default {
const step = bus.getStep(this.filterTime[0], this.filterTime[1]) const step = bus.getStep(this.filterTime[0], this.filterTime[1])
promqlInputIndexs.push(index) promqlInputIndexs.push(index)
queryExpression.push(item) queryExpression.push(item)
requestArr.push(this.$get('/prom/api/v1/query_range?query=' + item + '&start=' + this.$stringTimeParseToUnix(this.filterTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.filterTime[1]) + '&step=' + step + '&nullType=null')) requestArr.push(this.$get('/prom/api/v1/query_range?query=' + encodeURIComponent(item) + '&start=' + this.$stringTimeParseToUnix(this.filterTime[0]) + '&end=' + this.$stringTimeParseToUnix(this.filterTime[1]) + '&step=' + step + '&nullType=null'))
} }
}) })
if (requestArr.length > 0) { if (requestArr.length > 0) {
@@ -668,8 +669,11 @@ export default {
this.$refs['promql-' + promqlIndex][0].setError('') this.$refs['promql-' + promqlIndex][0].setError('')
} else { } else {
// console.log(response) if (response.error) {
this.$refs['promql-' + promqlIndex][0].setError(response.error) this.$refs['promql-' + promqlIndex][0].setError(response.error)
} else {
this.$refs['promql-' + promqlIndex][0].setError(response)
}
} }
}) })
@@ -693,7 +697,7 @@ export default {
const requestArr = [] const requestArr = []
this.expressions.forEach((item, index) => { this.expressions.forEach((item, index) => {
if (item !== '') { if (item !== '') {
requestArr.push(this.$get('/prom/api/v1/query?query=' + item)) requestArr.push(this.$get('/prom/api/v1/query?query=' + encodeURIComponent(item)))
} }
}) })
if (requestArr.length > 0) { if (requestArr.length > 0) {
@@ -759,6 +763,7 @@ export default {
}, },
expressionChange () { expressionChange () {
const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.pageObj.pageNo = 1
// console.log(this.filterTime,nowTimeType); // console.log(this.filterTime,nowTimeType);
this.setSearchTime(nowTimeType.type, nowTimeType.value) this.setSearchTime(nowTimeType.type, nowTimeType.value)
if (this.showMetrics) { if (this.showMetrics) {
@@ -801,7 +806,7 @@ export default {
const expressions = this.expressions.filter(item => { const expressions = this.expressions.filter(item => {
return item && item != '' return item && item != ''
}) })
const username = sessionStorage.getItem('nz-username') const username = localStorage.getItem('nz-username')
if (historyJson && historyJson != 'undefined' && historyJson != '') { if (historyJson && historyJson != 'undefined' && historyJson != '') {
const historyObj = JSON.parse(historyJson) const historyObj = JSON.parse(historyJson)
let history = historyObj[username] let history = historyObj[username]

View File

@@ -104,6 +104,7 @@
<script> <script>
import * as echarts from 'echarts' import * as echarts from 'echarts'
import chartConfig from '@/components/page/dashboard/overview/chartConfig' import chartConfig from '@/components/page/dashboard/overview/chartConfig'
import { dealLegendAlias } from '@/components/common/js/tools'
export default { export default {
name: 'logTab', name: 'logTab',
props: { props: {
@@ -178,6 +179,12 @@ export default {
} }
}, },
methods: { methods: {
resetOperation () {
this.operations = {
levels: [0, 1, 2, 3, 4, 5, 6],
descending: true
}
},
exportLog () { exportLog () {
this.$emit('exportLog', this.operations) this.$emit('exportLog', this.operations)
}, },
@@ -478,7 +485,7 @@ export default {
host += '}' host += '}'
} }
// 处理legend别名 // 处理legend别名
alias = this.dealLegendAlias(host, row.elements.legend) alias = dealLegendAlias(host, row.elements.legend)
if (!alias || alias === '') { if (!alias || alias === '') {
alias = host alias = host
} }
@@ -487,23 +494,6 @@ export default {
} }
return alias return alias
}, },
dealLegendAlias: function (legend, expression) {
if (/\{\{.+\}\}/.test(expression)) {
const labelValue = expression.replace(/(\{\{.+?\}\})/g, function (i) {
const label = i.substr(i.indexOf('{{') + 2, i.indexOf('}}') - i.indexOf('{{') - 2)
const reg = new RegExp(label + '=".+?"')
let value = null
if (reg.test(legend)) {
const find = legend.match(reg)[0]
value = find.substr(find.indexOf('"') + 1, find.lastIndexOf('"') - find.indexOf('"') - 1)
}
return value || label
})
return labelValue
} else {
return expression
}
},
tooltipFormatter (params, a, b) { tooltipFormatter (params, a, b) {
const vm = this const vm = this
let str = ` let str = `

View File

@@ -0,0 +1,459 @@
<style lang="scss">
@import './metricPreview.scss';
</style>
<template>
<div class="main-container metric-dashboard">
<left-menu >
<div slot="content-left" class="slot-content">
<div class="sidebar-title">{{$t('dashboard.title')}}</div>
<div class="sidebar-info">
<div class="sidebar-info-item " @click="jumpTo('overview')">{{$t('dashboard.overview.title')}}</div>
<div class="sidebar-info-item sidebar-info-top" @click="jumpTo('panel')">{{$t('dashboard.panel.title')}}</div>
<div class="sidebar-info-item sidebar-info-item-active">{{$t('dashboard.metricPreview.title')}}</div>
<!-- <div class="sidebar-info-item "@click="jumpTo('explore')">{{$t('dashboard.metricPreview.title')}}</div>-->
</div>
</div>
<div slot="content-right" class="slot-content">
<!--<div class="top-tools">
<div class="float-right mr-10">
<my-date-picker size="mini" ref="calendar"
format="yyyy/MM/dd HH:mm"
@change="dateChange"
v-model="searchTime"
type="datetimerange"
:picker-options="pickerOptions"
:range-separator="$t('dashboard.panel.to')"
:start-placeholder="$t('dashboard.panel.startTime')"
:end-placeholder="$t('dashboard.panel.endTime')"
align="right">
</my-date-picker>
</div>
</div>-->
<div class="table-list" >
<div class="box-content" >
<el-row :gutter="20" class="row-width" style="height: calc(100% - 65px);">
<el-col :span="10" >
<metric-set :panelData="panelData" ref="metricSet" @on-view-chart="getChartParam" @reloadPanel="getPanelData" ></metric-set>
</el-col>
<el-col :span="0.5" ><div>&nbsp;</div></el-col>
<el-col :span="13" class="chart-preview-area" >
<my-date-picker size="mini" ref="calendar"
format="yyyy/MM/dd HH:mm"
@change="dateChange"
v-model="searchTime"
type="datetimerange"
:picker-options="pickerOptions"
:range-separator="$t('dashboard.panel.to')"
:start-placeholder="$t('dashboard.panel.startTime')"
:end-placeholder="$t('dashboard.panel.endTime')"
style="position:absolute; right: 10px"
align="right">
</my-date-picker>
<el-row class="border-area" v-show="chartCount === 'single'" style="margin-top: 40px;">
<div class="chartBox">
<line-chart-block
:show-setting="false"
:isExplore="true"
ref="editChartSingle"
@on-refresh-data="refreshChart"
@on-remove-chart-block="removeChart"
@on-edit-chart-block="editData"
></line-chart-block>
</div>
</el-row>
<el-row class="border-area" v-show="chartCount === 'multiple'">
<div style="height: 100%; overflow: auto;">
<div v-for="item in lineList" :key="item" class="chartBoxMul">
<line-chart-block
:show-setting="false"
ref="editChartMultiple"
@on-refresh-data="refreshChart"
@on-remove-chart-block="removeChart"
@on-edit-chart-block="editData"
></line-chart-block>
</div>
</div>
</el-row>
</el-col>
</el-row>
</div>
</div>
</div>
</left-menu>
</div>
</template>
<script>
import bus from '../../../libs/bus'
import metricSet from './metricSet'
import lineChartBlock from '../../charts/line-chart-block'
export default {
name: 'metricPreview',
components: {
lineChartBlock,
metricSet
},
data () {
return {
filter: {
start_time: '',
end_time: ''
},
total: 0, // 总数
selectedData: null, // 选中数据
searchName: '', // 搜索名称
showTagModal: false,
tagSet: null, // 根据你metric获取的tags信息
metricInfo: {}, // 保存参数信息
chartCount: 'single', // multiple
lineList: [], // 线列表
panelData: [], // panel列表
searchTime: [new Date().setHours(new Date().getHours() - 1), new Date()],
// searchTime:[new Date().setMinutes(new Date().getMinutes()-1),new Date()],
pickerOptions: {
shortcuts: [
{
text: this.$t('dashboard.panel.recOne'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setHours(start.getHours() - 1)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.recFour'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setHours(start.getHours() - 4)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.recOneDay'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 1)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.yesterday'),
onClick (picker) {
const start = new Date()
const end = new Date()
start.setDate(start.getDate() - 1)
start.setHours(0)
start.setMinutes(0)
start.setSeconds(0)
end.setDate(end.getDate() - 1)
end.setHours(23)
end.setMinutes(59)
end.setSeconds(59)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.recSevenDay'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 7)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.recOneMonth'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setDate(start.getDate() - 30)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.curMonth'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setDate(1)
start.setHours(0)
start.setMinutes(0)
picker.$emit('pick', [start, end])
}
}, {
text: this.$t('dashboard.panel.lastMonth'),
onClick (picker) {
const end = new Date()
const start = new Date()
start.setDate(1)
start.setMonth(start.getMonth() - 1)
end.setDate(0)
start.setStart()
end.setEnd()
picker.$emit('pick', [start, end])
}
}]
}
}
},
methods: {
jumpTo (data, id) {
// this.$store.state.assetData.moduleData = data;
// this.$store.state.assetData.selectedData = id;
bus.$emit('menu-change', data)
this.$store.state.showPanel.id = 0
this.$store.state.showPanel.name = ''
this.$router.push({
path: '/' + data,
query: {
t: +new Date()
}
})
},
// 获取默认时间
getInit () {
const end = new Date()
const start = new Date()
start.setHours(start.getHours() - 1)
start.setSeconds(0)
end.setSeconds(59)
this.filter.start_time = bus.timeFormate(start, 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(end, 'yyyy-MM-dd hh:mm:ss')
this.$refs.editChartSingle.setDivFirstShow(true)
},
dateChange (time) {
this.filter.start_time = `${time[0]}:00`
this.filter.end_time = `${time[1]}:59`
this.getChartParam(this.metricInfo, this.chartCount)
if (this.chartCount === 'single') {
this.$refs.editChartSingle.changeDate(this.searchTime)
} else if (this.chartCount === 'multiple') {
if (this.lineList.length > 0) {
this.$refs.editChartMultiple.forEach((item) => {
item.changeDate(this.searchTime)
})
}
}
},
getPanelData () { // 获取panel数据
this.$get('panel?pageNo=1&pageSize=-1').then(response => {
if (response.code === 200) {
this.panelData = response.data.list
}
})
},
// 获取图表信息
getChartParam (params, chartCount) {
this.chartCount = chartCount
this.metricInfo = params
if (this.chartCount === 'single') {
this.$refs.editChartSingle.showLoad()
} else if (this.chartCount === 'multiple') {
if (this.lineList.length > 0) {
this.$refs.editChartMultiple.forEach((item) => {
item.showLoad()
})
}
}
const startTime = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
const endTime = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss')
this.filter.start_time = startTime
this.filter.end_time = endTime
const step = bus.getStep(startTime, endTime)
const query = params.elements[0].expression
this.$get('/prom/api/v1/query_range?query=' + encodeURIComponent(query) + '&start=' + this.$stringTimeParseToUnix(startTime) + '&end=' + this.$stringTimeParseToUnix(endTime) + '&step=' + step).then(response => {
this.$refs.metricSet.loading = false
if (response.status === 'success') {
if (response.data.result) {
this.lineList = response.data.result
// 如果只有一组数据,强制显示一条
if (response.data.result.length === 1) {
this.chartCount = 'single'
}
if (response.data.result.length === 0) {
this.$refs.editChartSingle.setData(params, [], 0, this.filter, [])
}
}
this.getChartData(response, params)
} else {
this.chartCount = 'single'
// 图表不可保存
this.$refs.metricSet.saveDisabled = true
this.$refs.metricSet.isSave = false
this.chartCount = 'single'
if (response.msg) {
this.$message.error(response.msg)
} else if (response.error) {
this.$message.error(response.error)
} else {
this.$message.error(response)
}
this.$nextTick(() => {
this.$refs.editChartSingle.setData(params, [], 0, this.filter)
})
}
})
},
// 获取一个图表具体数据
getChartData (response, params) {
const chartItem = Object.assign({}, params)
chartItem.title = params.metric
const series = []
const legend = []
// 一个图表
response.data.result.forEach((queryItem) => {
const seriesItem = {
theData: {
name: '',
symbol: 'none', // 去掉点
smooth: 0.2, // 曲线变平滑
data: [],
type: chartItem.type ? chartItem.type : 'line',
// visible: true,
// threshold: null,
chartTitle: '',
lineStyle: {
width: 1,
opacity: 0.9
}
},
metric_name: ''
}
// 图表中每条线的名字,后半部分
// let host = `${queryItem.metric.__name__}`;//up,
let host = ''// up,
let charName = ''
if (queryItem.metric.__name__) {
host = `${queryItem.metric.__name__}`// up,
charName = `${queryItem.metric.__name__}`
}
// let charName = `${queryItem.metric.__name__}`;
const tagsArr = Object.keys(queryItem.metric)// ["__name__","asset","idc","instance","job","module","project"]
// 设置时间-数据格式对
const dpsArr = Object.entries(queryItem.values)// [ ["0",[1577959830.781,"0"]], ["1",[1577959845.781,"0"]] ]
// 判断是否有数据, && tagsArr.length > 0
if (dpsArr.length > 0) {
if (queryItem.metric.__name__) {
host += '{'
}
tagsArr.forEach((tag, i) => {
if (tag !== '__name__') {
host += `${tag}="${queryItem.metric[tag]}",`
}
if (tag === 'asset') {
const labVal = `${queryItem.metric[tag]}`
if (labVal !== '') {
charName += `(${queryItem.metric[tag]})`
}
}
})
if (host.endsWith(',')) { host = host.substr(0, host.length - 1) }
if (queryItem.metric.__name__) {
host += '}'
}
if (!host || host === '') {
host = params.metric
}
const alias = params.metric
legend.push({ name: host, alias: alias })
// 图表中每条线的名字,去掉最后的逗号与空格
seriesItem.theData.name = host
seriesItem.theData.chartTitle = charName
seriesItem.metric_name = seriesItem.theData.name
// 将秒改为毫秒
seriesItem.theData.data = queryItem.values.map(dpsItem =>
[dpsItem[0] * 1000, dpsItem[1]])
series.push(seriesItem.theData)
} else { /*
const errorMsg = `metric ${params.metric} 和tags ${params.tags} 组合下无数据`;
this.$message.error({
duration: 15,
content: errorMsg,
closable: true,
});
*/
}
})
// 将获取的数据运用于创建多个图表备用
this.$refs.metricSet.setSeries(response.data.result, series)
if (this.chartCount === 'single') {
// this.setSize(chartItem.span, 0);
const filterParams = Object.assign({}, this.filter)
filterParams.chartCount = 'single'
this.$nextTick(() => {
this.$refs.editChartSingle.setData(chartItem, series, 0, filterParams, legend)
})
} else if (this.chartCount === 'multiple') {
const filterParams = Object.assign({}, this.filter)
filterParams.chartCount = 'multiple'
this.setSize(chartItem.span, 'all')
this.$nextTick(() => {
series.forEach((serieData, index) => {
// 设置每个图表名称
const chartInfoParams = Object.assign({}, chartItem)
chartInfoParams.title = serieData.chartTitle
this.$refs.editChartMultiple[index]
.setData(chartInfoParams, [serieData], 0, filterParams, [legend[index]])
})
})
}
},
// 设置图表的宽度
setSize (size, index) {
this.$nextTick(() => {
const chartBox = document.getElementsByClassName('chartBox')
if (index === 0) {
chartBox[index].style.width = `${(size / 12) * 100}%`
} else {
const chartBoxMul = document.getElementsByClassName('chartBoxMul')
Array.prototype.slice.call(chartBoxMul).forEach((item) => {
const obj = item
obj.style.width = `${(size / 12) * 100}%`
})
}
})
},
refreshChart () {},
removeChart () {},
editData () {}
/*
// 查看指标确认
viewConfirm() {
this.showTagModal = false;
},
// 取消查看
viewCancel() {
this.showTagModal = false;
this.selectedData = {};
},
// 查看详情
viewDetail(item) {
this.selectedData = item;
},
// eslint-disable-next-line
search: _.debounce(function() { // 输入框筛选
}, 300),
// 刷新
reload() {
this.getChartParam(this.metricInfo, this.chartCount);
},
// 滚动条复位
refresh_scroll() {
window.scrollTo(0, 0);
},
*/
},
mounted: function () {
this.getInit()
this.getPanelData()
},
watch: {
}
}
</script>

View File

@@ -397,11 +397,12 @@ export default {
return params.title return params.title
}, },
defaultTooltipFormatter: function (params) { defaultTooltipFormatter: function (params) {
let showFlag = false
let minusFlag = true let minusFlag = true
let str = '<div>' let str = '<div>'
params instanceof Array || (params = [params]) params instanceof Array || (params = [params])
params.forEach((item, i) => { params.forEach((item, i) => {
const alias = this.queryAlias(i) const alias = this.queryAlias(item.seriesIndex)
if (i === 0 && alias.indexOf('Previous ') === -1) { if (i === 0 && alias.indexOf('Previous ') === -1) {
const value = item.data[0] const value = item.data[0]
const tData = new Date(value) const tData = new Date(value)
@@ -420,43 +421,50 @@ export default {
str += '<br/>' str += '<br/>'
minusFlag = false minusFlag = false
} }
const val = Number(item.data[1]) showFlag = showFlag || item.data[1]
str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">' if (!isNaN(item.data[1] + '')) {
str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${alias || item.seriesName}: </div>` const val = Number(item.data[1])
str += '<div style="padding-left: 10px;">' str += '<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;display: flex; justify-content: space-between; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 12px;">'
let dot = bus.countDecimals(val) str += `<div style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;"><span style='display:inline-block;margin-right:5px;border-radius:10px;width:15px;height:5px;background-color: ${item.color};}'></span>${alias || item.seriesName}: </div>`
// console.log(dot,val) str += '<div style="padding-left: 10px;">'
if (dot < this.chartDot) { let dot = bus.countDecimals(val)
dot = this.chartDot // console.log(dot,val)
} else if (dot > 6) { if (dot < this.chartDot) {
dot = 6 dot = this.chartDot
} } else if (dot > 6) {
str += chartDataFormat.getUnit(this.unit).compute(val, null, -1, dot) dot = 6
const previousItem = params.find((series) => ('Previous ' + item.seriesName) === series.seriesName)
if (previousItem) {
str += '<span style="padding-left: 10px; display: inline-block;width: 100px;text-align: right">'
const previousval = formatScientificNotation(previousItem.data[1], dot)
let minusVal = 0
if (previousval <= val) {
minusVal = val - previousval
str += '+'
} else {
minusVal = previousval - val
str += '-'
} }
str += chartDataFormat.getUnit(this.unit).compute(val, null, -1, dot)
const previousItem = params.find((series) => ('Previous ' + item.seriesName) === series.seriesName)
if (previousItem) {
str += '<span style="padding-left: 10px; display: inline-block;width: 65px;text-align: right;box-sizing: border-box;padding-right: 10px">'
const previousval = formatScientificNotation(previousItem.data[1], dot)
let minusVal = 0
if (previousval <= val) {
minusVal = val - previousval
str += '+'
} else {
minusVal = previousval - val
str += '-'
}
str += chartDataFormat.getUnit(this.unit).compute(minusVal, null, -1, dot) str += chartDataFormat.getUnit(this.unit).compute(minusVal, null, -1, dot)
str += '</span>' str += '</span>'
} else if (alias.indexOf('Previous ') !== -1) { } else if (alias.indexOf('Previous ') !== -1) {
str += '<span style="padding-left: 10px; display: inline-block;width: 100px;text-align: right">' str += '<span style="padding-left: 10px; display: inline-block;width: 100px;text-align: right">'
str += '</span>' str += '</span>'
}
str += '</div>'
str += '</div>'
} }
str += '</div>'
str += '</div>'
}) })
str += '</div>' str += '</div>'
return str if (!showFlag) {
return ''
} else {
return str
}
}, },
queryAlias: function (i) { queryAlias: function (i) {
let alias = null let alias = null

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="panel list-page"> <div class="panel list-page" v-loading="panelTabLoading">
<div class="main-list"> <div class="main-list">
<div> <div>
<transition name="el-zoom-in-center"> <transition name="el-zoom-in-center">
@@ -86,6 +86,7 @@
ref="chartList" ref="chartList"
:class="{'show-top':showTopBtn}" :class="{'show-top':showTopBtn}"
:data-list="dataList" :data-list="dataList"
:nowTimeType="nowTimeType"
:from="fromRoute.panel" :from="fromRoute.panel"
:panel-lock="panelLock" :panel-lock="panelLock"
:time-range="searchTime" :time-range="searchTime"
@@ -94,6 +95,7 @@
@on-remove-chart="delChart" @on-remove-chart="delChart"
@on-add-group-item-chart="addGroupItem" @on-add-group-item-chart="addGroupItem"
></chart-list> ></chart-list>
<chart-list :nowTimeType="nowTimeType" ref="chartList" :class="{'show-top':showTopBtn}" :from="fromRoute.panel" :panel-lock="panelLock" @on-edit-chart="editChart" @on-refresh-time="refreshTime" @on-remove-chart="delChart" @panel-list-loading="load" @on-add-group-item-chart="addGroupItem"></chart-list>
</div> </div>
</div> </div>
</div> </div>
@@ -131,6 +133,7 @@ export default {
data () { data () {
return { return {
fromRoute, fromRoute,
panelTabLoading: false,
overScroll10: false, overScroll10: false,
isLoading: true, isLoading: true,
panelLock: false, panelLock: false,
@@ -225,7 +228,8 @@ export default {
filterPanel: '', filterPanel: '',
// ---图表相关参数--end // ---图表相关参数--end
scrollbarWrap: null, scrollbarWrap: null,
batchDeleteObjs: [] batchDeleteObjs: [],
nowTimeType: {}
} }
}, },
components: { components: {
@@ -255,13 +259,8 @@ export default {
this.showPanel = val this.showPanel = val
this.showPanel.type = 'dashboard' this.showPanel.type = 'dashboard'
this.filter.panelId = this.showPanel.id this.filter.panelId = this.showPanel.id
// let curTime = this.$refs.calendarPanel.getCurrentTime(); this.dateChange()
const curTime = this.searchTime this.$refs.chartList.cleanData()
this.filter.start_time = bus.timeFormate(curTime[0], 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(curTime[1], 'yyyy-MM-dd hh:mm:ss')
// this.$refs.chartList.initCurrentRecordNum();
// this.$refs.chartList.cleanData()
this.getData(this.filter)
}, },
del (u) { del (u) {
@@ -327,7 +326,9 @@ export default {
this.rightBox.chartTemp.show = true this.rightBox.chartTemp.show = true
}, },
chartBySync () { chartBySync () {
this.panelTabLoading = true
this.$post('visual/panel/chart/syncTmpl', { panelId: this.showPanel.id }).then(res => { this.$post('visual/panel/chart/syncTmpl', { panelId: this.showPanel.id }).then(res => {
this.panelTabLoading = false
if (res.code === 200) { if (res.code === 200) {
this.getData(this.filter) this.getData(this.filter)
this.$message.success(this.$t('tip.syncSuccess')) this.$message.success(this.$t('tip.syncSuccess'))
@@ -486,6 +487,7 @@ export default {
// 选择日期变化 // 选择日期变化
dateChange (val) { dateChange (val) {
const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.setSearchTime(nowTimeType.type, nowTimeType.value, nowTimeType) this.setSearchTime(nowTimeType.type, nowTimeType.value, nowTimeType)
this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss') this.filter.start_time = bus.timeFormate(this.searchTime[0], 'yyyy-MM-dd hh:mm:ss')
this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss') this.filter.end_time = bus.timeFormate(this.searchTime[1], 'yyyy-MM-dd hh:mm:ss')

View File

@@ -590,7 +590,7 @@ export default {
} }
this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo) this.$set(this.searchLabel, 'pageNo', this.pageObj.pageNo)
this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize) this.$set(this.searchLabel, 'pageSize', this.pageObj.pageSize)
if (this.$route.path === '/monitor/endpoint' && !this.titleSearchList.project.children.length) { if (this.$route.path === '/monitor/endpoint') {
this.$set(this.searchLabel, 'statistics', 1) this.$set(this.searchLabel, 'statistics', 1)
} }
const params = { const params = {
@@ -664,6 +664,7 @@ export default {
this.getTableData() this.getTableData()
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = '' this.timer = ''
this.scrollbarToTop()
}, 1000) }, 1000)
} else { } else {
clearTimeout(this.timer) clearTimeout(this.timer)
@@ -671,9 +672,21 @@ export default {
this.getTableData() this.getTableData()
clearTimeout(this.timer) clearTimeout(this.timer)
this.timer = '' this.timer = ''
this.scrollbarToTop()
}, 1000) }, 1000)
} }
}, },
scrollbarToTop () {
this.$nextTick(() => {
const wraps = document.querySelectorAll('.el-table__body-wrapper')
wraps.forEach(wrap => {
if (wrap) {
wrap.scrollTop = 0
wrap.scrollLeft = 0
}
})
})
},
getSearchableStateData (data) { getSearchableStateData (data) {
return new Promise(resolve => { return new Promise(resolve => {
// this.$get('asset/model?pageSize=-1').then(response => { // this.$get('asset/model?pageSize=-1').then(response => {

View File

@@ -1,7 +1,7 @@
import axios from 'axios' import axios from 'axios'
axios.interceptors.request.use(config => { axios.interceptors.request.use(config => {
const token = sessionStorage.getItem('nz-token') const token = localStorage.getItem('nz-token')
if (token) { if (token) {
config.headers.Authorization = token // 请求头token config.headers.Authorization = token // 请求头token
} }
@@ -58,6 +58,8 @@ axios.interceptors.response.use(
if (accountErrorCode.indexOf(response.data.code) !== -1 && noJumpPath.indexOf(window.location.hash) == -1) { if (accountErrorCode.indexOf(response.data.code) !== -1 && noJumpPath.indexOf(window.location.hash) == -1) {
window.location.href = '/' window.location.href = '/'
} }
} else {
return response
} }
return response return response
}, },
@@ -76,6 +78,8 @@ export function get (url, params) {
resolve(err.response.data) resolve(err.response.data)
} else if (err.message) { } else if (err.message) {
resolve(err.message) resolve(err.message)
} else {
resolve(err)
} }
}) })
}) })
@@ -90,6 +94,8 @@ export function post (url, params, headers) {
resolve(err.response.data) resolve(err.response.data)
} else if (err.message) { } else if (err.message) {
resolve(err.message) resolve(err.message)
} else {
resolve(err)
} }
}) })
}) })
@@ -104,6 +110,8 @@ export function put (url, params, headers) {
resolve(err.response.data) resolve(err.response.data)
} else if (err.message) { } else if (err.message) {
resolve(err.message) resolve(err.message)
} else {
resolve(err)
} }
}) })
}) })
@@ -118,6 +126,8 @@ export function del (url, params) {
resolve(err.response.data) resolve(err.response.data)
} else if (err.message) { } else if (err.message) {
resolve(err.message) resolve(err.message)
} else {
resolve(err)
} }
}) })
}) })

View File

@@ -38,7 +38,16 @@ router.beforeEach((to, from, next) => {
if (res.inited === 0) { if (res.inited === 0) {
next({ path: '/setup' }) next({ path: '/setup' })
} else { } else {
next() if (localStorage.getItem('nz-token')) {
next({
path: 'overview',
query: {
t: +new Date()
}
})
} else {
next()
}
} }
} }
}) })
@@ -52,7 +61,7 @@ router.beforeEach((to, from, next) => {
} }
}) })
}) })
} else if (sessionStorage.getItem('nz-token')) { } else if (localStorage.getItem('nz-token')) {
const i18nRequest = new Promise(resolve => { const i18nRequest = new Promise(resolve => {
// 从localStorage加载i18n // 从localStorage加载i18n
if (!store.getters.i18nIsReady) { if (!store.getters.i18nIsReady) {
@@ -76,12 +85,17 @@ router.beforeEach((to, from, next) => {
const permissionRequest = new Promise(resolve => { const permissionRequest = new Promise(resolve => {
if (store.getters.menuList.length === 0) { if (store.getters.menuList.length === 0) {
Vue.http.get(configUrl).then(config => { Vue.http.get(configUrl).then(config => {
post(config.body.baseUrl + 'sys/user/permissions', { token: sessionStorage.getItem('nz-token') }).then(res => { post(config.body.baseUrl + 'sys/user/permissions', { token: localStorage.getItem('nz-token') }).then(res => {
store.commit('setMenuList', sortByOrderNum(res.data.menus)) if (res.code === 200) {
store.commit('setButtonList', res.data.buttons) store.commit('setMenuList', sortByOrderNum(res.data.menus))
store.commit('setRoleList', res.data.roles) store.commit('setButtonList', res.data.buttons)
document.getElementsByTagName('body')[0].setAttribute('class', 'theme-' + localStorage.getItem(`nz-user-${localStorage.getItem('nz-user-id')}-theme`)) store.commit('setRoleList', res.data.roles)
resolve() document.getElementsByTagName('body')[0].setAttribute('class', 'theme-' + localStorage.getItem(`nz-user-${localStorage.getItem('nz-user-id')}-theme`))
resolve()
} else {
localStorage.removeItem('nz-token')
next({ path: '/login' })
}
}) })
}) })
} else { } else {

View File

@@ -57,7 +57,7 @@ const user = {
system_bgImg: localStorage.getItem('nz-sys-bgImg'), system_bgImg: localStorage.getItem('nz-sys-bgImg'),
dateFormat: localStorage.getItem('nz-default-dateFormat') dateFormat: localStorage.getItem('nz-default-dateFormat')
} }
sessionStorage.setItem('nz-token', res.data.token) localStorage.setItem('nz-token', res.data.token)
localStorage.setItem('nz-sys-name', res.data.systemName || defaultAppearance.system_name) localStorage.setItem('nz-sys-name', res.data.systemName || defaultAppearance.system_name)
if (res.systemLogo || defaultAppearance.system_logo) { if (res.systemLogo || defaultAppearance.system_logo) {
localStorage.setItem('nz-sys-logo', res.data.systemLogo || defaultAppearance.system_logo) localStorage.setItem('nz-sys-logo', res.data.systemLogo || defaultAppearance.system_logo)
@@ -100,9 +100,9 @@ const user = {
}) })
}, },
logoutSuccess (store, res) { logoutSuccess (store, res) {
sessionStorage.removeItem('nz-username')
localStorage.removeItem('nz-username') localStorage.removeItem('nz-username')
sessionStorage.removeItem('nz-token') localStorage.removeItem('nz-username')
localStorage.removeItem('nz-token')
} }
} }
} }