Merge branch 'dev-3.3' of https://git.mesalab.cn/nezha/nezha-fronted into dev-3.3

This commit is contained in:
likexuan
2022-05-30 09:20:52 +08:00
26 changed files with 538 additions and 133 deletions

View File

@@ -24,3 +24,6 @@
border-color: $--checkbox-border-color; border-color: $--checkbox-border-color;
background-color: $--background-color-empty; background-color: $--background-color-empty;
} }
.el-input__inner {
border-color: $--border-color-light;
}

View File

@@ -411,7 +411,7 @@
margin-right: 20px; margin-right: 20px;
height: 22px; height: 22px;
margin-top: 8px; margin-top: 8px;
border: 1px solid $--click-search-items-border-color; border: 1px solid $--explore-border-color-bottom;
background: $--background-color-empty; background: $--background-color-empty;
.el-cascader { .el-cascader {
@@ -461,7 +461,7 @@
} }
} }
.nz-label-search:hover { .nz-label-search:hover {
border-color: #C7C7C7; border-color: $--explore-border-color-bottom;
} }
} }
.click-search-dropdown { .click-search-dropdown {

View File

@@ -33,7 +33,8 @@
} }
&>.nz-table2 { &>.nz-table2 {
height: 100%; height: 100%;
padding-top: 20px !important; padding: 20px 20px 10px 20px !important;
box-sizing: border-box;
.table-list { .table-list {
background-color: $--background-color-empty; background-color: $--background-color-empty;
.list-width { .list-width {
@@ -44,6 +45,9 @@
} }
} }
} }
&>.bottom-panel{
padding: 15px 10px 10px 10px !important;
}
} }
.sub-top-tools .top-tool-btn-txt .nz-icon{ .sub-top-tools .top-tool-btn-txt .nz-icon{
display: inline-block; display: inline-block;
@@ -141,9 +145,7 @@
} }
.bottom-panel { .bottom-panel {
padding-top: 15px;
background-color: $--background-color-empty; background-color: $--background-color-empty;
padding-bottom: 10px;
height: calc(100% - 30px); height: calc(100% - 30px);
} }
.bottom-log { .bottom-log {

View File

@@ -61,7 +61,7 @@
} }
.edit-topologyLine{ .edit-topologyLine{
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); border-bottom: 1px solid $--explore-border-color-bottom;
} }
.topology-scroll{ .topology-scroll{
&.v{ &.v{

View File

@@ -269,8 +269,8 @@
.ti-input { .ti-input {
border: 1px solid $--border-color-light; border: 1px solid $--border-color-light;
.ti-tag.ti-valid { .ti-tag.ti-valid {
background-color: $--value-background-color; background-color: $--label-background-color !important;;
color: $--value-color; color: $--color-text-primary !important;;
} }
.ti-new-tag-input { .ti-new-tag-input {
color: $--color-text-regular !important; color: $--color-text-regular !important;

View File

@@ -1,4 +1,4 @@
.system { .system.backup {
padding-top: 40px; padding-top: 40px;
.system-config-backup { .system-config-backup {
width: 100% !important; width: 100% !important;
@@ -144,7 +144,7 @@
} }
} }
} }
} }
} }
.el-table_1_column_1 .cell{ .el-table_1_column_1 .cell{

View File

@@ -135,7 +135,7 @@
} }
.show-panel-name{ .show-panel-name{
display: inline-block; display: inline-block;
padding: 0 7px; padding: 0 5px;
font-weight: bold; font-weight: bold;
max-width: 310px; max-width: 310px;
overflow:hidden; overflow:hidden;
@@ -144,3 +144,9 @@
vertical-align: bottom; vertical-align: bottom;
color: $--color-text-primary; color: $--color-text-primary;
} }
.starred-pop{
padding: 8px 12px;
margin-bottom: 8px;
min-width: auto;
}

View File

@@ -18,7 +18,7 @@
.projectTopo{ .projectTopo{
flex: 1; flex: 1;
width: calc(50% - 10px); width: calc(50% - 10px);
margin-right: 10px; //margin-right: 10px;
min-width: 435px; min-width: 435px;
//div.page { //div.page {
// textarea { // textarea {

View File

@@ -1,3 +1,7 @@
.ping-popover.el-popover {
padding: 0;
margin-top: 5px;
}
.ping{ .ping{
.top-tool-left{ .top-tool-left{
// align-items: center; // align-items: center;
@@ -20,8 +24,8 @@
border-radius: 2px; border-radius: 2px;
border: 1px solid $--button-icon-border-color !important; border: 1px solid $--button-icon-border-color !important;
.ti-tag.ti-valid { .ti-tag.ti-valid {
background-color: $--value-background-color; background-color: $--label-background-color !important;;
color: $--value-color; color: $--color-text-primary !important;;
} }
.ti-new-tag-input { .ti-new-tag-input {
color: $--color-text-regular !important; color: $--color-text-regular !important;
@@ -35,20 +39,31 @@
} }
.ti-input:hover{} .ti-input:hover{}
} }
.choose{ .choose-box {
width: 50px !important; overflow: hidden;
height: 36px !important; width: calc(100% - 7px);
line-height: 36px !important; height: 30px;
padding: 0 !important; border: 1px solid $--border-color-light;
border-radius: 2px 0px 0px 2px !important; padding-left: 5px;
border-right: none !important; display: flex;
span{ //align-items: center;
display: flex; .nz-icon-arrow-down6{
align-content: center; font-size: 12px;
justify-content: center; color: $--color-text-secondary;
} }
}
.choose{
width: auto;
height: 26px !important;
line-height: 30px !important;
padding: 2px 4px !important;
border-radius: 2px !important;
border-right: none !important;
background: $--label-background-color;
margin-right: 5px;
color: $--color-text-primary;
i{ i{
font-size: 20px !important; font-size: 14px !important;
} }
} }
.btn{ .btn{

View File

@@ -19,8 +19,8 @@
border-radius: 2px; border-radius: 2px;
border: 1px solid $--button-icon-border-color !important; border: 1px solid $--button-icon-border-color !important;
.ti-tag.ti-valid { .ti-tag.ti-valid {
background-color: $--value-background-color; background-color: $--label-background-color !important;;
color: $--value-color; color: $--color-text-primary !important;;
} }
.ti-new-tag-input { .ti-new-tag-input {
color: $--color-text-regular !important; color: $--color-text-regular !important;
@@ -33,20 +33,31 @@
} }
.ti-input:hover{} .ti-input:hover{}
} }
.choose{ .choose-box {
width: 50px !important; overflow: hidden;
height: 36px !important; width: calc(100% - 7px);
line-height: 36px !important; height: 30px;
padding: 0 !important; border: 1px solid $--border-color-light;
border-radius: 2px 0px 0px 2px !important; padding-left: 5px;
border-right: none !important; display: flex;
span{ //align-items: center;
display: flex; .nz-icon-arrow-down6{
align-content: center; font-size: 12px;
justify-content: center; color: $--color-text-secondary;
} }
}
.choose{
width: auto;
height: 26px !important;
line-height: 30px !important;
padding: 2px 4px !important;
border-radius: 2px !important;
border-right: none !important;
background: $--label-background-color;
margin-right: 5px;
color: $--color-text-primary;
i{ i{
font-size: 20px !important; font-size: 14px !important;
} }
} }
.btn{ .btn{
@@ -103,7 +114,7 @@
} }
.nz-icon-edit{ .nz-icon-edit{
font-size: 26px; font-size: 26px;
} }
.el-icon-more{ .el-icon-more{
font-size: 22px; font-size: 22px;
} }
@@ -163,4 +174,4 @@
.pop-list{ .pop-list{
max-height: 144px; max-height: 144px;
overflow-y: auto; overflow-y: auto;
} }

View File

@@ -252,6 +252,8 @@ $--right-box-sub-title-border-color: $--border-color-light;
/* 16.tooltip */ /* 16.tooltip */
$--tooltip-background-color: #222329; $--tooltip-background-color: #222329;
$--tooltip-border-color: rgba(112,116,122,0.6); $--tooltip-border-color: rgba(112,116,122,0.6);
/* 17.label*/
$--label-background-color: #18171D;
/*** themes/common.scss是与主题切换无关的变量 ***/ /*** themes/common.scss是与主题切换无关的变量 ***/
@import './src/common/var.scss'; @import './src/common/var.scss';

View File

@@ -247,7 +247,8 @@ $--right-box-sub-title-border-color: $--right-box-sub-title-background-color;
/* 16.tooltip */ /* 16.tooltip */
$--tooltip-background-color: #ffffff; $--tooltip-background-color: #ffffff;
$--tooltip-border-color: rgba(119,131,145,0.6); $--tooltip-border-color: rgba(119,131,145,0.6);
/* 17.label*/
$--label-background-color: #D8d8d8;
/*** themes/common.scss是与主题切换无关的变量 ***/ /*** themes/common.scss是与主题切换无关的变量 ***/
@import './src/common/var.scss'; @import './src/common/var.scss';

View File

@@ -197,13 +197,13 @@ export default {
let minute = tData.getMinutes() let minute = tData.getMinutes()
minute = minute > 9 ? minute : '0' + minute // 如果分钟小于10,则在前面加0补充为两位数字 minute = minute > 9 ? minute : '0' + minute // 如果分钟小于10,则在前面加0补充为两位数字
if (minTime !== null && maxTime !== null) { if (minTime !== null && maxTime !== null) {
const diffSec = (maxTime - minTime) / 1000 const diffSec = (maxTime - minTime)
const secOneDay = 24 * 60 * 60// 1天的秒数 const secOneDay = 24 * 60 * 60// 1天的秒数
const secOneMonth = secOneDay * 30// 30天的秒数 const secOneMonth = secOneDay * 30// 30天的秒数
if (diffSec <= secOneDay) { // 同一天 if (diffSec <= secOneDay) { // 同一天
return [hour, minute].join(':') return [hour, minute].join(':')
} else if (diffSec < secOneMonth) { // 大于1天小于30天 } else if (diffSec < secOneMonth) { // 大于1天小于30天
return [tData.getMonth() + 1, tData.getDate()].join('/') + ' ' + [hour, minute].join(':') return [tData.getMonth() + 1, tData.getDate()].join('/') + '\n' + [hour, minute].join(':')
} else { // 大于等于30天 } else { // 大于等于30天
return [tData.getMonth() + 1, tData.getDate()].join('/') return [tData.getMonth() + 1, tData.getDate()].join('/')
} }

View File

@@ -72,6 +72,7 @@ import logsData from '@/components/chart/logsData'
import lodash from 'lodash' import lodash from 'lodash'
export default { export default {
// 该组件用于获取chart的具体数据
name: 'panelChart', name: 'panelChart',
components: { components: {
chartHeader, chartHeader,
@@ -79,44 +80,44 @@ export default {
ChartScreenHeader ChartScreenHeader
}, },
props: { props: {
chartInfo: Object, // 其中的param json串已转化为对象 chartInfo: Object, // 其中的param json串已转化为对象 // 当前chart的具体信息
timeRange: Array, // 时间范围 timeRange: Array, // 时间范围
isFullscreen: Boolean, isFullscreen: Boolean, // 是否全屏
panelLock: Boolean, panelLock: Boolean, // 是否被锁定
chartDetailInfo: Object, chartDetailInfo: Object,
from: String, from: String, // 使用该组件的位置
filter: {}, filter: {},
showHeader: { showHeader: { // 是否显示header
type: Boolean, type: Boolean,
default: true default: true
}, },
isExportHtml: { isExportHtml: { // 是否是导出的html
type: Boolean, type: Boolean,
default: false default: false
}, },
dataJson: { dataJson: { // 导出的html的数据
type: Object type: Object
} }
}, },
data () { data () {
return { return {
chartData: [], chartData: [], // 当前chart的数据
loading: true, loading: true,
isError: false, isError: false,
multipleTime: false, multipleTime: false, // 是否开启对比
minusTime: '', minusTime: '', // 是否开启对比相差的时间
showAllData: false, showAllData: false, // 是否显示所有legend
allDataLength: 0, allDataLength: 0,
severityData: this.$store.getters.severityData, severityData: this.$store.getters.severityData, // 告警级别的数据
severityDataWeight: this.$store.getters.severityDataWeight severityDataWeight: this.$store.getters.severityDataWeight
// isExportData: false // isExportData: false
} }
}, },
computed: { computed: {
headerH () { headerH () { // 50px header所包含的高
return this.$store.getters.getHeaderH return this.$store.getters.getHeaderH
}, },
headerHPadding () { headerHPadding () { // 50px header + padding 主要用于展开的空group
return this.$store.getters.getHeaderHPadding return this.$store.getters.getHeaderHPadding
} }
}, },
@@ -142,7 +143,7 @@ export default {
this.chartInfo.loaded && this.query(elements, startTime, endTime, step) this.chartInfo.loaded && this.query(elements, startTime, endTime, step)
}, },
// 参数 isRefresh 标识是否是刷新操作 // 参数 isRefresh 标识是否是刷新操作
getChartData (isRefresh, params) { getChartData (isRefresh, params) { // 获取chart的数据前的准备 主要用于处理时间参数
this.loading = true this.loading = true
// TODO assetInfo、endpointInfo、echarts等进行不同的处理 // TODO assetInfo、endpointInfo、echarts等进行不同的处理
let startTime = '' let startTime = ''
@@ -172,7 +173,7 @@ export default {
} }
this.chartInfo.loaded && this.query(elements, startTime, endTime, step, params) this.chartInfo.loaded && this.query(elements, startTime, endTime, step, params)
}, },
query (elements, startTime, endTime, step, params) { query (elements, startTime, endTime, step, params) { // 获取chart的数据
this.isError = false this.isError = false
this.allDataLength = 0 this.allDataLength = 0
// this.chartData = this.chartInfo.chartData // this.chartData = this.chartInfo.chartData
@@ -419,7 +420,7 @@ export default {
this.loading = false this.loading = false
} }
}, },
queryData (elements, startTime, endTime, step, params) { queryData (elements, startTime, endTime, step, params) { // 获取chart的数据主要用于导出的html
this.isError = false this.isError = false
this.allDataLength = 0 this.allDataLength = 0
// this.chartData = this.chartInfo.chartData // this.chartData = this.chartInfo.chartData

View File

@@ -99,8 +99,8 @@ export default {
subContentClass () { subContentClass () {
const className = [] const className = []
switch (this.targetTab) { switch (this.targetTab) {
case 'panel': case 'panelTab':
className.push('bottom-panel') className.push('nz-table2 bottom-panel')
break break
case 'log': { case 'log': {
className.push('bottom-log') className.push('bottom-log')

View File

@@ -43,6 +43,9 @@
<el-dropdown-item v-has="'main_edit'"> <el-dropdown-item v-has="'main_edit'">
<div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div> <div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-has="'panel_view'">
<div id="chart-export-html" @click="exportType"><i class="nz-icon nz-icon-download1"></i>{{ $t('overall.snapshoot') }}</div>
</el-dropdown-item>
</template> </template>
</top-tool-more-options> </top-tool-more-options>
</div> </div>
@@ -76,6 +79,9 @@
<el-dropdown-item v-has="'main_edit'"> <el-dropdown-item v-has="'main_edit'">
<div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div> <div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-has="'panel_view'">
<div id="chart-export-html" @click="exportType"><i class="nz-icon nz-icon-download1"></i>{{ $t('overall.snapshoot') }}</div>
</el-dropdown-item>
</template> </template>
</top-tool-more-options> </top-tool-more-options>
</div> </div>

View File

@@ -2,12 +2,46 @@
<el-popover :placement="placement" :popper-class="chartBox === true ? 'nz-pop nz-pop-select-panel right-box-select-top nz-pop-select-panel__dropdown' : 'nz-pop nz-pop-select-panel right-box-select-top right-public-box-dropdown-top nz-pop-select-panel__dropdown'" ref="selectPanelPopBox" transition="slide" v-model="popBox.show" :width="chartBox === true ? 626 : 310" :disabled="disabled"> <el-popover :placement="placement" :popper-class="chartBox === true ? 'nz-pop nz-pop-select-panel right-box-select-top nz-pop-select-panel__dropdown' : 'nz-pop nz-pop-select-panel right-box-select-top right-public-box-dropdown-top nz-pop-select-panel__dropdown'" ref="selectPanelPopBox" transition="slide" v-model="popBox.show" :width="chartBox === true ? 626 : 310" :disabled="disabled">
<div> <div>
<div class="pop-item-wider"> <div class="pop-item-wider">
<slot name="header"></slot> <slot name="header"></slot>
<div :class="{'movable': !panelLock}" class="select-panel-tree"> <div :class="{'movable': !panelLock}" class="select-panel-tree">
<el-tree <el-tree
:data="panelData" v-show="starredData[0].children.length"
:data="starredData"
:expand-on-click-node="false"
:filter-node-method="filterNode"
:props="{label: 'name', children: 'children'}"
@node-click="selectPanel"
default-expand-all
node-key="id"
ref="starredTree"
style="margin-bottom:5px"
class="starred-tree"
>
<div class="tree--node" slot-scope="{ node, data }">
<span :title="data.id?node.label + ' (' + data.chartNum +' charts':''" :class="{'select-panel-title':data.id===0}">{{ node.label }}</span>
<el-row class="block-col-2" style="margin-left:10px">
<el-col>
<el-dropdown v-if="!panelLock" placement="bottom-end" trigger="click" style="margin-right:10px">
<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="['main_edit', 'main_delete']">
<el-dropdown-item>
<div @click="editPanel(data)" v-has="'main_edit'"><i class="nz-icon nz-icon-edit"></i>{{$t('overall.edit')}}</div>
</el-dropdown-item>
<el-dropdown-item>
<div @click="deletePanel(data)" v-has="'main_delete'"><i class="nz-icon nz-icon-delete"></i>{{$t('overall.delete')}}</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<template v-if="data.id">
<i v-if="data.starred" class="el-rate__icon el-icon-star-on" @click.stop="delStarred(data)"></i>
<i v-else class="el-rate__icon el-icon-star-off" @click.stop="addStarred(data)"></i>
</template>
</el-col>
</el-row>
</div>
</el-tree>
<el-tree
:data="treeData"
:draggable="!panelLock" :draggable="!panelLock"
:expand-on-click-node="false" :expand-on-click-node="false"
:filter-node-method="filterNode" :filter-node-method="filterNode"
@@ -21,10 +55,10 @@
node-key="id" node-key="id"
ref="panelTree"> ref="panelTree">
<div class="tree--node" slot-scope="{ node, data }"> <div class="tree--node" slot-scope="{ node, data }">
<span :title="node.label + ' (' + data.chartNum +' charts' ">{{ node.label }}</span> <span :title="data.id?node.label + ' (' + data.chartNum +' charts':''" :class="{'select-panel-title':data.id===0}">{{ node.label }}</span>
<el-row class="block-col-2" v-if="!panelLock" style="width: 35px;"> <el-row class="block-col-2" style="margin-left:10px">
<el-col> <el-col>
<el-dropdown placement="bottom-end" trigger="click"> <el-dropdown v-if="!panelLock" placement="bottom-end" trigger="click" style="margin-right:10px">
<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="['main_edit', 'main_delete']"> <el-dropdown-menu class="right-box-select-top" slot="dropdown" v-has="['main_edit', 'main_delete']">
<el-dropdown-item> <el-dropdown-item>
@@ -35,6 +69,10 @@
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<template v-if="data.id">
<i v-if="data.starred" class="el-rate__icon el-icon-star-on" @click.stop="delStarred(data)"></i>
<i v-else class="el-rate__icon el-icon-star-off" @click.stop="addStarred(data)"></i>
</template>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
@@ -52,6 +90,7 @@
</template> </template>
<script> <script>
import bus from '@/libs/bus'
export default { export default {
name: 'selectPanel', name: 'selectPanel',
props: { props: {
@@ -72,6 +111,7 @@ export default {
immediate: true, immediate: true,
handler (n) { handler (n) {
this.$refs.panelTree && this.$refs.panelTree.filter(n) this.$refs.panelTree && this.$refs.panelTree.filter(n)
this.$refs.starredTree && this.$refs.starredTree.filter(n)
} }
}, },
showPanel: { showPanel: {
@@ -81,6 +121,14 @@ export default {
this.panel = JSON.parse(JSON.stringify(n)) this.panel = JSON.parse(JSON.stringify(n))
} }
} }
},
panelData: {
immediate: true,
handler (n) {
if (n) {
this.treeData[0].children = n
}
}
} }
/* panel: { /* panel: {
immediate: true, immediate: true,
@@ -95,10 +143,108 @@ export default {
data () { data () {
return { return {
popBox: { show: false }, popBox: { show: false },
panel: { id: 0, name: '' } panel: { id: 0, name: '' },
// 全部列表
treeData: [
{
id: 0,
name: 'All Panels',
children: []
}
],
// 收藏夹列表
starredData: [
{
id: 0,
name: 'Starred Panels',
children: []
}
],
tempArr: []
} }
}, },
methods: { methods: {
// 获取收藏的列表
async getStarred (type) {
const params = {
type: 'panel'
}
const response = await this.$get('/sys/user/starred', params)
if (response.code === 200) {
this.tempArr = []
this.recursionStarred(this.panelData, response.data)
this.starredData[0].children = this.formatStarred(this.tempArr)
if (type === 'tree') {
// 刷新树形控件
this.$emit('refreshStarred', { data: this.panelData, type: 'tree' })
} else {
this.$emit('refreshStarred', { data: this.panelData })
}
}
},
// 比对收藏的列表和全部列表 改变状态
recursionStarred (allList, starredList) {
allList.forEach((item) => {
item.starred = false
starredList.forEach((subItem) => {
// 判断全部列表每一项的id和收藏列表每一项的id是否相等
if (item.id === subItem.tid) {
if (this.tempArr.every(val => val.id !== item.id)) {
item.starred = true
this.tempArr.push({
...item,
children: []
})
}
}
})
if (item.children && item.children.length) {
this.recursionStarred(item.children, starredList)
}
})
},
// 格式化收藏列表 (树形)
formatStarred (list) {
const arr = JSON.parse(JSON.stringify(list))
arr.reverse()
for (let i = 0; i < arr.length; i++) {
if (arr[i].pid) {
// 找到父级所在下标
const parentIndex = arr.findIndex(subItem => subItem.id === arr[i].pid)
if (parentIndex > -1) {
arr[parentIndex].children.unshift(arr[i])
arr.splice(i, 1)
i--
}
}
}
return arr.reverse()
},
// 新增收藏
addStarred: bus.debounceFn(function (data) {
const params = {
type: 'panel',
tid: data.id
}
this.$post('/sys/user/starred', params).then(async response => {
if (response.code === 200) {
await this.getStarred()
data.starred = true
}
})
},
300, true),
// 删除收藏
delStarred: bus.debounceFn(function (data) {
this.$delete('/sys/user/starred?type=panel&tid=' + data.id).then(async response => {
if (response.code === 200) {
await this.getStarred()
data.starred = false
}
})
},
300, true),
/* /*
* node: 被拖的节点 * node: 被拖的节点
* relative: 发生关系的节点 * relative: 发生关系的节点
@@ -119,8 +265,8 @@ export default {
updateWeight () { updateWeight () {
const toUpdate = [] const toUpdate = []
let count = 0 let count = 0
handler(this.panelData)
handler(this.panelData)
function handler (panelData) { function handler (panelData) {
panelData.forEach(panel => { panelData.forEach(panel => {
panel.weight = count++ panel.weight = count++
@@ -130,7 +276,7 @@ export default {
} }
}) })
} }
this.getStarred()
this.$put('visual/panel/tree', toUpdate) this.$put('visual/panel/tree', toUpdate)
}, },
deletePanel (data) { deletePanel (data) {
@@ -144,6 +290,11 @@ export default {
}, },
// 确认选择某个节点,与父组件交互 // 确认选择某个节点,与父组件交互
selectPanel (data, checked, child) { selectPanel (data, checked, child) {
// 判断是否点击的Starred Panels或All Panels
if (!data.id) {
this.$refs.panelTree.setCurrentKey(this.showPanel)
return false
}
this.$emit('selectPanel', data) this.$emit('selectPanel', data)
this.$refs.panelTree.setCurrentKey(data) this.$refs.panelTree.setCurrentKey(data)
this.esc() this.esc()
@@ -151,3 +302,22 @@ export default {
} }
} }
</script> </script>
<style scoped>
.starred-tree>>>.el-tree__empty-block{
display: none;
}
.select-panel-title{
font-weight: bold;
font-size: 14px;
color: #333;
}
.el-rate__icon{
color: #C0C4CC !important;
cursor: pointer;
margin-right: 0px;
}
.el-icon-star-on{
color:#FF9219 !important;
transform: scale(1.2);
}
</style>

View File

@@ -500,19 +500,19 @@ export default {
this.importBox.width = '600px' this.importBox.width = '600px'
} else if (type == 2) { // export } else if (type == 2) { // export
this.importBox.title = this.$t('overall.exportExcel') this.importBox.title = this.$t('overall.exportExcel')
this.importBox.width = this.exportBoxShow ? '850px' : '580px' this.importBox.width = '580px'
if (this.exportBoxShow) { // if (this.exportBoxShow) {
this.formatArr = [ // this.formatArr = [
{ name: 'XLSX', value: 1 }, // { name: 'XLSX', value: 1 },
{ name: 'CSV', value: 2 }, // { name: 'CSV', value: 2 },
{ name: 'JSON', value: 3 }, // { name: 'JSON', value: 3 },
{ name: 'PDF', value: 4 }, // { name: 'PDF', value: 4 },
{ name: 'Html', value: 5 }] // { name: 'Html', value: 5 }]
} else { // } else {
this.formatArr = [{ name: 'XLSX', value: 1 }, // this.formatArr = [{ name: 'XLSX', value: 1 },
{ name: 'CSV', value: 2 }, // { name: 'CSV', value: 2 },
{ name: 'JSON', value: 3 }] // { name: 'JSON', value: 3 }]
} // }
} }
}, },
getTimeString () { getTimeString () {

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="system"> <div class="system backup">
<div class="system-config-form system-config-backup"> <div class="system-config-form system-config-backup">
<div class="system-title">{{ $t("backup.configurations") }}</div> <div class="system-title">{{ $t("backup.configurations") }}</div>
<nz-data-list <nz-data-list

View File

@@ -13,7 +13,7 @@
</div> </div>
<template v-else> <template v-else>
<div class="top-tool-left" style="cursor: pointer;"> <div class="top-tool-left" style="cursor: pointer;">
<select-panel ref="selectPanel" :filter-panel="filterPanel" :panel-data="panelData" :panel-lock="panelLock" :placement="'bottom-start'" <select-panel ref="selectPanel" @refreshStarred="refreshStarred" :filter-panel="filterPanel" :panel-data="panelData" :panel-lock="panelLock" :placement="'bottom-start'"
:show-panel="showPanel" style="display: inline-block;padding: 0" @deletePanel="del" @editPanel="edit" @selectPanel="panelChange"> :show-panel="showPanel" style="display: inline-block;padding: 0" @deletePanel="del" @editPanel="edit" @selectPanel="panelChange">
<template v-slot:header> <template v-slot:header>
<div class="panel-select-header"> <div class="panel-select-header">
@@ -24,7 +24,17 @@
<template v-slot:trigger> <template v-slot:trigger>
<i style="color: #BEBEBE" class="el-icon-menu"></i> <i style="color: #BEBEBE" class="el-icon-menu"></i>
<span :title="showPanel.name + ' (' + showPanel.chartNum +' charts' " class="show-panel-name">{{showPanel.name}}</span> <span :title="showPanel.name + ' (' + showPanel.chartNum +' charts' " class="show-panel-name">{{showPanel.name}}</span>
<i style="font-size: 12px;color: #BEBEBE;" class="nz-icon nz-icon-arrow-down"></i> <el-popover
placement="top-start"
trigger="hover"
:content="$t('tip.addFavorites')"
popper-class="starred-pop"
>
<span slot="reference">
<i @click.stop="delStarred(showPanel)" v-if="showPanel.starred" class="el-rate__icon el-icon-star-on"></i>
<i @click.stop="addStarred(showPanel)" v-else class="el-rate__icon el-icon-star-off"></i>
</span>
</el-popover>
</template> </template>
<template v-slot:tail> <template v-slot:tail>
<div class="panel-select-tail"> <div class="panel-select-tail">
@@ -77,6 +87,9 @@
<el-dropdown-item v-has="'panel_view'"> <el-dropdown-item v-has="'panel_view'">
<div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div> <div id="chart-temp-sync" @click="chartBySync"><i class="nz-icon nz-icon-sync"></i>{{ $t('overall.syncChart') }}</div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-has="'panel_view'">
<div id="chart-export-html" @click="exportType"><i class="nz-icon nz-icon-download1"></i>{{ $t('overall.snapshoot') }}</div>
</el-dropdown-item>
</template> </template>
</top-tool-more-options> </top-tool-more-options>
</div> </div>
@@ -295,6 +308,28 @@ export default {
} }
}, },
methods: { methods: {
// 刷新树形菜单视图
refreshStarred ({ data, type }) {
if (type === 'tree') {
this.panelData = JSON.parse(JSON.stringify(data))
}
this.$nextTick(() => {
this.$refs.selectPanel.$refs.starredTree.filter(this.filterPanel)
this.$refs.selectPanel.$refs.panelTree.filter(this.filterPanel)
this.$refs.selectPanel.$refs.panelTree.setCurrentKey(this.showPanel)
})
// 判断当前页面收藏状态
const starredArr = this.$refs.selectPanel.tempArr
this.showPanel.starred = starredArr.some(item => item.id === this.showPanel.id)
},
// 新增收藏
addStarred (data) {
this.$refs.selectPanel.addStarred(data)
},
// 删除收藏
delStarred (data) {
this.$refs.selectPanel.delStarred(data)
},
// 刷新 // 刷新
refreshPanel () { refreshPanel () {
this.getData(this.filter) this.getData(this.filter)
@@ -355,12 +390,12 @@ export default {
return return
} }
this.rightBox.panel.show = true this.rightBox.panel.show = true
this.$refs.panelBox.show(true) // this.$refs.panelBox.show(true)
this.panel = { this.panel = {
id: '', id: '',
name: '' name: ''
} }
this.$refs.panelBox.setTitle(this.$t('dashboard.panel.createPanelTitle')) // this.$refs.panelBox.setTitle(this.$t('dashboard.panel.createPanelTitle'))
}, },
panelReload (clearShowPanel) { panelReload (clearShowPanel) {
this.getTableData(clearShowPanel) this.getTableData(clearShowPanel)
@@ -637,8 +672,11 @@ export default {
const vm = this const vm = this
this.$get('visual/panel?type=dashboard&pageSize=-1').then(response => { this.$get('visual/panel?type=dashboard&pageSize=-1').then(response => {
if (response.code === 200) { if (response.code === 200) {
this.panelData = JSON.parse(JSON.stringify(response.data.list))
let isInitData = false let isInitData = false
this.panelData = JSON.parse(JSON.stringify(response.data.list))
this.$nextTick(() => {
this.$refs.selectPanel.getStarred('tree')
})
if (response.data.list.length > 0) { if (response.data.list.length > 0) {
if (this.$store.state.showPanel.id > 0 && this.$store.state.showPanel.name) { if (this.$store.state.showPanel.id > 0 && this.$store.state.showPanel.name) {
this.showPanel = JSON.parse(JSON.stringify(this.$store.state.showPanel)) this.showPanel = JSON.parse(JSON.stringify(this.$store.state.showPanel))
@@ -984,3 +1022,15 @@ export default {
} }
} }
</script> </script>
<style scoped>
.el-rate__icon{
color: #C0C4CC !important;
cursor: pointer;
margin-right: 0px;
transform: translateY(1px);
}
.el-icon-star-on{
color:#FF9219 !important;
transform: translateY(1px) scale(1.2);
}
</style>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="main-list main-list--project"> <div class="main-list main-list--project">
<projectList ref="dataList" :class="showList?'projectList':'hide'" v-has="'project_view'"/> <projectList ref="dataList" :class="showList?'projectList':'hide'" v-has="'project_view'"/>
<projectTopo :class="showList?'projectTopo':'projectTopo ml10'" v-has="'project_view'"/> <projectTopo :class="showList?'projectTopo':'projectTopo'" v-has="'project_view'"/>
</div> </div>
</template> </template>

View File

@@ -25,14 +25,46 @@
<div class="tools-header-center"> <div class="tools-header-center">
<el-form size="small" ref="ruleForm" :model="ruleForm" :rules="formRules" label-position="right" label-width="150px"> <el-form size="small" ref="ruleForm" :model="ruleForm" :rules="formRules" label-position="right" label-width="150px">
<el-form-item style="margin-bottom:10px" :label="$t('ping.dcs')"> <el-form-item style="margin-bottom:10px" :label="$t('ping.dcs')">
<el-select v-model="checked" multiple @change="checkedChange" > <!-- <el-select v-model="checked" multiple @change="checkedChange" >-->
<el-option <!-- <el-option-->
:key="item.id" <!-- :key="item.id"-->
v-for="item in dataCenter" <!-- v-for="item in dataCenter"-->
:label="item.name" <!-- :label="item.name"-->
:value="item.id"> <!-- :value="item.id">-->
</el-option> <!-- </el-option>-->
</el-select> <!-- </el-select>-->
<el-popover
placement="bottom"
width="220"
trigger="manual"
v-model="visible"
v-clickoutside="close"
popper-class="no-style-class ping-popover"
>
<el-form-item style="margin-bottom:0px">
<ul class="pop-list-wrap">
<li class="el-dropdown-menu__item">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="checkAllChange">{{$t('overall.all')}}</el-checkbox>
</li>
<ul class="pop-list">
<el-checkbox-group v-model="checked" @change="checkedChange">
<li class="el-dropdown-menu__item" v-for="item in dataCenter" :key="item.id">
<el-checkbox :label="item.id">{{item.name}}</el-checkbox>
</li>
</el-checkbox-group>
</ul>
</ul>
</el-form-item>
<div slot="reference" class="choose-box" @click="triggerVisible">
<div v-if="checkAll" style="flex: 1">All</div>
<div v-else style="flex: 1">
<span class="choose" v-for="item in dataCenter" :key="item.id" v-if="checked.indexOf(item.id) !== -1">
<span> {{item.name}} <i class="nz-icon nz-icon-close" @click="removeCheckedItem(item.id)"/></span>
</span>
</div>
<i class="nz-icon nz-icon-arrow-down6"/>
</div>
</el-popover>
</el-form-item> </el-form-item>
<el-form-item prop="timeout" style="margin-bottom:10px" :label="$t('ping.timeout')"> <el-form-item prop="timeout" style="margin-bottom:10px" :label="$t('ping.timeout')">
<div class="wrap" style="height:32px"> <div class="wrap" style="height:32px">
@@ -78,10 +110,10 @@
<span class="nz-icon nz-icon-edit" slot="icon"></span> <span class="nz-icon nz-icon-edit" slot="icon"></span>
<p class="txt" slot="title">{{$t('overall.placeHolder')}} IP</p> <p class="txt" slot="title">{{$t('overall.placeHolder')}} IP</p>
</el-step> </el-step>
<el-step> <!-- <el-step>-->
<span class="el-icon-more" slot="icon"></span> <!-- <span class="el-icon-more" slot="icon"></span>-->
<p class="txt" slot="title">{{$t('ping.filter')}}</p> <!-- <p class="txt" slot="title">{{$t('ping.filter')}}</p>-->
</el-step> <!-- </el-step>-->
<el-step> <el-step>
<span class="msg" slot="icon">Ping</span> <span class="msg" slot="icon">Ping</span>
<p class="txt" slot="title">Ping {{$t('config.terminallog.cmd.cmd')}}</p> <p class="txt" slot="title">Ping {{$t('config.terminallog.cmd.cmd')}}</p>
@@ -156,7 +188,7 @@ export default {
tableData: [], tableData: [],
ruleForm: { ruleForm: {
// 超时时间 // 超时时间
timeout: '' timeout: 30
}, },
formRules: { formRules: {
timeout: [{ validator: positiveInteger, trigger: 'blur' }] timeout: [{ validator: positiveInteger, trigger: 'blur' }]
@@ -166,6 +198,22 @@ export default {
created () { created () {
this.getDataCenter() this.getDataCenter()
}, },
mounted () {
const tiInput = document.getElementsByClassName('ti-input')[0]
tiInput.addEventListener('click', (e) => {
const event = e || window.event
if (event && event.stopPropagation) {
event.stopPropagation()
} else {
event.cancelBubble = true
}
if (event.path[0].className === 'ti-input') {
const tiInputBox = document.getElementsByClassName('ti-new-tag-input')[0]
console.log(tiInputBox)
tiInputBox.focus()
}
})
},
methods: { methods: {
// 使用防抖是因为,防止标签输入框失去焦点校验和开始任务校验重复(连续两次message提示) // 使用防抖是因为,防止标签输入框失去焦点校验和开始任务校验重复(连续两次message提示)
validateHost: bus.debounce(function () { validateHost: bus.debounce(function () {
@@ -217,6 +265,16 @@ export default {
this.checkAll = checkedCount === this.dataCenter.length this.checkAll = checkedCount === this.dataCenter.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.dataCenter.length this.isIndeterminate = checkedCount > 0 && checkedCount < this.dataCenter.length
}, },
// 删除选中
removeCheckedItem (id, e) {
const event = e || window.event
if (event && event.stopPropagation) {
event.stopPropagation()
} else {
event.cancelBubble = true
}
this.checked = this.checked.filter(dcId => dcId !== id)
},
// 开始任务 // 开始任务
startTask () { startTask () {
if (!this.flag) { if (!this.flag) {

View File

@@ -24,14 +24,46 @@
<div class="tools-header-center"> <div class="tools-header-center">
<el-form size="small" ref="ruleForm" :model="ruleForm" :rules="formRules" label-position="right" label-width="150px"> <el-form size="small" ref="ruleForm" :model="ruleForm" :rules="formRules" label-position="right" label-width="150px">
<el-form-item style="margin-bottom:10px" :label="$t('ping.dcs')"> <el-form-item style="margin-bottom:10px" :label="$t('ping.dcs')">
<el-select v-model="checked" multiple @change="checkedChange" > <!-- <el-select v-model="checked" multiple @change="checkedChange" >-->
<el-option <!-- <el-option-->
:key="item.id" <!-- :key="item.id"-->
v-for="item in dataCenter" <!-- v-for="item in dataCenter"-->
:label="item.name" <!-- :label="item.name"-->
:value="item.id"> <!-- :value="item.id">-->
</el-option> <!-- </el-option>-->
</el-select> <!-- </el-select>-->
<el-popover
placement="bottom"
width="220"
trigger="manual"
v-model="visible"
v-clickoutside="close"
popper-class="no-style-class ping-popover"
>
<el-form-item style="margin-bottom:0px">
<ul class="pop-list-wrap">
<li class="el-dropdown-menu__item">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="checkAllChange">{{$t('overall.all')}}</el-checkbox>
</li>
<ul class="pop-list">
<el-checkbox-group v-model="checked" @change="checkedChange">
<li class="el-dropdown-menu__item" v-for="item in dataCenter" :key="item.id">
<el-checkbox :label="item.id">{{item.name}}</el-checkbox>
</li>
</el-checkbox-group>
</ul>
</ul>
</el-form-item>
<div slot="reference" class="choose-box" @click="triggerVisible">
<div v-if="checkAll" style="flex: 1">All</div>
<div v-else style="width: 100%;flex: 1">
<span class="choose" v-for="item in dataCenter" :key="item.id" v-if="checked.indexOf(item.id) !== -1">
<span> {{item.name}} <i class="nz-icon nz-icon-close" @click="removeCheckedItem(item.id)"/></span>
</span>
</div>
<i class="nz-icon nz-icon-arrow-down6"/>
</div>
</el-popover>
</el-form-item> </el-form-item>
<el-form-item prop="maxHops" style="margin-bottom:10px" :label="$t('trace.maxHops')"> <el-form-item prop="maxHops" style="margin-bottom:10px" :label="$t('trace.maxHops')">
<div class="wrap" style="height:32px"> <div class="wrap" style="height:32px">
@@ -81,10 +113,6 @@
<span class="nz-icon nz-icon-edit" slot="icon"></span> <span class="nz-icon nz-icon-edit" slot="icon"></span>
<p class="txt" slot="title">{{$t('overall.placeHolder')}}IP</p> <p class="txt" slot="title">{{$t('overall.placeHolder')}}IP</p>
</el-step> </el-step>
<el-step>
<span class="el-icon-more" slot="icon"></span>
<p class="txt" slot="title">{{$t('ping.filter')}}</p>
</el-step>
<el-step> <el-step>
<span class="msg" slot="icon">Trace</span> <span class="msg" slot="icon">Trace</span>
<p class="txt" slot="title">Trace {{$t('config.terminallog.cmd.cmd')}}</p> <p class="txt" slot="title">Trace {{$t('config.terminallog.cmd.cmd')}}</p>
@@ -159,7 +187,7 @@ export default {
// 最大跃点数 // 最大跃点数
maxHops: '', maxHops: '',
// 超时时间 // 超时时间
timeout: '' timeout: 30
}, },
formRules: { formRules: {
timeout: [{ validator: positiveInteger, trigger: 'blur' }], timeout: [{ validator: positiveInteger, trigger: 'blur' }],
@@ -170,6 +198,22 @@ export default {
created () { created () {
this.getDataCenter() this.getDataCenter()
}, },
mounted () {
const tiInput = document.getElementsByClassName('ti-input')[0]
tiInput.addEventListener('click', (e) => {
const event = e || window.event
if (event && event.stopPropagation) {
event.stopPropagation()
} else {
event.cancelBubble = true
}
if (event.path[0].className === 'ti-input') {
const tiInputBox = document.getElementsByClassName('ti-new-tag-input')[0]
console.log(tiInputBox)
tiInputBox.focus()
}
})
},
methods: { methods: {
// 使用防抖是因为,防止标签输入框失去焦点校验和开始任务校验重复(连续两次message提示) // 使用防抖是因为,防止标签输入框失去焦点校验和开始任务校验重复(连续两次message提示)
validateHost: bus.debounce(function () { validateHost: bus.debounce(function () {
@@ -221,6 +265,16 @@ export default {
this.checkAll = checkedCount === this.dataCenter.length this.checkAll = checkedCount === this.dataCenter.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.dataCenter.length this.isIndeterminate = checkedCount > 0 && checkedCount < this.dataCenter.length
}, },
// 删除选中
removeCheckedItem (id, e) {
const event = e || window.event
if (event && event.stopPropagation) {
event.stopPropagation()
} else {
event.cancelBubble = true
}
this.checked = this.checked.filter(dcId => dcId !== id)
},
// 开始任务 // 开始任务
startTask () { startTask () {
if (!this.flag) { if (!this.flag) {

View File

@@ -22,7 +22,7 @@ export default {
} }
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) // 获取本地的config.json 判断是否需要清空localStorage 以及设备的宽 和 axios的baseUrl
this.$axios.defaults.baseURL = result.body.baseUrl this.$axios.defaults.baseURL = result.body.baseUrl
const version = result.body.version const version = result.body.version
const defaultWindowWidth = result.body.width || 1024 const defaultWindowWidth = result.body.width || 1024

View File

@@ -50,14 +50,14 @@ Vue.use(vSelectPage, {
}) })
} }
}) })
Vue.use(myDatePicker) Vue.use(myDatePicker) // 对element-ui的时间组件进行二次重构
Vue.component('Pagination', Pagination) Vue.component('Pagination', Pagination) // 公用分页组件
Vue.component('searchInput', searchInput) Vue.component('searchInput', searchInput) // 公用搜索组件
Vue.component('element-set', elementSet) Vue.component('element-set', elementSet) // 公用设置表头
Vue.component('loading', loading) Vue.component('loading', loading)// 公用loading 除特殊情况使用 正常使用自定义指令 v-my-loading
Vue.component('pick-time', pickTime) Vue.component('pick-time', pickTime)// 时间组件 包含刷新 单位 同步等
Vue.component('myDatePicker', myDatePicker) Vue.component('myDatePicker', myDatePicker)
Vue.component('nzDataList', nzDataList) Vue.component('nzDataList', nzDataList) // 公用表格父组件
Vue.component('chartList', chartList) Vue.component('chartList', chartList)
Vue.prototype.$axios = axios Vue.prototype.$axios = axios
@@ -65,11 +65,11 @@ Vue.prototype.$post = post
Vue.prototype.$get = get Vue.prototype.$get = get
Vue.prototype.$put = put Vue.prototype.$put = put
Vue.prototype.$delete = del Vue.prototype.$delete = del
Vue.prototype.$loadsh = loadsh Vue.prototype.$loadsh = loadsh // JavaScript 实用工具库 https://www.lodashjs.com/
Vue.prototype.$CONSTANTS = constants Vue.prototype.$CONSTANTS = constants
Vue.prototype.$TOOLS = tools Vue.prototype.$TOOLS = tools
Vue.prototype.$bottomBoxWindow = bottomBoxWindow // 底部上滑框控制 Vue.prototype.$bottomBoxWindow = bottomBoxWindow // 底部上滑框控制
Vue.prototype.$stringTimeParseToUnix = stringTimeParseToUnix Vue.prototype.$stringTimeParseToUnix = stringTimeParseToUnix // 处理string类型的时间为时间戳 单位s
Vue.prototype.$unixTimeParseToString = unixTimeParseToString Vue.prototype.$unixTimeParseToString = unixTimeParseToString
Vue.prototype.$chartResizeTool = chartResizeTool Vue.prototype.$chartResizeTool = chartResizeTool
Vue.prototype.$tableSet = tableSet Vue.prototype.$tableSet = tableSet
@@ -101,13 +101,13 @@ Vue.mixin({
} }
}, },
computed: { computed: {
timeFormatMain () { timeFormatMain () { // 所有组件添加默认时间格式
return this.$store.getters.getTimeFormatMain return this.$store.getters.getTimeFormatMain
}, },
getMenuList () { getMenuList () { // 所有的菜单权限
return this.$store.state.user.menuList return this.$store.state.user.menuList
}, },
getButtonList () { getButtonList () { // 所有的按钮权限
return this.$store.state.buttonList return this.$store.state.buttonList
}, },
$routePath () { $routePath () {
@@ -115,7 +115,7 @@ Vue.mixin({
} }
}, },
methods: { methods: {
hasButton (code) { hasButton (code) { // 同v-has 主要判断button的权限
return hasButton(this.$store.getters.buttonList, code) return hasButton(this.$store.getters.buttonList, code)
}, },
...mainMixin.methods ...mainMixin.methods

View File

@@ -248,6 +248,32 @@ export default new Vue({
}, delay) }, delay)
} }
}, },
/**
* @desc 防抖函数
* @param {需要防抖的函数} func
* @param {延迟时间} wait
* @param {是否立即执行} immediate
*/
debounceFn (func, wait, immediate) {
let timeout
return function (...args) {
const context = this
if (timeout) clearTimeout(timeout)
if (immediate) {
const callNow = !timeout
timeout = setTimeout(function () {
timeout = null
}, wait)
if (callNow) func.apply(context, args)
} else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait)
}
}
},
UTCTimeToConfigTimezone (utcTime) { UTCTimeToConfigTimezone (utcTime) {
let offset = localStorage.getItem('nz-sys-timezone') let offset = localStorage.getItem('nz-sys-timezone')
offset = moment.tz(offset).format('Z') offset = moment.tz(offset).format('Z')