NEZ-2741 feat:playlist页面开发
This commit is contained in:
@@ -66,21 +66,34 @@
|
||||
}
|
||||
.top-tool-btn-group {
|
||||
display: flex;
|
||||
.top-tool-btn:not(:last-of-type):not(:first-of-type) {
|
||||
border-left: none;
|
||||
border-radius: 0;
|
||||
}
|
||||
.top-tool-btn:first-of-type:not(:last-of-type) {
|
||||
border-right-color: transparent;
|
||||
border-radius: $--button-border-radius 0 0 $--button-border-radius;
|
||||
&:focus+.top-tool-btn{
|
||||
border-left-color: transparent !important;
|
||||
}
|
||||
}
|
||||
.top-tool-btn:not(:last-of-type):not(:first-of-type) {
|
||||
border-right-color: transparent;
|
||||
border-radius: 0;
|
||||
&:focus+.top-tool-btn{
|
||||
border-left-color: transparent !important;
|
||||
}
|
||||
}
|
||||
.top-tool-btn:last-of-type:not(:first-of-type) {
|
||||
border-radius: 0 $--button-border-radius $--button-border-radius 0;
|
||||
border-left: none;
|
||||
}
|
||||
.top-tool-btn {
|
||||
background-color: $--background-color-empty;
|
||||
}
|
||||
}
|
||||
.top-tool-btn-group.playlist{
|
||||
margin-right: 10px;
|
||||
.top-tool-btn.stopPlaylist{
|
||||
width: 92px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
.top-tool-btn {
|
||||
height: 32px;
|
||||
width: 36px;
|
||||
|
||||
@@ -24,22 +24,28 @@
|
||||
.tree--node > span:last-of-type > span > i {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.select-panel-tree {
|
||||
.select-dashboard-tree {
|
||||
height: 350px;
|
||||
overflow: auto;
|
||||
}
|
||||
.select-panel-tree .el-tree-node__content {
|
||||
.select-dashboard-tree .el-tree-node__content {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
}
|
||||
.select-panel-tree .el-tree-node__content:hover {
|
||||
.select-dashboard-tree .el-tree-node__content:hover {
|
||||
color: $--color-primary;
|
||||
}
|
||||
.select-panel-tree .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
|
||||
.select-dashboard-tree .el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
|
||||
background-color: $--background-color-base;
|
||||
font-weight: bold;
|
||||
color: $--color-primary;
|
||||
}
|
||||
.select-dashboard-tree.playlistTree .el-tree-node:focus>.el-tree-node__content{
|
||||
background-color: transparent;
|
||||
}
|
||||
.select-dashboard-tree.playlistTree .el-tree-node>.el-tree-node__content:hover{
|
||||
background-color: $--background-color-base;
|
||||
}
|
||||
.tree--node {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -71,12 +77,12 @@
|
||||
color: #D96D7A;
|
||||
}
|
||||
|
||||
.panel-select-wrap{
|
||||
.dashboard-select-wrap{
|
||||
width: 100%;
|
||||
height: 402px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.panel-select-left{
|
||||
.dashboard-select-left{
|
||||
width: 196px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
@@ -85,9 +91,9 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.panel-select-list{
|
||||
.dashboard-select-list{
|
||||
width: 100%;
|
||||
.panel-select-item{
|
||||
.dashboard-select-item{
|
||||
font-family: Roboto-Regular;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
@@ -106,14 +112,14 @@
|
||||
color: $--color-text-regular;
|
||||
}
|
||||
}
|
||||
.panel-select-item:hover{
|
||||
.dashboard-select-item:hover{
|
||||
color: $--color-primary;
|
||||
background: $--background-color-base;
|
||||
i{
|
||||
color: $--color-primary;
|
||||
}
|
||||
}
|
||||
.panel-select-item.active{
|
||||
.dashboard-select-item.active{
|
||||
color: $--color-primary;
|
||||
background: $--background-color-base;
|
||||
i{
|
||||
@@ -167,9 +173,60 @@
|
||||
flex: 1;
|
||||
width: calc(100% - 196px);
|
||||
padding-top: 0;
|
||||
.panel-select-header{
|
||||
.dashboard-select-header{
|
||||
margin-top: 12px;
|
||||
margin-bottom: 8px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
.el-input{
|
||||
flex: 1;
|
||||
.el-input__inner {
|
||||
border: 1px solid $--button-icon-border-color;
|
||||
}
|
||||
.el-input__inner:hover {
|
||||
border: 1px solid $--button-icon-hover-border-color;
|
||||
}
|
||||
.el-input__inner:focus {
|
||||
border: 1px solid $--button-icon-active-border-color;
|
||||
}
|
||||
}
|
||||
.top-tool-btn {
|
||||
height: 32px;
|
||||
width: 36px;
|
||||
cursor: pointer;
|
||||
border: 1px solid $--button-icon-border-color;
|
||||
outline: none;
|
||||
border-radius: $--button-border-radius;
|
||||
background-color: $--background-color-empty;
|
||||
transition:all .2s;
|
||||
color: $--button-icon-color;
|
||||
i {
|
||||
font-size: 14px;
|
||||
color: $--button-icon-color;
|
||||
}
|
||||
}
|
||||
.top-tool-btn.top-tool-btn--text {
|
||||
padding: 0 8px;
|
||||
width: unset;
|
||||
color: $--color-text-regular;
|
||||
}
|
||||
.top-tool-btn:hover:not(.nz-btn-disabled) {
|
||||
background-color: $--button-icon-hover-background-color;
|
||||
border: 1px solid $--button-icon-hover-border-color;
|
||||
color: $--button-icon-hover-color;
|
||||
i {
|
||||
color: $--button-icon-hover-color;
|
||||
}
|
||||
}
|
||||
.top-tool-btn:focus:not(.nz-btn-disabled), .top-tool-btn.is-focus {
|
||||
background-color: $--button-icon-active-background-color;
|
||||
border: 1px solid $--button-icon-active-border-color !important;
|
||||
color: $--button-icon-active-color;
|
||||
i {
|
||||
color: $--button-icon-active-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.nz-icon-xingzhuang{
|
||||
@@ -185,4 +242,15 @@
|
||||
color:$--color-primary;
|
||||
background: none;
|
||||
}
|
||||
.nz-icon-bofang{
|
||||
color: $--color-text-regular;
|
||||
}
|
||||
}
|
||||
|
||||
.right-box-playlist{
|
||||
.el-input-group__append{
|
||||
background-color: $--right-box-sub-title-background-color;
|
||||
border: 1px solid $--border-color-light;
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,10 @@
|
||||
top: 0px;
|
||||
height: 100%;
|
||||
}
|
||||
.panel-loading{
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.home.se{
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: center center no-repeat $--background-color-empty;
|
||||
z-index: 1010;
|
||||
z-index: 10;
|
||||
}
|
||||
.show-panel-name{
|
||||
display: inline-block;
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,6 +5,41 @@
|
||||
"css_prefix_text": "nz-icon-",
|
||||
"description": "",
|
||||
"glyphs": [
|
||||
{
|
||||
"icon_id": "34816567",
|
||||
"name": "下一播放",
|
||||
"font_class": "xiayibofang",
|
||||
"unicode": "e7dc",
|
||||
"unicode_decimal": 59356
|
||||
},
|
||||
{
|
||||
"icon_id": "34816568",
|
||||
"name": "上一播放",
|
||||
"font_class": "shangyibofang",
|
||||
"unicode": "e7dd",
|
||||
"unicode_decimal": 59357
|
||||
},
|
||||
{
|
||||
"icon_id": "34801441",
|
||||
"name": "播放",
|
||||
"font_class": "bofang",
|
||||
"unicode": "e7da",
|
||||
"unicode_decimal": 59354
|
||||
},
|
||||
{
|
||||
"icon_id": "34801442",
|
||||
"name": "Playlists",
|
||||
"font_class": "Playlists",
|
||||
"unicode": "e7db",
|
||||
"unicode_decimal": 59355
|
||||
},
|
||||
{
|
||||
"icon_id": "34764401",
|
||||
"name": "edit",
|
||||
"font_class": "edit1",
|
||||
"unicode": "e7d9",
|
||||
"unicode_decimal": 59353
|
||||
},
|
||||
{
|
||||
"icon_id": "34724146",
|
||||
"name": "全部展开",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@ import MessageBox from 'element-ui/packages/message-box/src/main'
|
||||
import i18n from '../i18n'
|
||||
import bus from '@/libs/bus'
|
||||
import moment from 'moment-timezone'
|
||||
import loadsh from 'lodash'
|
||||
/* 弹窗点击外部后关闭 */
|
||||
const exceptClassName = ['prevent-clickoutside', 'config-dropdown', 'nz-pop', 'el-picker', 'chart-box-dropdown', 'metric-dropdown', 'el-cascader__dropdown', 'no-style-class', 'el-message-box', 'nz-dashboard-dropdown', 'el-autocomplete-suggestion', 'nz-temp-box', 'el-time-panel', 'el-dropdown-menu', 'el-select-dropdown', 'no-close'] // clickoutside排除的class(白名单) no-style-class:没有任何样式的class
|
||||
export const clickoutside = {
|
||||
@@ -12,9 +13,9 @@ export const clickoutside = {
|
||||
if (!binding.expression) return
|
||||
const unsavedChange = localStorage.getItem('nz-unsaved-change')
|
||||
try {
|
||||
el.__oldValue__ = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
el.__oldData__ = JSON.parse(JSON.stringify(binding.value.oldData))
|
||||
el.__oldValue__ = loadsh.cloneDeep(binding.value.obj)
|
||||
el.__newValue__ = el.__oldValue__
|
||||
el.__oldData__ = loadsh.cloneDeep(binding.value.oldData)
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
@@ -38,7 +39,7 @@ export const clickoutside = {
|
||||
return false
|
||||
}
|
||||
if (el.__oldValue__) {
|
||||
// const newValue = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
// const newValue = loadsh.cloneDeep(binding.value.obj)
|
||||
const oldData = el.__oldData__ || el.__oldValue__
|
||||
if (unsavedChange == 'on' && !isEqual(oldData, el.__newValue__) && !el.isShow) {
|
||||
el.isShow = true
|
||||
@@ -77,7 +78,7 @@ export const clickoutside = {
|
||||
update (el, binding, vnode) {
|
||||
if (binding.arg && binding.arg != 'stable') {
|
||||
if (binding.value.obj.datasource !== '0') {
|
||||
el.__oldValue__ = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
el.__oldValue__ = loadsh.cloneDeep(binding.value.obj)
|
||||
}
|
||||
}
|
||||
el.__newValue__ = binding.value.obj
|
||||
@@ -219,7 +220,7 @@ export const cancelWithChange = {
|
||||
setTimeout(() => {
|
||||
if (!binding.value || !binding.value.obj) return
|
||||
const unsavedChange = localStorage.getItem('nz-unsaved-change')
|
||||
el.__oldValue__ = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
el.__oldValue__ = loadsh.cloneDeep(binding.value.obj)
|
||||
el.__newValue__ = el.__oldValue__
|
||||
function domClick (e) {
|
||||
if (unsavedChange == 'on' && !isEqual(el.__oldValue__, el.__newValue__)) {
|
||||
@@ -242,7 +243,7 @@ export const cancelWithChange = {
|
||||
},
|
||||
update (el, binding, vnode) {
|
||||
if (binding.arg && binding.arg != 'stable') {
|
||||
el.__oldValue__ = JSON.parse(JSON.stringify(binding.value.obj))
|
||||
el.__oldValue__ = loadsh.cloneDeep(binding.value.obj)
|
||||
}
|
||||
el.__newValue__ = binding.value.obj
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<span class="select-refresh-time-label" v-if="interval">{{interLabel}}</span>
|
||||
<i class="nz-icon nz-icon-arrow-down" style="font-size: 12px;"></i>
|
||||
<transition name="el-zoom-in-top">
|
||||
<ul v-show="dropdownShow" class="el-dropdown-menu el-popper el-dropdown-menu--mini nz-dropdown" v-clickoutside="dropdownHandler">
|
||||
<ul v-show="dropdownShow" class="el-dropdown-menu el-popper el-dropdown-menu--mini nz-dropdown popper-z-index" v-clickoutside="dropdownHandler">
|
||||
<li v-for="i in $CONSTANTS.intervalList" :key="i.value + i.label" :style="{color:interval === i.value || interval.value === i.value ? theme.themeColor : ''}" class="el-dropdown-menu__item dropdown-content" @click="selectInterval(i,true)">
|
||||
{{$t(i.label)}}
|
||||
</li>
|
||||
|
||||
121
nezha-fronted/src/components/common/playlist.vue
Normal file
121
nezha-fronted/src/components/common/playlist.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="top-tool-btn-group playlist">
|
||||
<el-tooltip
|
||||
effect="light"
|
||||
placement="bottom"
|
||||
:content="$t('dashboard.previous')">
|
||||
<button class="top-tool-btn previous" @click="goPrevious">
|
||||
<i class="nz-icon nz-icon-shangyibofang"></i>
|
||||
</button>
|
||||
</el-tooltip>
|
||||
<button class="top-tool-btn stopPlaylist" @click="stopPlaylist">{{$t('dashboard.stopPlaylist')}}</button>
|
||||
<el-tooltip
|
||||
effect="light"
|
||||
placement="bottom"
|
||||
:content="$t('dashboard.next')">
|
||||
<button class="top-tool-btn next" @click="goNext">
|
||||
<i class="nz-icon nz-icon-xiayibofang"></i>
|
||||
</button>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'playlist',
|
||||
props: {
|
||||
playlistObj: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dashboardList: [], // 轮播仪表盘列表
|
||||
timer: null,
|
||||
currentIndex: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
playlistObj: {
|
||||
immediate: true,
|
||||
async handler () {
|
||||
this.currentIndex = 0
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
await this.getDashboard()
|
||||
this.startPlay()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 开始轮播
|
||||
async startPlay () {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
this.changePlay()
|
||||
const interval = this.playlistObj.intvl * 60 * 1000
|
||||
this.timer = setInterval(() => {
|
||||
this.currentIndex++
|
||||
if (this.currentIndex === this.playlistObj.dashboardIds.length) {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
this.changePlay()
|
||||
}, interval)
|
||||
},
|
||||
// 上一个
|
||||
goPrevious () {
|
||||
this.currentIndex--
|
||||
if (this.currentIndex === -1) {
|
||||
this.currentIndex = this.playlistObj.dashboardIds.length - 1
|
||||
}
|
||||
this.startPlay()
|
||||
},
|
||||
// 下一个
|
||||
goNext () {
|
||||
this.currentIndex++
|
||||
if (this.currentIndex === this.playlistObj.dashboardIds.length) {
|
||||
this.currentIndex = 0
|
||||
}
|
||||
this.startPlay()
|
||||
},
|
||||
// 停止轮播
|
||||
stopPlaylist () {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
this.$emit('stopPlaylist')
|
||||
},
|
||||
changePlay () {
|
||||
let data = this.dashboardList[this.currentIndex]
|
||||
if (!data) {
|
||||
data = {
|
||||
id: this.playlistObj.dashboardIds[this.currentIndex],
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
this.$emit('changePlay', data)
|
||||
},
|
||||
async getDashboard () {
|
||||
this.dashboardList = []
|
||||
const ids = this.playlistObj.dashboardIds.join(',')
|
||||
const res = await this.$get('visual/dashboard?ids=' + ids)
|
||||
this.playlistObj.dashboardIds.forEach(id => {
|
||||
const findItem = res.data.list.find(item => item.id == id)
|
||||
this.dashboardList.push(findItem)
|
||||
})
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,9 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-popover :placement="placement" popper-class="'nz-pop nz-pop-select-panel right-box-select-top right-public-box-dropdown-top nz-pop-select-panel__dropdown'" transition="slide" v-model="popBox.show" :width="536" :disabled="disabled">
|
||||
<div class="panel-select-wrap">
|
||||
<div class="panel-select-left">
|
||||
<ul class="panel-select-list">
|
||||
<li class="panel-select-item" :class="{active:currentTab===item.value}" v-for="item in tabList" :key="item.value" @click="tabChange(item.value)">
|
||||
<div class="dashboard-select-wrap">
|
||||
<div class="dashboard-select-left">
|
||||
<ul class="dashboard-select-list">
|
||||
<li class="dashboard-select-item" :class="{active:currentTab===item.value}" v-for="item in tabList" :key="item.value" @click="tabChange(item.value)">
|
||||
<i class="nz-icon" :class="item.icon"></i>
|
||||
<span>{{item.name}}</span>
|
||||
</li>
|
||||
@@ -13,11 +14,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="pop-item-wider">
|
||||
<div class="panel-select-header">
|
||||
<el-input id="panel-list-search" v-model="filterPanel" :placeholder="$t('overall.search')" clearable size="small" style="width:316px"></el-input>
|
||||
<div class="dashboard-select-header">
|
||||
<el-input v-model="filterPanel" :placeholder="$t('overall.search')" clearable size="small"></el-input>
|
||||
<button v-has="'main_add'" :title="$t('overall.createChart')" class="top-tool-btn margin-l-10" type="button" @click="addPlaylist" v-if="currentTab==='playlist'">
|
||||
<i class="nz-icon-create-square nz-icon"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- 全部仪表盘 数据 -->
|
||||
<div :class="{'movable': !panelLock}" class="select-panel-tree" v-if="currentTab==='all'">
|
||||
<!-- 全部仪表盘数据(树形结构)-->
|
||||
<div :class="{'movable': !panelLock}" class="select-dashboard-tree" v-if="currentTab==='all'">
|
||||
<el-tree
|
||||
:data="panelData"
|
||||
:draggable="!panelLock"
|
||||
@@ -56,8 +60,8 @@
|
||||
</div>
|
||||
</el-tree>
|
||||
</div>
|
||||
<!-- 我的收藏、我的创建、最近浏览数据 -->
|
||||
<div class="select-panel-tree" v-else>
|
||||
<!-- 我的收藏、我的创建、最近浏览数据、轮播列表(无层级关系) -->
|
||||
<div class="select-dashboard-tree" :class="{'playlistTree':currentTab==='playlist'}" v-else>
|
||||
<el-tree
|
||||
:data="otherData"
|
||||
:expand-on-click-node="false"
|
||||
@@ -68,10 +72,10 @@
|
||||
check-on-click-node
|
||||
check-strictly
|
||||
default-expand-all
|
||||
:highlight-current="true"
|
||||
:highlight-current="currentTab!=='playlist'"
|
||||
node-key="id"
|
||||
ref="otherTree">
|
||||
<div class="tree--node" slot-scope="{ node, data }">
|
||||
<div class="tree--node" slot-scope="{ node, data }" v-if="currentTab!=='playlist'">
|
||||
<HighlightText :queries="filterPanel" :highlightClass="'highlight-keyword'" style="vertical-align: middle" :title="node.label + ' (' + data.chartNum +' charts)' ">{{node.label}}</HighlightText>
|
||||
<el-row class="block-col-2" style="margin-left:10px;margin-right:8px">
|
||||
<el-col>
|
||||
@@ -93,6 +97,28 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<!-- 轮播列表 -->
|
||||
<div class="tree--node" slot-scope="{ node, data }" v-else>
|
||||
<HighlightText :queries="filterPanel" :highlightClass="'highlight-keyword'" style="vertical-align: middle">{{node.label}}</HighlightText>
|
||||
<el-row class="block-col-2" style="margin-left:10px;margin-right:8px">
|
||||
<el-col>
|
||||
<el-dropdown placement="bottom-end" trigger="click" style="margin-right:10px" v-has="['main_edit', 'main_delete']">
|
||||
<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 nz-el-dropdown-menu" slot="dropdown">
|
||||
<el-dropdown-item>
|
||||
<div @click="editPlaylist(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="deletePlaylist(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>
|
||||
<i class="nz-icon nz-icon-bofang" @click.stop="startPlay(data)" :title ="$t('dashboard.startPlaylist')"></i>
|
||||
</template>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
@@ -101,14 +127,20 @@
|
||||
<slot name="trigger"></slot>
|
||||
</div>
|
||||
</el-popover>
|
||||
<transition name="right-box">
|
||||
<playlistBox v-if="playlistVisible" @close="closePlaylist" :obj="playlistObj"></playlistBox>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import bus from '@/libs/bus'
|
||||
import HighlightText from 'vue-text-highlight'
|
||||
import playlistBox from '@/components/common/rightBox/playlistBox'
|
||||
export default {
|
||||
name: 'selectDashboard',
|
||||
components: {
|
||||
HighlightText
|
||||
HighlightText,
|
||||
playlistBox
|
||||
},
|
||||
props: {
|
||||
placement: { type: String },
|
||||
@@ -155,7 +187,8 @@ export default {
|
||||
{ name: this.$t('dashboard.allDashboards'), icon: 'nz-icon-a-leimucuquanbu', value: 'all' },
|
||||
{ name: this.$t('dashboard.starredDashboards'), icon: 'nz-icon-xingzhuang', value: 'starred' },
|
||||
{ name: this.$t('dashboard.createdByYou'), icon: 'nz-icon-wodechuangjian', value: 'create' },
|
||||
{ name: this.$t('dashboard.recentlyViewed'), icon: 'nz-icon-liulanlishi', value: 'browse' }
|
||||
{ name: this.$t('dashboard.recentlyViewed'), icon: 'nz-icon-liulanlishi', value: 'browse' },
|
||||
{ name: this.$t('dashboard.playlist'), icon: 'nz-icon-Playlists', value: 'playlist' }
|
||||
],
|
||||
currentTab: 'all',
|
||||
// 过滤值
|
||||
@@ -163,9 +196,15 @@ export default {
|
||||
// 其他tab的数据(我的收藏、我的创建、最近浏览数据)
|
||||
otherData: [],
|
||||
// 收藏列表
|
||||
starredList: []
|
||||
starredList: [],
|
||||
playlist: [],
|
||||
playlistVisible: false,
|
||||
playlistObj: {}
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getPlaylist()
|
||||
},
|
||||
methods: {
|
||||
// 左侧tab点击
|
||||
tabChange (value) {
|
||||
@@ -178,12 +217,17 @@ export default {
|
||||
// 设置树形菜单数据
|
||||
setData (type = this.currentTab) {
|
||||
const userId = localStorage.getItem('nz-user-id')
|
||||
if (type === 'starred') { // 我的收藏
|
||||
switch (type) {
|
||||
case 'starred': { // 我的收藏
|
||||
this.otherData = JSON.parse(JSON.stringify(this.starredList))
|
||||
} else if (type === 'create') { // 我的创建
|
||||
break
|
||||
}
|
||||
case 'create': { // 我的创建
|
||||
const flatArr = this.flatten(this.panelData)
|
||||
this.otherData = flatArr.filter(item => item.createBy == userId)
|
||||
} else if (type === 'browse') { // 最近浏览
|
||||
break
|
||||
}
|
||||
case 'browse': { // 最近浏览
|
||||
const browseArr = JSON.parse(localStorage.getItem(`nz-view-dashboard-${userId}`) || '[]')
|
||||
const flatArr = this.flatten(this.panelData)
|
||||
const tempArr = []
|
||||
@@ -196,6 +240,12 @@ export default {
|
||||
})
|
||||
})
|
||||
this.otherData = JSON.parse(JSON.stringify(tempArr))
|
||||
break
|
||||
}
|
||||
case 'playlist': {
|
||||
this.otherData = JSON.parse(JSON.stringify(this.playlist))
|
||||
break
|
||||
}
|
||||
}
|
||||
// 设置当前面板高亮 以及保持搜索状态
|
||||
this.$nextTick(() => {
|
||||
@@ -208,6 +258,68 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
startPlay (val) {
|
||||
const data = this.$loadsh.cloneDeep(val)
|
||||
data.dashboardIds = JSON.parse(data.dashboardIds)
|
||||
if (data.dashboardIds.length) {
|
||||
this.esc()
|
||||
this.$emit('startPlay', data)
|
||||
} else {
|
||||
this.$message.error(this.$t('PLAYLIST_DASHBOARD_IDS_ISNULL'))
|
||||
}
|
||||
},
|
||||
async getPlaylist () {
|
||||
const res = await this.$get('/visual/playlist', { pageSize: -1 })
|
||||
this.playlist = res.data.list
|
||||
this.setData()
|
||||
},
|
||||
addPlaylist () {
|
||||
this.esc()
|
||||
this.playlistObj = {
|
||||
name: '',
|
||||
intvl: undefined,
|
||||
dashboardIds: []
|
||||
}
|
||||
this.playlistVisible = true
|
||||
},
|
||||
async editPlaylist (data) {
|
||||
this.esc()
|
||||
const res = await this.$get('/visual/playlist/' + data.id)
|
||||
this.playlistObj = {
|
||||
id: res.data.id,
|
||||
name: res.data.name,
|
||||
intvl: res.data.intvl,
|
||||
dashboardIds: res.data.dashboardIds
|
||||
}
|
||||
this.playlistObj.dashboardIds = JSON.parse(this.playlistObj.dashboardIds)
|
||||
this.playlistVisible = true
|
||||
},
|
||||
async deletePlaylist (data) {
|
||||
this.$confirm(this.$t('tip.confirmDelete'), {
|
||||
confirmButtonText: this.$t('tip.yes'),
|
||||
cancelButtonText: this.$t('tip.no'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$delete('/visual/playlist?ids=' + data.id).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.$message({
|
||||
duration: 1000,
|
||||
type: 'success',
|
||||
message: this.$t('tip.deleteSuccess')
|
||||
})
|
||||
this.getPlaylist(true)
|
||||
} else {
|
||||
this.$message.error(response.msg)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
closePlaylist (refresh) {
|
||||
this.playlistVisible = false
|
||||
if (refresh) {
|
||||
this.getPlaylist()
|
||||
}
|
||||
},
|
||||
// 获取收藏的列表
|
||||
async getStarred () {
|
||||
// 1: 已收藏 0:未收藏
|
||||
@@ -359,7 +471,8 @@ export default {
|
||||
},
|
||||
// 确认选择某个节点,与父组件交互
|
||||
selectDashboard (data, checked, child) {
|
||||
this.$emit('selectDashboard', data)
|
||||
if (this.currentTab === 'playlist') return
|
||||
this.$emit('selectDashboard', data, 'select')
|
||||
if (this.currentTab === 'all') {
|
||||
this.$refs.panelTree && this.$refs.panelTree.setCurrentKey(data)
|
||||
} else {
|
||||
|
||||
181
nezha-fronted/src/components/common/rightBox/playlistBox.vue
Normal file
181
nezha-fronted/src/components/common/rightBox/playlistBox.vue
Normal file
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<div v-clickoutside="{obj: editPlaylist, func: esc}" class="right-box right-box-playlist">
|
||||
<div class="right-box__header">
|
||||
<div class="header__title">{{editPlaylist.id ? $t('dashboard.editPlaylist') : $t('dashboard.createPlaylist')}}</div>
|
||||
<div class="header__operation">
|
||||
<span v-cancel="{obj: editPlaylist, func: esc}"><i class="nz-icon nz-icon-close" :title="$t('overall.close')"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box__container">
|
||||
<div class="container__form">
|
||||
<el-form ref="form" :model="editPlaylist" :rules="rules" label-position="top" label-width="120px">
|
||||
<!--name-->
|
||||
<el-form-item :label="$t('overall.name')" prop="name">
|
||||
<el-input maxlength="64" show-word-limit v-model="editPlaylist.name" size="small" type="text"></el-input>
|
||||
</el-form-item>
|
||||
<!-- interval -->
|
||||
<el-form-item
|
||||
:label="$t('dashboard.interval')"
|
||||
prop="intvl"
|
||||
>
|
||||
<div class="el-input-group el-input-group--append">
|
||||
<el-input-number
|
||||
style="width:100%"
|
||||
size="small"
|
||||
:controls="false"
|
||||
:min="1"
|
||||
v-model="editPlaylist.intvl">
|
||||
</el-input-number>
|
||||
<div class="el-input-group__append" style="text-transform:capitalize;">{{$t('config.system.basic.minute')}}</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- dashboardIds -->
|
||||
<el-form-item
|
||||
:label="$t('dashboard.title')"
|
||||
prop="dashboardIds"
|
||||
>
|
||||
<el-select
|
||||
v-model="editPlaylist.dashboardIds"
|
||||
multiple
|
||||
:placeholder="$t('el.select.placeholder')"
|
||||
popper-class="right-box-select-top prevent-clickoutside"
|
||||
size="small"
|
||||
style="width:100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in dashboardList"
|
||||
:key="item.id"
|
||||
:label="$t(item.name)"
|
||||
:value="item.id"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-box__footer">
|
||||
<button id="asset-edit-cancel" v-cancel="{obj: editPlaylist, func: esc}" class="footer__btn footer__btn--light">
|
||||
<span>{{$t('overall.cancel')}}</span>
|
||||
</button>
|
||||
<button id="asset-edit-save" :class="{'footer__btn--disabled': prevent_opt.save}" :disabled="prevent_opt.save" class="footer__btn" @click="save">
|
||||
<span>{{$t('overall.save')}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import editRigthBox from '../mixin/editRigthBox'
|
||||
export default {
|
||||
name: 'playlistBox',
|
||||
props: {
|
||||
obj: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
mixins: [editRigthBox],
|
||||
data () {
|
||||
return {
|
||||
url: '/visual/playlist',
|
||||
editPlaylist: {
|
||||
name: '',
|
||||
intvl: undefined,
|
||||
dashboardIds: []
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
intvl: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
],
|
||||
dashboardIds: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
]
|
||||
},
|
||||
dashboardList: []
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getDashboard()
|
||||
},
|
||||
methods: {
|
||||
clickOutside () {
|
||||
this.esc(false)
|
||||
},
|
||||
/* 关闭弹框 */
|
||||
esc (refresh) {
|
||||
this.prevent_opt.save = false
|
||||
this.$emit('close', refresh)
|
||||
},
|
||||
async getDashboard () {
|
||||
const res = await this.$get('visual/dashboard?type=dashboard&pageSize=-1')
|
||||
this.dashboardList = this.flatten(res.data.list)
|
||||
},
|
||||
// 数组对象扁平化
|
||||
flatten (arr) {
|
||||
const tempArr = this.$loadsh.cloneDeep(arr)
|
||||
// 递归调用
|
||||
function handler (tempArr) {
|
||||
const newArr = []
|
||||
tempArr.forEach(element => {
|
||||
newArr.push(element)
|
||||
if (element.children) {
|
||||
newArr.push.apply(newArr, handler(element.children))
|
||||
delete element.children
|
||||
}
|
||||
})
|
||||
return newArr
|
||||
}
|
||||
return handler(tempArr)
|
||||
},
|
||||
save () {
|
||||
if (this.prevent_opt.save) {
|
||||
return
|
||||
}
|
||||
this.prevent_opt.save = true
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
const params = {
|
||||
...this.editPlaylist
|
||||
}
|
||||
if (this.editPlaylist.id) {
|
||||
this.$put(this.url, params).then(res => {
|
||||
this.prevent_opt.save = false
|
||||
if (res.code === 200) {
|
||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||
this.esc(true)
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$post(this.url, params).then(res => {
|
||||
this.prevent_opt.save = false
|
||||
if (res.code === 200) {
|
||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
|
||||
this.esc(true)
|
||||
} else {
|
||||
this.$message.error(res.msg)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.prevent_opt.save = false
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
obj: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler (n) {
|
||||
this.isEdit = true
|
||||
this.editPlaylist = this.$loadsh.cloneDeep(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -7,7 +7,7 @@
|
||||
</transition>
|
||||
</div>
|
||||
<div class="main-container">
|
||||
<div class="top-tools panel-top-tools" :class="showTopLine? 'panel-top-tools-bottom' : ''" style="z-index: 1001;">
|
||||
<div class="top-tools panel-top-tools" :class="showTopLine? 'panel-top-tools-bottom' : ''">
|
||||
<div v-if="panelData.length === 0" class="top-tool-left" style="margin-left: 10px;">
|
||||
<button id="dashboard-add-panel" class="nz-btn nz-btn-style-light nz-btn-size-small" v-has="'main_add'" @click="toAdd"><i class="nz-icon nz-icon-create-square"></i> {{$t("overall.addDashboard")}}</button>
|
||||
</div>
|
||||
@@ -22,10 +22,12 @@
|
||||
style="display: inline-block;padding: 0"
|
||||
@deletePanel="del"
|
||||
@editPanel="edit"
|
||||
@selectDashboard="panelChange">
|
||||
@selectDashboard="panelChange"
|
||||
@startPlay="startPlay"
|
||||
>
|
||||
<template v-slot:trigger>
|
||||
<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 || 0) +' charts)' " class="show-panel-name">{{showPanel.name||$t('overall.notFound')}}</span>
|
||||
<i @click.stop="delStarred(showPanel)" v-if="showPanel.starred===1" class="nz-icon nz-icon-a-xingzhuang2" :title ="$t('overall.starred')"></i>
|
||||
<i @click.stop="addStarred(showPanel)" v-else class="nz-icon nz-icon-xingzhuang" :title ="$t('overall.unstarred')"></i>
|
||||
</template>
|
||||
@@ -43,6 +45,8 @@
|
||||
</div>
|
||||
|
||||
<div class="top-tool-right">
|
||||
<!-- 仪表盘轮播 -->
|
||||
<playlist v-if="playListControls" :playlistObj="playlistObj" @stopPlaylist="stopPlaylist" @changePlay="panelChange"></playlist>
|
||||
|
||||
<pick-time id="panel" ref="pickTime" v-model="searchTime" :refresh-data-func="dateChange" :use-chart-unit="false" class="margin-r-10" :sign="showPanel.id" :from="fromRoute.dashboard"></pick-time>
|
||||
|
||||
@@ -79,12 +83,6 @@
|
||||
</el-dropdown-item>
|
||||
</template>
|
||||
<template v-slot:after>
|
||||
<!-- <el-dropdown-item v-has="'main_add'">
|
||||
<div id="chart-temp-add" @click="addChartByTemp"><i class="nz-icon nz-icon-add"></i>{{$t('overall.AddByTemplate')}}</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-has="'main_edit'">
|
||||
<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 v-has="'dashboard_view'">
|
||||
<div id="chart-export-html" @click="exportType"><i class="nz-icon nz-icon-kuaizhao"></i>{{ $t('overall.snapshoot') }}</div>
|
||||
</el-dropdown-item>
|
||||
@@ -172,6 +170,7 @@ import exportHtmlMixin from '@/components/common/mixin/exportHtml'
|
||||
import panelVariables from '@/components/common/panel/panelVariables'
|
||||
import snapshotProgress from '@/components/common/snapshotProgress/snapshotProgress.vue'
|
||||
import dashboardTempBox from '@/components/common/rightBox/dashboardTempBox'
|
||||
import playlist from '@/components/common/playlist'
|
||||
// import FileSaver from 'file-saver'
|
||||
// import chartData from './testData'
|
||||
export default {
|
||||
@@ -347,7 +346,9 @@ export default {
|
||||
{ value: 300, label: '5m' },
|
||||
{ value: 900, label: '15m' },
|
||||
{ value: 1800, label: '30m' }
|
||||
]
|
||||
],
|
||||
playListControls: false, // 显示隐藏轮播按钮
|
||||
playlistObj: {} // 轮播仪表盘配置
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -359,7 +360,8 @@ export default {
|
||||
chartRightBox,
|
||||
panelVariables, // 处理panel变量的组件
|
||||
snapshotProgress, // 快照进度
|
||||
dashboardTempBox // dashboard模板
|
||||
dashboardTempBox, // dashboard模板
|
||||
playlist
|
||||
},
|
||||
computed: {
|
||||
chartRightBoxShow () {
|
||||
@@ -373,6 +375,16 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 开始轮播列表
|
||||
startPlay (data) {
|
||||
this.playListControls = true
|
||||
this.playlistObj = data
|
||||
},
|
||||
// 结束轮播列表
|
||||
stopPlaylist () {
|
||||
this.playListControls = false
|
||||
this.playlistObj = {}
|
||||
},
|
||||
closeDashboardTempBox (refresh) {
|
||||
this.rightBox.dashboardTemp.show = false
|
||||
if (refresh) {
|
||||
@@ -404,7 +416,7 @@ export default {
|
||||
cancelButtonText: this.$t('tip.no'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$delete('visual/dashboard?ids=' + u.id).then(async (response) => {
|
||||
this.$delete('visual/dashboard?ids=' + u.id).then((response) => {
|
||||
if (response.code === 200) {
|
||||
this.$message({
|
||||
duration: 1000,
|
||||
@@ -416,6 +428,7 @@ export default {
|
||||
const param = { t: +new Date() }
|
||||
const path = this.fromRoute.dashboard
|
||||
this.updatePath(param, path)
|
||||
this.stopPlaylist()
|
||||
this.getTableData(true)
|
||||
} else {
|
||||
this.getTableData(false)
|
||||
@@ -709,10 +722,13 @@ export default {
|
||||
},
|
||||
|
||||
// 面板相关操作
|
||||
panelChange (val) {
|
||||
panelChange (val, type) {
|
||||
if (!val) {
|
||||
return false
|
||||
}
|
||||
if (type === 'select') { // 选择面板 则停止仪表盘轮播
|
||||
this.stopPlaylist()
|
||||
}
|
||||
// 切换面板 重置参数
|
||||
const param = {
|
||||
dashboardId: val.id
|
||||
|
||||
Reference in New Issue
Block a user