merge: 删除无用文件
This commit is contained in:
@@ -1,624 +0,0 @@
|
||||
<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>
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/nezha-fronted/src/components/common/rightBox/setting/globalizationBox.vue b/nezha-fronted/src/components/common/rightBox/setting/globalizationBox.vue (rejected hunks)
|
||||
@@ -145,7 +145,7 @@
|
||||
if (response.code === 200) {
|
||||
this.languageList = response.data
|
||||
if (!this.editGlobalization.id) {
|
||||
- this.languageList[0].value = 'en'
|
||||
+ this.languageList[1].value = 'en'
|
||||
}
|
||||
} else {
|
||||
this.$message.error(response.msg)
|
||||
@@ -1,125 +0,0 @@
|
||||
<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>
|
||||
@@ -1,975 +0,0 @@
|
||||
<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>
|
||||
@@ -1,459 +0,0 @@
|
||||
<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> </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>
|
||||
Reference in New Issue
Block a user