feat:notebook列表页面 二级页面查看功能完成

This commit is contained in:
zyh
2023-09-19 18:05:37 +08:00
parent 8073443e92
commit 4b5ada2404
45 changed files with 2115 additions and 388 deletions

View File

@@ -754,6 +754,7 @@
}
.opacityItem{
opacity: 0;
pointer-events: none;
}
.hiddenItem{
box-shadow: $--chart-shadow;
@@ -873,3 +874,47 @@
height: auto !important;
}
}
.noteboook-chart-addWrap{
position: absolute;
top:-20px;
bottom: -20px;
width: 20px;
left: -20px;
visibility: hidden;
&:hover{
visibility: visible;
}
.noteboook-chart-add{
right: 5px;
cursor: pointer;
position: absolute;
font-size: 18px;
color: $--color-text-secondary;
&:hover{
color: $--color-primary;
}
&.addBefore{
top: 20px;
transform: translateY(-50%);
}
&.addAfter{
bottom: 20px;
transform: translateY(50%);
}
}
}
.notebook-detail{
.chart-header:hover{
background: transparent !important;
}
}
.panel-chart-notebook{
&:hover{
border-color: $--color-primary;
.noteboook-chart-addWrap{
visibility: visible;
}
}
}

View File

@@ -131,6 +131,7 @@
@import './page/tool/trace.scss';
@import './page/integration/integration.scss';
@import './page/softwareType/softwareType.scss';
@import './page/notebook/notebook.scss';
@import './common/v-selectpagenew/selectpage.scss';
@import './common/selectTable.scss';

View File

@@ -0,0 +1,154 @@
.notebook{
.nz-detail-view-left{
.author-avatar{
width: 20px;
height: 20px;
display: inline-block;
text-align: center;
line-height: 20px;
background: rgba(60,146,241,0.1);
font-size: 12px;
color: #3C92F1;
letter-spacing: 0;
font-weight: 500;
text-transform: capitalize;
border-radius: 100%;
}
.alert-label-header-circle{
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
background: #ECF5FE !important;
font-size: 12px;
color: #3C92F1;
}
.alert-label-box{
.alert-label-title{
min-width: 140px;
}
}
}
.notebook-detail{
.sub-container>.nz-table-list{
height: 100%;
padding: 0 !important;
}
.top-tool-right{
.nz-btn-size-normal{
height: 32px;
line-height: 32px;
margin-right: 10px;
}
}
.notebook-scrollWrap{
width: 100%;
height: 100%;
overflow: hidden scroll;
position: relative;
}
.notebook-content{
width: 100%;
max-width: 1200px;
margin: auto;
&>:not(.notebook-list){
width: calc(100% - 40px);
margin-left: 20px;
margin-right: 20px;
}
}
.notebook-title{
box-sizing: border-box;
margin-top: 30px;
padding-bottom: 20px;
font-family: Roboto-Medium;
font-size: 24px;
color: $--color-text-primary;
letter-spacing: 0;
font-weight: 500;
line-height: 28px;
border-bottom: 1px solid $--border-color-light;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.notebook-title-input{
box-sizing: border-box;
margin-top: 30px;
.el-input__inner{
height: 46px;
font-family: Roboto-Medium;
font-size: 24px;
color: $--color-text-primary;
letter-spacing: 0;
font-weight: 500;
line-height: 46px;
}
}
.notebook-list{
height: auto;
.panel-chart.my-loading-parent--relative{
height: 100% !important;
}
.no-data{
text-align: center;
position: absolute;
left: 0;
right: 0;
top: 50%;
margin-top: -54px;
.no-data-div {
color: $--color-text-regular;
}
}
}
.notebook-add{
padding-bottom: 60px;
.notebook-add-title{
margin-bottom: 10px;
font-family: Roboto-Regular;
font-size: 14px;
color: $--color-text-primary;
font-weight: 400;
}
.notebook-add-list{
display: grid;
grid-gap:10px;
grid-template-columns:repeat(auto-fill, minmax(172px, 1fr));
}
.notebook-add-item{
min-width: 172px;
height: 62px;
border: 1px solid $--border-color-light;
border-radius: 4px;
padding: 0 20px;
box-sizing: border-box;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
&:hover{
background: #FFFBF5;
border: 1px solid rgba(250,144,28,0.49);
box-shadow: 0px 1px 4px 0px rgba(250,144,28,0.13);
}
.notebook-chart-icon{
width: 24px;
margin-right: 12px;
}
span{
font-size: 14px;
color: $--color-text-primary;
}
}
.notebook-add-show{
font-family: Roboto-Regular;
font-size: 14px;
color: #FA901C;
font-weight: 400;
margin-top: 16px;
cursor: pointer;
}
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,132 @@
"css_prefix_text": "nz-icon-",
"description": "",
"glyphs": [
{
"icon_id": "37390892",
"name": "Doughnut chart",
"font_class": "a-Doughnutchart",
"unicode": "e801",
"unicode_decimal": 59393
},
{
"icon_id": "37390891",
"name": "Bar_chart",
"font_class": "Bar_chart",
"unicode": "e802",
"unicode_decimal": 59394
},
{
"icon_id": "37390899",
"name": "Area charts",
"font_class": "a-Areacharts",
"unicode": "e7f2",
"unicode_decimal": 59378
},
{
"icon_id": "37390905",
"name": "Rose chart",
"font_class": "a-Rosechart",
"unicode": "e7f5",
"unicode_decimal": 59381
},
{
"icon_id": "37390903",
"name": "Point",
"font_class": "Point",
"unicode": "e7f6",
"unicode_decimal": 59382
},
{
"icon_id": "37390904",
"name": "Table",
"font_class": "Table",
"unicode": "e7f7",
"unicode_decimal": 59383
},
{
"icon_id": "37390902",
"name": "hexagon",
"font_class": "hexagon",
"unicode": "e7f8",
"unicode_decimal": 59384
},
{
"icon_id": "37390901",
"name": "text",
"font_class": "text2",
"unicode": "e7f9",
"unicode_decimal": 59385
},
{
"icon_id": "37390900",
"name": "rank",
"font_class": "rank1",
"unicode": "e7fa",
"unicode_decimal": 59386
},
{
"icon_id": "37390898",
"name": "Stat",
"font_class": "Stat",
"unicode": "e7fb",
"unicode_decimal": 59387
},
{
"icon_id": "37390897",
"name": "Sankey",
"font_class": "Sankey",
"unicode": "e7fc",
"unicode_decimal": 59388
},
{
"icon_id": "37390893",
"name": "Bubble",
"font_class": "Bubble",
"unicode": "e7fd",
"unicode_decimal": 59389
},
{
"icon_id": "37390895",
"name": "Pie chat",
"font_class": "a-Piechat",
"unicode": "e7fe",
"unicode_decimal": 59390
},
{
"icon_id": "37390896",
"name": "Guage",
"font_class": "Guage",
"unicode": "e7ff",
"unicode_decimal": 59391
},
{
"icon_id": "37390894",
"name": "funnel",
"font_class": "funnel1",
"unicode": "e800",
"unicode_decimal": 59392
},
{
"icon_id": "37390907",
"name": "line_chart",
"font_class": "line_chart",
"unicode": "e7f3",
"unicode_decimal": 59379
},
{
"icon_id": "37390906",
"name": "Treemap",
"font_class": "Treemap",
"unicode": "e7f4",
"unicode_decimal": 59380
},
{
"icon_id": "37300939",
"name": "外链",
"font_class": "wailian",
"unicode": "e7f1",
"unicode_decimal": 59377
},
{
"icon_id": "37041244",
"name": "Show all series",

File diff suppressed because one or more lines are too long

View File

@@ -184,7 +184,6 @@ export default {
const styleOption = this.$lodash.get(this.chartInfo, 'param.option', {})
chartOption.series.forEach(item => {
console.log(item.lineStyle)
if (item.lineStyle && styleOption.lineWidth != undefined) {
item.lineStyle.width = styleOption.lineWidth
} else if (item.lineStyle) {

View File

@@ -58,6 +58,7 @@
<i class="nz-icon nz-icon-info-normal tool__icon"></i>
</el-tooltip>
</span>
<template v-if="from!=='notebook'">
<span v-if="chartInfo.type=='group'&&!chartInfo.repeatIndex&&from!=='integration'" class="chart-header__tool" @click="addChartGroup">
<!-- <el-tooltip :content="$t('button.add')" effect="light" placement="top" > -->
<i class="nz-icon nz-icon-plus tool__icon" :title="$t('tip.add')"></i>
@@ -97,6 +98,18 @@
</ul>
</el-dropdown>
</span>
</template>
<template v-else-if="notebookEdit">
<span class="chart-header__tool" @click="duplicate">
<i class="nz-icon nz-icon-override" style="font-size: 16px;"></i>
</span>
<span class="chart-header__tool" @click="removeChart">
<i class="nz-icon nz-icon-delete" style="font-size: 16px;"></i>
</span>
<span class="chart-header__tool" @click="editChart">
<i class="nz-icon nz-icon-edit" style="font-size: 16px;"></i>
</span>
</template>
</div>
</div>
</template>

View File

@@ -124,6 +124,9 @@ export default {
}
this.chartInfo.modifiedName = str
return str
},
notebookEdit () { // 是否是编辑状态
return this.$store.getters.getNotebookEdit
}
},
watch: {

View File

@@ -829,7 +829,7 @@ export default {
...item,
i: item.id,
w: item.span,
h: height || 4,
h: height || 2,
x: item.x || 0,
y: item.y || 0,
param

View File

@@ -5,8 +5,8 @@ const data = {
name: '',
dashboardId: 1244,
groupId: undefined,
span: 4,
height: 4,
span: 6,
height: 2,
updateBy: 381,
updateAt: '2021-12-23 03:49:51',
type: 'line',

View File

@@ -5,8 +5,8 @@ const data = {
name: '',
dashboardId: 1244,
groupId: 0,
span: 4,
height: 4,
span: 6,
height: 2,
updateBy: 381,
updateAt: '2021-12-23 03:49:51',
type: 'line',

View File

@@ -4,8 +4,8 @@ const TableData = {
loaded: true,
dashboardId: 1479,
groupId: 0,
span: 4.0,
height: 3.0,
span: 6.0,
height: 2.0,
updateBy: 1,
updateAt: '2021-12-14 03:24:25',
type: 'table',

View File

@@ -25,7 +25,9 @@ export default {
}
},
mounted () {
if (this.editData) {
this.text = this.editData
}
if (this.language == 'en') {
VueMarkdownEditor.lang.use('en-US', enUS)
} else {

View File

@@ -1,6 +1,14 @@
<template>
<!-- chart外层箱子 -->
<div :class="{'panel-chart--fullscreen': isFullscreen}" class="panel-chart" :id="isFullscreen ? ('chart-screen-' + chartInfo.id ) : ('chart-local-' + chartInfo.id)" v-my-loading="loading">
<div
:class="{
'panel-chart--fullscreen': isFullscreen,
'panel-chart-notebook':from==='notebook'&&notebookEdit&&!isExportHtml
}"
class="panel-chart"
:id="isFullscreen ? ('chart-screen-' + chartInfo.id ) : ('chart-local-' + chartInfo.id)"
v-my-loading="loading"
>
<!-- title和工具栏支持浮动 -->
<chart-header
v-if="!isFullscreen&&showHeader"
@@ -23,7 +31,7 @@
@groupShow="groupShow"
@showFullscreen="showFullscreen"
></chart-header>
<!-- 全屏的header-->
<!-- 全屏的header -->
<chart-screen-header
v-if="isFullscreen"
:is-group="isGroup(chartInfo.type)"
@@ -63,6 +71,18 @@
:showAllData="showAllData"
v-if="(!isGroup(chartInfo.type) || !chartInfo.param.collapse) && snapshotShow"
></chart>
<div class="noteboook-chart-addWrap" v-if="from==='notebook'&&!isExportHtml">
<el-tooltip :content="$t('notebook.addchart')" effect="light" placement="bottom">
<div class="noteboook-chart-add addBefore">
<i class="nz-icon nz-icon-plus" @click="addNotebook({position:'before',y:chartInfo.y})"></i>
</div>
</el-tooltip>
<el-tooltip :content="$t('notebook.addchart')" effect="light" placement="top">
<div class="noteboook-chart-add addAfter">
<i class="nz-icon nz-icon-plus" @click="addNotebook({position:'after',y:chartInfo.y})"></i>
</div>
</el-tooltip>
</div>
</div>
</template>
@@ -148,10 +168,16 @@ export default {
},
variablesArr () {
return this.$store.getters.getVariablesArr
},
notebookEdit () { // 是否是编辑状态
return this.$store.getters.getNotebookEdit
}
},
methods: {
isGroup,
addNotebook (position) {
bus.$emit('addNotebook', position)
},
variablesHandle (searchTime) {
this.setGlobalVariablesValue(searchTime)
this.myVariables = []
@@ -524,7 +550,7 @@ export default {
this.chartData = [this.chartInfo.param.topo]
}
if (isRefresh) {
let dom = this.$refs.chart.$refs['chart' + this.chartInfo.id]
const dom = this.$refs.chart.$refs['chart' + this.chartInfo.id]
if (dom) {
dom.refresh([startTime, endTime])
}

View File

@@ -24,6 +24,19 @@
</div>
</div>
</template>
<!-- notebook info -->
<template v-else-if="type === 'notebook'">
<div class="alert-label-header-title">
<div
class="alert-label-header-circle"
>
{{alertLabelData && alertLabelData.createUser ? alertLabelData.createUser.name.substr(0, 1) : "-" }}
</div>
<div class="alert-label-header-name">
{{alertLabelData && alertLabelData.name ? alertLabelData.name : "--"}}
</div>
</div>
</template>
<template v-else>
<div class="alert-label-header-title">
<div
@@ -710,6 +723,35 @@
</div>
</div>
</div>
<!-- type === 'user' -->
<div class="alert-label-info" v-if="type === 'notebook'" v-my-loading="loading">
<div class="alert-label-box">
<div class="alert-label-title">ID</div>
<div class="alert-label-value">
{{ alertLabelData && alertLabelData.id ? alertLabelData.id : "--" }}
</div>
</div>
<div class="alert-label-box name-labe document-copy-block">
<div class="alert-label-title">{{$t('overall.name')}}</div>
<div class="alert-label-value document-copy-text">
{{ alertLabelData && alertLabelData.name ? alertLabelData.name : "--" }}
</div>
<i v-if="alertLabelData && alertLabelData.name" class="nz-icon nz-icon-override" style="visibility: hidden" @click.stop="onCopy(alertLabelData.name)" :title="$t('overall.copyText')"></i>
</div>
<div class="alert-label-box">
<div class="alert-label-title">{{$t('notebook.author')}}</div>
<div class="alert-label-value">
{{ alertLabelData && alertLabelData.createUser ? alertLabelData.createUser.name : "--" }}
</div>
</div>
<div class="alert-label-box">
<div class="alert-label-title">{{$t('notebook.modifiedTime')}}</div>
<div class="alert-label-value">
{{ alertLabelData && alertLabelData.uts ? momentTz(alertLabelData.uts) : "--" }}
</div>
</div>
</div>
</div>
</template>
@@ -901,6 +943,10 @@ export default {
this.loading = false
this.alertLabelData = this.that
}
if (this.type === 'notebook') {
this.loading = false
this.alertLabelData = this.that
}
const weekDays = this.getWeeksTime()
if (this.trendTimer) {
clearTimeout(this.trendTimer)

View File

@@ -80,12 +80,15 @@
<!-- <issueTab v-if="from === fromRoute.issue && targetTab === 'issue'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertSilence" @changeTab="changeTab" :targetTab.sync="targetTab"></issueTab> -->
<!--Discovery Tab-->
<discovery-tab v-if="from === fromRoute.assetDiscovery && targetTab === 'assetDiscoveryTab'" :from="from" :obj="obj" :tabs="tabs.discovery" @changeTab="changeTab" :targetTab.sync="targetTab"></discovery-tab>
<!-- notebook Tab -->
<notebook-tab @getTableData="getTableData" v-if="from === fromRoute.notebook && targetTab === 'notebookTab'" :from="from" :obj="obj" :tabs="tabs.notebook" @changeTab="changeTab" :targetTab.sync="targetTab"></notebook-tab>
</div>
</div>
</div>
</template>
<script>
import routerPathParams from '@/components/common/mixin/routerPathParams'
import cabinetTab from './tabs/cabinetTab'
import alertMessageTab from './tabs/alertMessageTab'
import alertMessageTabNew from './tabs/alertMessageTabNew'
@@ -116,7 +119,7 @@ import rolesTab from '@/components/common/bottomBox/tabs/rolesTab'
import discoveryTab from '@/components/common/bottomBox/tabs/discoveryTab'
import IpDetails from '@/components/common/bottomBox/tabs/IpDetails'
import recordRuleEvalLog from '@/components/common/bottomBox/tabs/recordRuleEvalLog'
import routerPathParams from '@/components/common/mixin/routerPathParams'
import notebookTab from '@/components/common/bottomBox/tabs/notebookTab'
export default {
name: 'bottomBox',
@@ -150,7 +153,8 @@ export default {
discoveryTab,
commentsBottomTab,
vsysBottomTab,
rolesTab
rolesTab,
notebookTab
},
props: {
isFullScreen: Boolean, // 是否全屏
@@ -322,6 +326,9 @@ export default {
],
issue: [
// { prop: 'issue', name: this.$t('overall.issue'), active: true }
],
notebook: [
{ prop: 'notebookTab', name: this.$t('overall.notebook'), active: true }
]
}
}

View File

@@ -218,9 +218,9 @@ export default {
id: '',
name: '',
type: 'line',
span: 4,
span: 6,
datasource: 'metrics',
height: 4,
height: 2,
unit: 2,
param: {
stack: 0,
@@ -447,26 +447,9 @@ export default {
if (this.chart.type === 'group' && !this.chart.param.collapse == undefined) {
this.chart.param.collapse = false
}
if (this.chart.type === 'stat') {
if (!this.chart.param.sparklineMode) { this.chart.param.sparklineMode = 'none' }
if (!this.chart.param.comparison) { this.chart.param.comparison = 'none' }
}
if (!this.chart.param.dataLink) {
this.chart.param.dataLink = []
}
if (this.chart.type == 'table') {
if (!this.chart.param.tableOptions) {
this.chart.param.tableOptions = {
showTableHeader: 'enabled',
pagination: 'enabled',
defaultSortColumn: null,
defaultSort: null
}
}
}
if (this.chart.type == 'text' && !this.chart.param.editorType) {
this.chart.param.editorType = 'richText'
}
this.$nextTick(() => {
this.$refs.addChartModal.isStable = 'stable'
})
} else {
this.rightBox.loading = true
this.$get('visual/dashboard/chart/' + data.id).then(res => {
@@ -487,33 +470,6 @@ export default {
if (this.chart.type === 'group' && !this.chart.param.collapse == undefined) {
this.chart.param.collapse = false
}
if (this.chart.type === 'stat') {
if (!this.chart.param.sparklineMode) { this.chart.param.sparklineMode = 'none' }
if (!this.chart.param.comparison) { this.chart.param.comparison = 'none' }
}
if (!this.chart.param.dataLink) {
this.chart.param.dataLink = []
}
if (this.chart.type == 'table') {
const arr = this.chart.param.indexs ? this.chart.param.indexs.split(',') : []
this.chart.param.tags = arr.map((item) => {
return {
text: item,
tiClasses: ['ti-valid']
}
})
if (!this.chart.param.tableOptions) {
this.chart.param.tableOptions = {
showTableHeader: 'enabled',
pagination: 'enabled',
defaultSortColumn: null,
defaultSort: null
}
}
}
if (this.chart.type == 'text' && !this.chart.param.editorType) {
this.chart.param.editorType = 'richText'
}
this.$nextTick(() => {
this.$refs.addChartModal.isStable = 'stable'
})

View File

@@ -0,0 +1,597 @@
<template>
<div class="notebook-detail">
<nz-bottom-data-list
:showTitle='showTitle'
:obj='obj'
:layout="[]"
:tabs="tabs"
:targetTab="targetTab"
@changeTab="changeTab"
class="full-width-height"
:showPagination="false"
>
<template v-slot:title><span :title="obj.name">{{obj.name}}</span></template>
<template v-slot:top-tool-right>
<button class="nz-btn nz-btn-size-normal nz-btn-style-normal" v-if="!notebookEdit" @click="edit">
<i class="nz-icon nz-icon-edit"></i>
<span>{{$t('overall.edit')}}</span>
</button>
<button class="nz-btn nz-btn-size-normal nz-btn-style-normal" v-else @click="done">
<span>{{$t('notebook.done')}}</span>
</button>
<pick-time ref="pickTime" v-model="searchTime" :refresh-data-func="dateChange" :show-locked="true" :use-chart-unit="false" :sign="'notebook' + obj.id"></pick-time>
<el-dropdown v-has="['dashboard_view']" trigger="click" size="medium" class="nz-el-dropdown">
<button class="top-tool-btn" :title="$t('overall.download')">
<i class="nz-icon nz-icon-download1"></i>
</button>
<el-dropdown-menu slot="dropdown" class="right-box-select-top right-public-box-dropdown-top nz-el-dropdown-menu">
<el-dropdown-item v-has="'dashboard_view'">
<div @click="download('pdf')">{{$t('notebook.downloadAs',{format:'PDF'})}}</div>
</el-dropdown-item>
<el-dropdown-item v-has="'dashboard_view'">
<div @click="download('markdown')">{{$t('notebook.downloadAs',{format:'markdown'})}}</div>
</el-dropdown-item>
<el-dropdown-item v-has="'dashboard_view'">
<div @click="download('json')">{{$t('notebook.downloadNotebook')}} JSON</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<!--图表-->
<div ref="scrollbar" class="notebook-scrollWrap" v-my-loading="notebookLoading">
<div class="notebook-content">
<h2 class="notebook-title" v-if="!notebookEdit">{{notebookName}}</h2>
<el-input class="notebook-title-input" v-else v-model="notebookName" maxlength="64" placeholder="" size="small"></el-input>
<notebook-list
ref="notebookList"
:from="fromRoute.notebook"
:variablesInit="true"
:data-list="dataList"
:is-export-html="false"
:time-range="searchTime"
:nowTimeType="nowTimeType"
>
</notebook-list>
<div class="notebook-add" v-if="!notebookLoading&&notebookEdit">
<p class="notebook-add-title">{{$t('notebook.addchart')}}</p>
<ul class="notebook-add-list">
<li class="notebook-add-item"
v-show="!isShowLess||item.less"
v-for="item in typeList"
:key="item.name"
@click="addChartBefore(item)">
<svg class="notebook-chart-icon" aria-hidden="true">
<use :xlink:href="item.icon"></use>
</svg>
<span>{{item.name}}</span>
</li>
</ul>
<p class="notebook-add-show" @click="showChange">
<span>{{isShowLess?$t('notebook.showAll'):$t('notebook.showLess')}}</span>
</p>
</div>
</div>
</div>
</nz-bottom-data-list>
<transition name="right-box">
<chart-right-box
v-if="chartRightBoxShow"
v-my-loading="rightBox.loading"
ref="addChartModal"
:chart="chart"
:from="fromRoute.notebook"
:show-panel="showPanel"
@close="closeChartBox"
@on-create-success="createSuccess"
></chart-right-box>
</transition>
<!-- 快照进度 -->
<snapshotProgress v-if="snapshotVisible" :showPanel="showPanel" :searchTime="searchTime" :snapshotVisible.sync="snapshotVisible"></snapshotProgress>
</div>
</template>
<script>
import bus from '../../../../libs/bus'
import subDataListMixin from '@/components/common/mixin/subDataList'
import nzBottomDataList from '@/components/common/bottomBox/nzBottomDataList'
import detailViewRightMixin from '@/components/common/mixin/detailViewRightMixin'
import chartRightBox from '@/components/common/rightBox/chart/chartRightBox'
import { fromRoute } from '@/components/common/js/constants'
import { randomcolor } from '@/components/common/js/radomcolor/randomcolor'
import snapshotProgress from '@/components/common/snapshotProgress/snapshotProgress.vue'
import notebookList from '@/components/page/notebook/notebookList.vue'
export default {
name: 'notebookTab',
mixins: [subDataListMixin, detailViewRightMixin],
props: {
},
computed: {
delChartFlag () {
return this.$store.getters.getDelChart
},
chartRightBoxShow () {
return this.$store.getters.getShowRightBox
},
timePickerLocked () {
return this.$store.getters.getTimePickerLocked
},
timePickerRange () {
return this.$store.getters.getTimePickerRange
},
notebookEdit () { // 是否是编辑状态
return this.$store.getters.getNotebookEdit
}
},
data () {
return {
fromRoute,
notebookLoading: true,
searchTime: bus.getTimezontDateRange(),
nowTimeType: {},
snapshotVisible: false,
dataList: [],
notebookName: '',
isShowLess: false,
typeList: [
{ icon: '#nz-icon-text2', name: this.$t('dashboard.dashboard.chartForm.typeVal.text.label'), type: 'text', less: true, datasource: 'misc' },
{ icon: '#nz-icon-line_chart', name: this.$t('dashboard.dashboard.chartForm.typeVal.line.label'), type: 'line', less: true, datasource: 'metrics' },
{ icon: '#nz-icon-a-Areacharts', name: this.$t('dashboard.dashboard.chartForm.typeVal.stackArea.label'), type: 'area', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Point', name: this.$t('dashboard.dashboard.chartForm.typeVal.point.label'), type: 'point', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Stat', name: this.$t('dashboard.dashboard.chartForm.typeVal.singleStat.label'), type: 'stat', less: true, datasource: 'metrics' },
{ icon: '#nz-icon-hexagon', name: this.$t('dashboard.dashboard.chartForm.typeVal.hexagonFigure.label'), type: 'hexagon', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Bar_chart', name: this.$t('dashboard.dashboard.chartForm.typeVal.bar.label'), type: 'bar', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-a-Piechat', name: this.$t('dashboard.dashboard.chartForm.typeVal.pie.label'), type: 'pie', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-a-Doughnutchart', name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label'), type: 'doughnut', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-a-Rosechart', name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label'), type: 'rose', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Bubble', name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label'), type: 'bubble', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-funnel1', name: this.$t('dashboard.dashboard.chartForm.typeVal.funnel.label'), type: 'funnel', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-rank1', name: this.$t('dashboard.dashboard.chartForm.typeVal.rank.label'), type: 'rank', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Sankey', name: this.$t('dashboard.dashboard.chartForm.typeVal.sankey.label'), type: 'sankey', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Guage', name: this.$t('dashboard.dashboard.chartForm.typeVal.gauge.label'), type: 'gauge', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Treemap', name: this.$t('dashboard.dashboard.chartForm.typeVal.treemap.label'), type: 'treemap', less: false, datasource: 'metrics' },
{ icon: '#nz-icon-Table', name: this.$t('dashboard.dashboard.chartForm.typeVal.table.label'), type: 'table', less: true, datasource: 'metrics' }
],
rightBox: { // 面板弹出框相关
},
chart: {},
showPanel: {}
}
},
components: {
nzBottomDataList,
chartRightBox,
snapshotProgress, // 快照进度
notebookList
},
methods: {
getId (arr) { // 获取当前列表最大的id
const maxIdElement = arr.reduce(function (prev, current) {
return (prev.id > current.id) ? prev : current
})
return maxIdElement.id + 1
},
done () {
let charts = this.$lodash.cloneDeep(this.$refs.notebookList.copyDataList)
charts = charts.filter(item => item.name !== 'groupTemp')
const params = {
name: this.notebookName,
charts
}
if (!this.obj.id) { // 新增
this.$post('visual/notebook', params).then(response => {
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.$emit('getTableData')
this.$store.commit('setNotebookEdit', false)
} else {
this.$message.error(response.msg)
}
})
} else { // 编辑
params.id = this.obj.id
this.$put('visual/notebook', params).then(response => {
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.$emit('getTableData')
this.$store.commit('setNotebookEdit', false)
} else {
this.$message.error(response.msg)
}
})
}
},
// 图表创建成功回调panel页面进行图表的刷新
createSuccess (chart) {
delete chart.panelName
// this.$refs.notebookList.copyDataList.push(chart)
this.dataList.push(chart)
this.$store.dispatch('clearPanel')
},
addNotebook (position) {
this.addChartBefore({ type: 'line', datasource: 'metrics', position })
},
// 编辑图表信息,打开编辑弹窗
editChart (data, copy) {
if (copy) {
this.chart = JSON.parse(JSON.stringify(data))
this.chart.panelName = this.showPanel.name
this.chart.id = ''
this.chart.elements.forEach((item) => {
item.id = ''
item.chartId = ''
delete item.seq
})
if (this.chart.datasource !== 'metrics' && this.chart.datasource !== 'log') {
delete this.chart.elements
}
if (!this.chart.groupId || this.chart.groupId == -1) {
this.chart.groupId = ''
}
if (this.chart.type === 'group' && !this.chart.param.collapse == undefined) {
this.chart.param.collapse = false
}
this.$nextTick(() => {
this.$refs.addChartModal.isStable = 'stable'
})
} else {
this.rightBox.loading = true
this.$get('visual/dashboard/chart/' + data.id).then(res => {
this.rightBox.loading = false
if (res.code === 200) {
const chartData = res.data
this.chart = JSON.parse(JSON.stringify(chartData))
this.chart.panelName = this.showPanel.name
if (this.chart.param) {
this.chart.param = JSON.parse(this.chart.param)
} else {
this.chart.param = {}
}
if (!this.chart.groupId || this.chart.groupId == -1) {
this.chart.groupId = ''
}
if (this.chart.type === 'group' && !this.chart.param.collapse == undefined) {
this.chart.param.collapse = false
}
this.$nextTick(() => {
this.$refs.addChartModal.isStable = 'stable'
})
} else {
this.$message.error(res.msg)
}
})
}
},
/* 图表相关操作--start */
addChart (chart) {
const id = this.getId(this.$refs.notebookList.copyDataList)
console.log(chart)
this.chart = {
name: '',
type: chart.type,
unit: 2,
datasource: chart.datasource,
span: 12,
height: 4,
w: 12,
h: 4,
x: 0,
id: id,
i: id,
param: this.newChart(chart.type)
}
if (this.chart.datasource === 'metrics') {
this.chart.elements = [{ expression: '', legend: '', type: 'expert', id: '', name: 'A', state: 1, step: undefined }]
}
this.chart.panelName = this.obj.name
this.$nextTick(() => {
this.$refs.addChartModal.isStable = 'stable'
})
},
newChart (type) {
let param = {}
switch (type) {
case 'line':
case 'area':
case 'point':
param = {
stack: 0,
link: '',
nullType: 'null',
legend: { placement: 'bottom', values: [], show: true },
thresholdShow: true,
thresholds: [{ value: undefined, color: randomcolor() }],
enable: {
legend: true,
valueMapping: false,
thresholds: false,
visibility: false,
rightYAxis: false,
tooltip: true
},
showHeader: 1,
visibility: {
varName: '',
operator: 'equal',
varValue: '',
result: 'show'
},
rightYAxis: {
elementNames: [],
style: 'line',
unit: 2,
label: '',
min: undefined,
max: undefined
},
dataLink: [],
tooltip: {
mode: 'all',
sort: 'none'
},
option: undefined
}
break
case 'stat':
case 'hexagon':
case 'gauge':
case 'sankey':
case 'bubble':
case 'rank':
case 'funnel':
param = {
link: '',
nullType: 'null',
statistics: 'last',
text: 'value',
valueMapping: [],
min: 0,
max: 100,
enable: {
legend: true,
valueMapping: false,
thresholds: false,
visibility: false
},
showHeader: 1,
visibility: {
varName: '',
operator: 'equal',
varValue: '',
result: 'show'
},
sparklineMode: 'line',
comparison: 'none',
dataLink: []
}
break
case 'bar':
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
param = {
link: '',
nullType: 'null',
statistics: 'last',
text: 'value',
valueMapping: [],
legend: { placement: 'bottom', values: [], show: true },
enable: {
legend: true,
valueMapping: false,
thresholds: false,
visibility: false
},
showHeader: 1,
visibility: {
varName: '',
operator: 'equal',
varValue: '',
result: 'show'
},
dataLink: []
}
break
case 'table':
param = {
link: '',
nullType: 'null',
statistics: 'last',
columns: [],
tags: [],
indexs: '',
valueMapping: [],
enable: {
legend: true,
valueMapping: false,
thresholds: false,
visibility: false
},
showHeader: 1,
visibility: {
varName: '',
operator: 'equal',
varValue: '',
result: 'show'
},
tableOptions: {
showTableHeader: 'enabled',
pagination: 'enabled',
defaultSortColumn: null,
defaultSort: null
},
dataLink: []
}
break
case 'text':
param = {
link: '',
text: '',
enable: {
visibility: false
},
showHeader: 1,
visibility: {
varName: '',
operator: 'equal',
varValue: '',
result: 'show'
},
editorType: 'markdown'
}
break
}
return param
},
addChartBefore (chart) {
this.$store.dispatch('dispatchEditChart', {
chart: chart,
type: 'add'
})
},
disposeChart () {
const chartInfo = this.$store.getters.getChart
const type = this.$store.getters.getType
if (type === 'add') {
this.addChart(chartInfo)
}
if (type === 'edit') {
this.editChart(chartInfo)
}
if (type === 'delete') {
this.delChart(chartInfo)
}
if (type === 'duplicate') {
this.editChart(chartInfo, true)
}
},
closeChartBox (refresh) {
this.chart = {}
this.$store.dispatch('clearPanel')
},
showChange () {
this.isShowLess = !this.isShowLess
},
edit () {
this.$store.commit('setNotebookEdit', true)
},
download (type) {
console.log(type)
},
// 获取数据,用在子页面
getData () {
this.dataList = []
this.notebookLoading = true
if (this.obj.id) {
this.$get('/visual/notebook/' + this.obj.id).then(response => {
if (response.code === 200) {
this.notebookLoading = false
this.dataList = response.data.charts.map(item => {
return {
...item,
loaded: false
}
})
}
})
} else {
this.notebookLoading = false
}
},
refreshData (timeRange) { // 选择时间范围 还是刷新
const refresh = !timeRange
this.$refs.notebookList.refreshData(refresh)
},
dateChange (timeRange) {
if (this.$refs.pickTime) {
const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.setSearchTime('searchTime', nowTimeType, this.storeDispatchPanelTime)
this.refreshData(timeRange)
this.$store.dispatch('dispatchPanelTime', {
time: this.searchTime,
nowTimeType: this.nowTimeType
})
this.$store.dispatch('dispatchTimePickerRange', {
time: this.searchTime,
nowTimeType: this.nowTimeType
})
}
},
setTimePickerRange () {
this.$nextTick(() => {
if (this.timePickerLocked) {
const nowTimeType = this.nowTimeType = this.timePickerRange.nowTimeType
this.searchTime = this.timePickerRange.time
this.$refs.pickTime && this.$refs.pickTime.$refs.timePicker.setTimeRange(this.nowTimeType, this.searchTime)
this.setSearchTime('searchTime', nowTimeType, this.storeDispatchPanelTime)
}
})
},
storeDispatchPanelTime () { // 设置searchTime
this.$store.dispatch('dispatchPanelTime', {
time: this.searchTime,
nowTimeType: this.nowTimeType
})
},
// 切换tab
changeTab (tab) {
this.$emit('changeTab', tab)
},
// 滚动事件触发下拉加载
onScroll: bus.debounce(function () {
this.$refs.notebookList.onScroll(this.scrollbarWrap.scrollTop)
}, 300)
},
mounted () {
this.setTimePickerRange()
this.scrollbarWrap = this.$refs.scrollbar
this.scrollbarWrap.addEventListener('scroll', this.onScroll)
bus.$on('addNotebook', this.addNotebook)
},
beforeDestroy () {
this.$store.dispatch('dispatchPanelTime', {
time: [],
nowTimeType: {}
})
if (this.scrollbarWrap) {
this.scrollbarWrap.removeEventListener('scroll', this.onScroll)
}
bus.$off('addNotebook', this.addNotebook)
},
watch: {
obj: {
immediate: true,
handler (n) {
this.notebookName = n.name
this.getData()
if (!n.id) {
this.$store.commit('setNotebookEdit', true)
}
}
},
chartRightBoxShow: {
immediate: false,
deep: true,
handler (n) {
if (n) {
this.disposeChart()
} else {
this.$refs.addChartModal.isStable = 'instability'
}
}
},
delChartFlag: {
immediate: false,
deep: true,
handler (n) {
if (n) {
this.disposeChart()
}
}
}
}
}
</script>

View File

@@ -0,0 +1,101 @@
<template>
<div class="detail-left-box">
<div class="order-box">
<el-select v-model="orderBy" size="small" :placeholder="$t('asset.detail.orderBy')" popper-class="right-box-select-top" class="detail-select">
<el-option
v-for="item in tableTitle"
v-if="item.sortable==='custom'"
:key="item.prop"
:label="$t('asset.detail.orderByLabel',{label:item.label})"
:value="item.prop">
{{item.label}}
</el-option>
</el-select>
<button @click="orderTypeChange" size="small" class="detail-button top-tool-btn table-column-setting margin-l-10">
<i class="nz-icon nz-icon-arrow-up1" v-if="orderType=='ascending'" :title="$t('dashboard.explore.ascending')"/>
<i class="nz-icon nz-icon-arrow-down2" v-if="orderType=='descending'" :title="$t('dashboard.explore.descending')"/>
</button>
</div>
<ul class="detail-row-box" ref="dataTable">
<li
v-for="(item,index) in tableData"
:key="index"
class="detail-row"
:id="'globalSearch' + item.id"
:class="item.id === detailViewRightObj.id ? 'selected' : ''"
@click="detailViewRightShow(item)"
@mouseenter="labelHover(item, 'notebook', true, $event)"
@mouseleave="labelHover(item, 'notebook', false)">
<div class="detail-row-info" :title="item.name">
<div class="asset-manageIp">
<span class="author-avatar">{{item.createUser ? item.createUser.name.substr(0, 1) : '-'}}</span>
<span>{{item.name}}</span>
</div>
<div class="asset-name">
<span>{{item.location?item.location:'-'}}</span>
</div>
</div>
<alertLabel
v-if="item && item.loading"
:id="item.id"
:that="item"
:detail-list="true"
:type="'notebook'"
></alertLabel>
</li>
</ul>
</div>
</template>
<script>
import detailViewLeftMixin from '@/components/common/mixin/detailViewLeftMixin'
import alertLabel from '@/components/common/alert/alertLabel'
export default {
name: 'notebookDetail',
mixins: [detailViewLeftMixin],
components: {
alertLabel
},
data () {
return {
tableTitle: [
{
label: 'ID',
prop: 'id',
show: true,
width: 80,
sortable: 'custom'
}, {
label: this.$t('overall.name'),
prop: 'name',
show: true,
minWidth: 200,
sortable: 'custom'
}, {
label: this.$t('notebook.author'),
prop: 'createUser',
show: true,
minWidth: 300
}, {
label: this.$t('notebook.modifiedTime'),
prop: 'uts',
show: true,
minWidth: 200
}
]
}
},
methods: {
// label 鼠标划入
labelHover (item, type, loading, e) {
if (e) {
const dom = e.currentTarget
const position = dom.getBoundingClientRect()
this.$set(item, 'position', position)
}
this.$set(item, 'loading', loading)
}
}
}
</script>

View File

@@ -44,11 +44,14 @@
<alertRuleEvalLog v-if="from === fromRoute.alertRule && targetTab === 'evalLog'" v-show="subResizeShow" :from="from" :obj="obj" :tabs="tabs.alertRule.alertRule" @changeTab="changeTab" :targetTab.sync="targetTab"></alertRuleEvalLog>
<!--model 下滑-->
<asset-tab :showTitle="false" v-if="(from === fromRoute.model) && targetTab === 'asset'" :tabs="tabs.model" ref="assetTab" :from="from" :obj="obj" @changeTab="changeTab" @exit="closeSubList" :targetTab="targetTab"></asset-tab>
<!-- notebook Tab -->
<notebook-tab @getTableData="getTableData" :showTitle="false" v-if="from === fromRoute.notebook && targetTab === 'notebookTab'" :from="from" :obj="obj" :tabs="tabs.notebook" @changeTab="changeTab" :targetTab.sync="targetTab"></notebook-tab>
</div>
</div>
</template>
<script>
import routerPathParams from '@/components/common/mixin/routerPathParams'
import cabinetTab from '@/components/common/bottomBox/tabs/cabinetTab'
import alertMessageTab from '@/components/common/bottomBox/tabs/alertMessageTab'
import alertMessageTabNew from '@/components/common/bottomBox/tabs/alertMessageTabNew'
@@ -71,7 +74,7 @@ import LogBottomTab from '@/components/common/bottomBox/tabs/logBottomTab'
import processBottomTab from '@/components/common/bottomBox/tabs/processBottomTab'
import networkBottomTab from '@/components/common/bottomBox/tabs/networkBottomTab'
import detailRightTop from './detailRightTop/detailRightTop'
import routerPathParams from '@/components/common/mixin/routerPathParams'
import notebookTab from '@/components/common/bottomBox/tabs/notebookTab'
export default {
name: 'detailViewRight',
@@ -97,7 +100,8 @@ export default {
processBottomTab,
networkBottomTab,
commentsBottomTab,
vsysBottomTab
vsysBottomTab,
notebookTab
},
props: {
isFullScreen: Boolean, // 是否全屏
@@ -205,8 +209,10 @@ export default {
{ prop: 'asset', name: this.$t('asset.asset'), active: false },
{ prop: 'alertMessageTab', name: this.$t('overall.alert'), active: true }
]
}
},
notebook: [
{ prop: 'notebookTab', name: this.$t('overall.notebook'), active: true }
]
}
}
},
@@ -318,6 +324,8 @@ export default {
this.targetTab = 'cmdTab'
} else if (this.from === fromRoute.user) {
this.targetTab = 'operationLogTab'
} else if (this.from === fromRoute.notebook) {
this.targetTab = 'notebookTab'
}
this.updatePath(this.$route.query, this.$route.path, 'bottomBox')
}

View File

@@ -449,7 +449,8 @@ export const fromRoute = {
backups: 'backups',
ping: 'ping',
trace: 'trace',
integration: 'integration'
integration: 'integration',
notebook: 'notebook'
}
export const chartdatasource = [

View File

@@ -438,7 +438,7 @@ export default {
if (!tableTitle || !this.tableId) {
return
}
const preferenceTableTitle = tableHeaders || tableTitle
const preferenceTableTitle = (tableHeaders && tableHeaders.length) ? tableHeaders : tableTitle
if (tableTitle) {
// 先根据本地缓存中的prop进行排序
tableTitle.sort(function (a, b) {

View File

@@ -87,7 +87,7 @@ export default {
}
this.$refs[dataList].$refs.searchInput.sreach_num++
this.$refs[dataList].$refs.searchInput.searchLabelList = this.$refs.dataList.$refs.searchInput.searchLabelList.filter(item => searchLabel.label !== item.label)
this.$refs[dataList].$refs.searchInput.searchLabelList = this.$refs[dataList].$refs.searchInput.searchLabelList.filter(item => searchLabel.label !== item.label)
}
})
if (this.orderBy) {

View File

@@ -329,11 +329,10 @@ export default {
this.$set(this[key], 1, endTime)
this.$set(this[key], 2, val + 'd')
}
console.log(this[key], 'mainMixin')
this.$refs.pickTime.$refs.timePicker.searchTime = this[key]
}
if (cb) {
this.cb()
cb()
}
}
}

View File

@@ -108,6 +108,11 @@ export default {
})
break
}
case 'notebookTab': {
this.$store.commit('setNotebookEdit', true)
this.$emit('showBottomBox', 'notebookTab', row)
break
}
default:
this.$emit(command, row, param)
break

View File

@@ -283,10 +283,6 @@ export default {
},
computed: {
language () { return this.$store.getters.getLanguage },
// 判断是否是dashboard
isDashboard () {
return this.exportUrl === '/visual/dashboard/export'
},
// assetendpoint dashboard导出选项不支持 all data
assetOrEndpoint () {
return this.paramsType === 'asset' || this.paramsType === 'endpoint'
@@ -750,10 +746,6 @@ export default {
if (this.assetOrEndpoint || this.isTopo) {
this.importBox.record = 'current'
}
// isDashboard 只支持JSON
if (this.isDashboard) {
this.importBox.format = 3
}
if (this.onlyJson) {
this.importBox.format = 3
}

View File

@@ -202,58 +202,6 @@
@change="change"/>
</el-form-item>
<!--width-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.width')"
class="form-item--half-width"
prop="span">
<el-select
id="chart-box-span"
v-model="chartConfig.span"
:disabled="chartConfig.type === 'group'"
placeholder=""
popper-class="right-box-select-top prevent-clickoutside"
size="small"
value-key="chartSpan"
@change="change"
>
<el-option
v-for="item in spanList"
:key="item"
:label="'span-' + item"
:value="item">
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
<!--height-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.high')"
class="form-item--half-width"
prop="height">
<!-- 由px改为span -->
<el-select
id="chart-box-height"
v-model="chartConfig.height"
:disabled="chartConfig.type === 'group'"
placeholder=""
popper-class="right-box-select-top prevent-clickoutside"
size="small"
value-key="chartSpan"
@change="change"
>
<el-option
v-for="item in spanList"
:key="item"
:label="'span-' + item"
:value="item"
>
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
<!--stack-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.stack')"

View File

@@ -17,15 +17,17 @@
<el-form ref="chartForm" :model="editChart" :rules="rules" label-position= "top" label-width="120px" @submit.native.prevent>
<el-form-item :label='$t("overall.name")' prop="name">
<div style="display:flex;align-items:center">
<el-input style="flex:1;margin-right:10px" maxlength="64" show-word-limit size="small" v-model="editChart.name" id="chart-box-title"></el-input>
<el-input style="flex:1;" maxlength="64" show-word-limit size="small" v-model="editChart.name" id="chart-box-title"></el-input>
<template v-if="from !=='notebook'">
<!-- 显示头部 -->
<div class="choose-header-btn" v-if="editChart.param&&editChart.param.showHeader!==0" @click="switchHeader(0)" :title="$t('overall.visible')">
<div class="choose-header-btn margin-l-10" v-if="editChart.param&&editChart.param.showHeader!==0" @click="switchHeader(0)" :title="$t('overall.visible')">
<i class="nz-icon nz-icon-mimakejian"></i>
</div>
<!-- 隐藏头部 -->
<div class="choose-header-btn" v-else @click="switchHeader(1)" :title="$t('overall.invisible')">
<div class="choose-header-btn margin-l-10" v-else @click="switchHeader(1)" :title="$t('overall.invisible')">
<i class="nz-icon nz-icon-mimabukejian"></i>
</div>
</template>
</div>
</el-form-item>
@@ -33,7 +35,7 @@
<!--panel-->
<el-form-item
class="form-item--half-width"
v-if="showPanel.type !== fromRoute.project && showPanel.type !== fromRoute.asset && showPanel.type !== fromRoute.endpoint && showPanel.type !== fromRoute.model"
v-if="showPanel.type !== fromRoute.project && showPanel.type !== fromRoute.asset && showPanel.type !== fromRoute.endpoint && showPanel.type !== fromRoute.model&&from !=='notebook'"
:label="$t('overall.dashboard')"
prop="panelName"
>
@@ -49,7 +51,7 @@
</select-panel>
</el-form-item>
<!--group-->
<el-form-item :label="$t('dashboard.dashboard.chartForm.group')" class="form-item--half-width" prop="group">
<el-form-item :label="$t('dashboard.dashboard.chartForm.group')" class="form-item--half-width" prop="group" v-if="from !=='notebook'">
<el-select id="chart-box-group" v-model="editChart.groupId" :disabled="editChart.type==='group'" clearable placeholder="" popper-class="right-box-select-top prevent-clickoutside el-option-width303" size="small" value-key="chartType">
<el-option v-for="item in groupArr" :key="item.id" :label="item.name" :value="item.id">
<span class="panel-dropdown-label-txt" >{{item.name}}</span>
@@ -61,7 +63,7 @@
<el-form-item :label="$t('overall.remark')">
<el-input maxlength="256" show-word-limit v-model="editChart.remark" size="small" :rows="2" type="textarea"/>
</el-form-item>
<!--remark-->
<!--link-->
<el-form-item :label="$t('overall.link')" v-if="editChart.param">
<el-input maxlength="256" show-word-limit v-model="editChart.param.link" size="small" :rows="2" type="textarea"/>
</el-form-item>
@@ -72,16 +74,16 @@
</div>
<el-tabs v-model="editChart.datasource" @tab-click="datasourceChange" type="card">
<el-tab-pane :label="$t('overall.metrics')" name="metrics">
<chart-config :variables="variables" ref="childrenFrommetrics" :type="'metrics'" v-if="editChart.datasource == 'metrics'" :params.sync="editChart" @change="editChartChange"/>
<chart-config :from="from" :variables="variables" ref="childrenFrommetrics" :type="'metrics'" v-if="editChart.datasource == 'metrics'" :params.sync="editChart" @change="editChartChange"/>
</el-tab-pane>
<el-tab-pane :label="$t('overall.logs')" name="logs">
<chart-config :variables="variables" ref="childrenFromlogs" :type="'log'" v-if="editChart.datasource == 'logs'" :params.sync="editChart" @change="editChartChange" class="datasource-log"/>
<el-tab-pane :label="$t('overall.logs')" name="logs" :disabled="from==='notebook'">
<chart-config :from="from" :variables="variables" ref="childrenFromlogs" :type="'log'" v-if="editChart.datasource == 'logs'" :params.sync="editChart" @change="editChartChange" class="datasource-log"/>
</el-tab-pane>
<el-tab-pane :label="$t('overall.system')" name="system">
<system-chart-config :variables="variables" ref="childrenFromsystem" v-if="editChart.datasource == 'system'" :params.sync="editChart" @change="editChartChange"/>
<system-chart-config :from="from" :variables="variables" ref="childrenFromsystem" v-if="editChart.datasource == 'system'" :params.sync="editChart" @change="editChartChange"/>
</el-tab-pane>
<el-tab-pane :label="$t('overall.misc')" name="misc">
<other-chart-config :variables="variables" ref="childrenFrommisc" v-if="editChart.datasource == 'misc'" :params.sync="editChart" @change="editChartChange"/>
<other-chart-config :from="from" :variables="variables" ref="childrenFrommisc" v-if="editChart.datasource == 'misc'" :params.sync="editChart" @change="editChartChange"/>
</el-tab-pane>
</el-tabs>
</el-form>
@@ -268,10 +270,6 @@ export default {
params.x = 0
params.y = 999
}
if (!params.x && !params.y && this.from === 'chartTemp') { // chartTemp 新增 在第一位
params.x = 0
params.y = 0
}
if (isNaN(params.y) && isNaN(params.y) && params.groupId) { // group 内的坐标需要单独计算
params.x = 0
params.y = 999
@@ -296,6 +294,10 @@ export default {
if (params.datasource === 'system' && params.param.datasource[0].filter) {
params.param.datasource[0].filter = params.param.datasource[0].filter.filter(item => item.value)
}
if (this.from === 'notebook') {
self.$emit('on-create-success', params)
return
}
if (params.id) { // 修改
this.$put('visual/dashboard/chart', params).then(response => {
if (response.code === 200) {
@@ -380,8 +382,8 @@ export default {
if (this.editChart.datasource == 'metrics') {
this.editChart = {
...this.editChart,
span: 4,
height: 4,
span: 6,
height: 2,
unit: 2,
type: 'line',
elements: [{ expression: '', legend: '', type: 'expert', id: '', name: 'A', state: 1, step: undefined }],
@@ -423,8 +425,8 @@ export default {
if (this.editChart.datasource == 'logs') {
this.editChart = {
...this.editChart,
span: 4,
height: 4,
span: 6,
height: 2,
unit: 2,
type: 'log',
elements: [{ expression: '', legend: '', type: 'expert', id: '', name: 'A', state: 1, step: undefined }],
@@ -450,8 +452,8 @@ export default {
if (this.editChart.datasource == 'system') {
this.editChart = {
...this.editChart,
span: 4,
height: 4,
span: 6,
height: 2,
unit: 2,
type: 'stat',
param: {
@@ -490,11 +492,33 @@ export default {
}
delete this.editChart.elements
}
if (this.editChart.datasource == 'misc') {
if (this.editChart.datasource == 'misc' && this.from === 'notebook') {
this.editChart = {
...this.editChart,
span: 4,
span: 12,
height: 4,
type: 'text',
param: {
text: '',
enable: {
visibility: false
},
showHeader: this.editChart.param.showHeader,
visibility: {
varName: '',
operator: 'equal',
varValue: '',
result: 'show'
},
editorType: 'markdown'
}
}
delete this.editChart.elements
} else if (this.editChart.datasource == 'misc') {
this.editChart = {
...this.editChart,
span: 6,
height: 2,
type: 'url',
param: {
enable: {
@@ -515,6 +539,9 @@ export default {
}
delete this.editChart.elements
}
if (this.from === 'notebook') {
this.editChart.span = 12
}
},
editChartChange (newEditChart) {
this.editChart = {
@@ -629,14 +656,9 @@ export default {
}
})
}
}
if (obj.elements && obj.elements.length) {
obj.elements.forEach((item, index) => {
item.orderNum = index
delete item.seq
delete item.buildIn
delete item.chartId
})
if (!obj.param.dataLink) {
obj.param.dataLink = []
}
if ((obj.type === 'line' || obj.type === 'area' || obj.type === 'point')) {
if (!obj.param.rightYAxis) {
@@ -653,6 +675,39 @@ export default {
obj.param.option = this.lineOption
}
}
if (obj.type == 'table') {
const arr = obj.param.indexs ? obj.param.indexs.split(',') : []
obj.param.tags = arr.map((item) => {
return {
text: item,
tiClasses: ['ti-valid']
}
})
if (!obj.param.tableOptions) {
obj.param.tableOptions = {
showTableHeader: 'enabled',
pagination: 'enabled',
defaultSortColumn: null,
defaultSort: null
}
}
}
if (obj.type === 'stat') {
if (!obj.param.sparklineMode) { obj.param.sparklineMode = 'none' }
if (!obj.param.comparison) { obj.param.comparison = 'none' }
}
if (obj.type == 'text' && !obj.param.editorType) {
obj.param.editorType = 'richText'
}
}
if (obj.elements && obj.elements.length) {
obj.elements.forEach((item, index) => {
item.orderNum = index
delete item.seq
delete item.buildIn
delete item.chartId
})
}
this.editChart = this.$lodash.cloneDeep(obj)
this.oldData = this.$lodash.cloneDeep(obj)
if (this.stableTime) {

View File

@@ -30,6 +30,7 @@
value-key="chartType"
@change="chartTypeChange">
<el-option
v-show="from!=='notebook'||item.id==='text'"
v-for="item in chartTypeList"
:key="item.id"
:disabled="item.id==='group' && !!chartConfig.groupId"
@@ -62,6 +63,7 @@
popper-class="right-box-select-top prevent-clickoutside"
size="small"
@change="editorTypeChange"
:disabled="from==='notebook'"
>
<el-option :label="$t('dashboard.dashboard.chartForm.richText')" value="richText"></el-option>
<el-option :label="$t('dashboard.dashboard.chartForm.markDown')" value="markdown"></el-option>
@@ -69,58 +71,6 @@
</el-form-item>
</div>
<div class="form-items--half-width-group" v-if="!isGroup(chartConfig.type)">
<!--width-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.width')"
class="form-item--half-width"
prop="span">
<el-select
id="chart-box-span"
v-model="chartConfig.span"
:disabled="chartConfig.type === 'group'"
placeholder=""
popper-class="right-box-select-top prevent-clickoutside"
size="small"
value-key="chartSpan"
@change="change"
>
<el-option
v-for="item in spanList"
:key="item"
:label="'span-' + item"
:value="item">
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
<!--height-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.high')"
class="form-item--half-width"
prop="height">
<!-- 由px改为span -->
<el-select
id="chart-box-height"
v-model="chartConfig.height"
:disabled="chartConfig.type === 'group'"
placeholder=""
popper-class="right-box-select-top prevent-clickoutside"
size="small"
value-key="chartSpan"
@change="change"
>
<el-option
v-for="item in spanList"
:key="item"
:label="'span-' + item"
:value="item"
>
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
<!-- timeType -->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.timeType')"
@@ -426,7 +376,7 @@ export default {
},
methods: {
editorTypeChange () {
this.chartConfig.param.text = ''
this.chartConfig.param.text = undefined
this.change()
},
init () {

View File

@@ -19,7 +19,8 @@ export default {
default: () => {
return []
}
}
},
from: { type: String }
},
data () {
return {

View File

@@ -215,59 +215,6 @@
</el-cascader>
</el-form-item>
</div>
<div class="form-items--half-width-group">
<!--width-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.width')"
class="form-item--half-width"
prop="span">
<el-select
id="chart-box-span"
v-model="chartConfig.span"
:disabled="chartConfig.type === 'group'"
placeholder=""
popper-class="right-box-select-top prevent-clickoutside"
size="small"
value-key="chartSpan"
@change="change"
>
<el-option
v-for="item in spanList"
:key="item"
:label="'span-' + item"
:value="item">
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
<!--height-->
<el-form-item
:label="$t('dashboard.dashboard.chartForm.high')"
class="form-item--half-width"
prop="height">
<!-- 由px改为span -->
<el-select
id="chart-box-height"
v-model="chartConfig.height"
:disabled="chartConfig.type === 'group'"
placeholder=""
popper-class="right-box-select-top prevent-clickoutside"
size="small"
value-key="chartSpan"
@change="change"
>
<el-option
v-for="item in spanList"
:key="item"
:label="'span-' + item"
:value="item"
>
<span class="panel-dropdown-label-txt" > span-{{item}}</span>
</el-option>
</el-select>
</el-form-item>
</div>
<div class="form-items--half-width-group" v-if="isGauge(chartConfig.type)">
<!--min-->
<el-form-item :label="$t('dashboard.dashboard.chartForm.min')" class="form-item--half-width">

View File

@@ -0,0 +1,129 @@
<template>
<el-table
id="roleTable"
ref="dataTable"
:data="tableData"
:height="height"
border
:default-sort="orderBy"
@header-dragend="dragend"
@sort-change="tableDataSort"
@selection-change="selectionChange"
@row-dblclick="(row)=>{showBottomBox('notebookTab', row)}"
>
<el-table-column
:resizable="false"
align="center"
type="selection"
width="55">
</el-table-column>
<el-table-column
v-for="(item, index) in customTableTitle"
v-if="item.show"
:key="`col-${index}-${item.prop}`"
:fixed="item.fixed"
:label="item.label"
:min-width="`${item.minWidth}`"
:prop="item.prop"
:resizable="true"
:sort-orders="['ascending', 'descending']"
:sortable="item.sortable"
:width="`${item.width}`"
class="data-column"
>
<template slot="header">
<span class="data-column__span">{{item.label}}</span>
<div class="col-resize-area"></div>
</template>
<template slot-scope="scope" :column="item">
<template v-if="item.prop === 'name'">
<copy :copyData='scope.row[item.prop]' :showInfo='scope.row[item.prop]'>
<template slot="copy-text">
{{scope.row[item.prop]?scope.row[item.prop]:'-'}}
</template>
</copy>
</template>
<template v-else-if="item.prop === 'createUser'">{{scope.row[item.prop] ? scope.row[item.prop].name : '-'}}</template>
<template v-else-if="item.prop === 'uts'">{{scope.row[item.prop] ? momentTz(scope.row[item.prop]) : '-'}}</template>
<template v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</template>
<template v-else>-</template>
</template>
</el-table-column>
<el-table-column
:resizable="false"
:width="operationWidth"
fixed="right">
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
<div slot-scope="scope" class="table-operation-items">
<button class="table-operation-item" @click="showBottomBox('notebookTab', scope.row)" :title="$t('overall.view')"><i class="nz-icon nz-icon-view1"></i></button>
<el-dropdown size="medium" v-has="['role_add','role_edit','role_delete']" trigger="click" @command="tableOperation">
<div class="table-operation-item table-operation-item--more" :title="$t('overall.moreOperations')">
<i class="nz-icon nz-icon-more3"></i>
</div>
<el-dropdown-menu slot="dropdown" class="right-box-select-top right-public-box-dropdown-top">
<el-dropdown-item v-has="'role_edit'" :command="['notebookTab', scope.row]"><i class="nz-icon nz-icon-edit"></i><span class="operation-dropdown-text">{{$t('overall.edit')}}</span></el-dropdown-item>
<el-dropdown-item v-has="'role_add'" :command="['copy', scope.row]"><i class="nz-icon nz-icon-override"></i><span class="operation-dropdown-text">{{$t('overall.duplicate')}}</span></el-dropdown-item>
<el-dropdown-item v-has="'role_delete'" :command="['delete-rel', scope.row, {forceDeleteShow:false, single:true,from:'notebook'}]"><i class="nz-icon nz-icon-delete"></i><span class="operation-dropdown-text">{{$t('overall.delete')}}</span></el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</el-table-column>
<template slot="empty">
<div v-if="!loading" class="table-no-data">
<svg class="icon" aria-hidden="true">
<use xlink:href="#nz-icon-no-data-list"></use>
</svg>
<div class="table-no-data__title">No results found</div>
</div>
<div v-else>&nbsp;</div>
</template>
</el-table>
</template>
<script>
import table from '@/components/common/mixin/table'
import copy from '@/components/common/copy'
export default {
name: 'notebookTable',
mixins: [table],
components: { copy },
props: {
loading: Boolean
},
data () {
return {
tableTitle: [
{
label: 'ID',
prop: 'id',
show: true,
width: 80,
sortable: 'custom'
}, {
label: this.$t('overall.name'),
prop: 'name',
show: true,
minWidth: 200,
sortable: 'custom'
}, {
label: this.$t('notebook.author'),
prop: 'createUser',
show: true,
minWidth: 300
}, {
label: this.$t('notebook.modifiedTime'),
prop: 'uts',
show: true,
minWidth: 200
}
]
}
},
methods: {
showBottomBox (targetTab, row) {
this.$store.commit('setNotebookEdit', false)
this.$emit('showBottomBox', targetTab, JSON.parse(JSON.stringify(row)))
}
}
}
</script>

View File

@@ -173,10 +173,10 @@ export default {
id: '',
name: '',
type: 'line',
span: 4,
span: 6,
datasource: 'metrics',
varType: 1,
height: 4,
height: 2,
unit: 2,
param: {
stack: 0,

View File

@@ -234,9 +234,9 @@ export default {
id: '',
name: '',
type: 'line',
span: 4,
span: 6,
datasource: 'metrics',
height: 4,
height: 2,
unit: 2,
param: {
stack: 0,
@@ -621,26 +621,9 @@ export default {
if (this.chart.type === 'group' && !this.chart.param.collapse == undefined) {
this.chart.param.collapse = false
}
if (this.chart.type === 'stat') {
if (!this.chart.param.sparklineMode) { this.chart.param.sparklineMode = 'none' }
if (!this.chart.param.comparison) { this.chart.param.comparison = 'none' }
}
if (!this.chart.param.dataLink) {
this.chart.param.dataLink = []
}
if (this.chart.type == 'table') {
if (!this.chart.param.tableOptions) {
this.chart.param.tableOptions = {
showTableHeader: 'enabled',
pagination: 'enabled',
defaultSortColumn: null,
defaultSort: null
}
}
}
if (this.chart.type == 'text' && !this.chart.param.editorType) {
this.chart.param.editorType = 'richText'
}
setTimeout(() => {
this.$refs.addChartModal.isStable = 'stable'
})
} else {
this.rightBox.loading = true
this.$get('visual/dashboard/chart/' + data.id).then(res => {
@@ -661,33 +644,6 @@ export default {
if (this.chart.type === 'group' && !this.chart.param.collapse == undefined) {
this.chart.param.collapse = false
}
if (this.chart.type === 'stat') {
if (!this.chart.param.sparklineMode) { this.chart.param.sparklineMode = 'none' }
if (!this.chart.param.comparison) { this.chart.param.comparison = 'none' }
}
if (!this.chart.param.dataLink) {
this.chart.param.dataLink = []
}
if (this.chart.type == 'table') {
const arr = this.chart.param.indexs ? this.chart.param.indexs.split(',') : []
this.chart.param.tags = arr.map((item) => {
return {
text: item,
tiClasses: ['ti-valid']
}
})
if (!this.chart.param.tableOptions) {
this.chart.param.tableOptions = {
showTableHeader: 'enabled',
pagination: 'enabled',
defaultSortColumn: null,
defaultSort: null
}
}
}
if (this.chart.type == 'text' && !this.chart.param.editorType) {
this.chart.param.editorType = 'richText'
}
setTimeout(() => {
this.$refs.addChartModal.isStable = 'stable'
})
@@ -819,7 +775,7 @@ export default {
/* 图表相关操作--end */
/* 时间条件查询--start */
// 选择日期变化
dateChange (route) {
dateChange (timeRange) {
clearTopology()
const nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
this.nowTimeType = this.$refs.pickTime.$refs.timePicker.nowTimeType
@@ -834,7 +790,7 @@ export default {
nowTimeType: this.nowTimeType
})
// 选择时间范围时更新路由
if (route) {
if (timeRange) {
const param = { ...this.$route.query }
param.nowTimeType = JSON.stringify(this.nowTimeType)
param.searchTime = JSON.stringify(this.searchTime)

View File

@@ -4405,9 +4405,9 @@ export default {
name: '',
panelName: '',
type: 'line',
span: 4,
span: 6,
datasource: 'metrics',
height: 4,
height: 2,
unit: 2,
param: {
stack: 0,
@@ -4454,8 +4454,8 @@ export default {
id: '',
name: '',
panelName: '',
span: 4,
height: 4,
span: 6,
height: 2,
unit: 2,
groupId: -1,
updateBy: 1,

View File

@@ -0,0 +1,284 @@
<template>
<div v-my-loading="preferenceLoading">
<nzDetailView
v-my-loading="detailViewLoading || tools.loading"
v-if="detailType !== 'list'&&!preferenceLoading"
:api="url"
ref="detailList"
:layout="['searchInput', 'elementSet', 'pagination','detailViewSet']"
:from="fromRoute.notebook"
:search-msg="searchMsg"
:detailType="detailType"
:detailViewRightObj="detailViewRightObj"
:dataLength="tableData.length"
@search="search"
@changeDetailType="changeDetailType"
@getTableData="getTableData"
>
<template v-slot:top-tool-left>
</template>
<template v-slot:top-tool-right>
<button id="asset-create-asset" v-has="'role_add'" :title="$t('asset.createAsset')" class="top-tool-btn" @click.stop="add">
<i class="nz-icon nz-icon-create-square"></i>
</button>
<top-tool-more-options
:delete-objs="batchDeleteObjs"
ref="export"
id="model"
:params="searchLabel"
:params2="searchCheckBox"
:permissions="{
import: 'role_add',
export: 'role_edit'
}"
class="top-tool-export margin-r-10 margin-l-10"
export-file-name="notebook"
export-url="/visual/notebook/export"
import-url="/visual/notebook/import"
@afterImport="getTableData"
v-has="['role_add','role_edit']"
>
</top-tool-more-options>
</template>
<template v-slot:nz-detail-view-list>
<notebook-detail
class="data-detail"
ref="dataDetail"
:orderByFa="orderBy"
v-my-loading="tools.loading"
:detailViewRightObj="detailViewRightObj"
:api="url"
:table-data="tableData"
@detailViewRightShow="detailViewRightShow"
@orderDetail="orderDetail"
>
</notebook-detail>
</template>
<!-- 分页组件 -->
<template v-slot:pagination>
<el-pagination
@current-change="pageNo"
:current-page.sync="pageObj.pageNo"
:page-size="20"
:total="pageObj.total"
layout="prev, slot, next"
small
>
<template>
<el-input-number v-if="showInput" ref="jumpInput" v-model="pageObj.pageNo" :controls="false" :min="1" :max="pageObj.pages" class="jump-input" @change="getTableData" @keyup.enter.native="getTableData" size="mini"/>
<span class="jump-pages">/&nbsp;{{pageObj.pages}}</span>
</template>
</el-pagination>
</template>
</nzDetailView>
<nz-data-list
ref="dataList"
:api="url"
v-if="detailType === 'list'&&!preferenceLoading"
:layout="['searchInput', 'elementSet', 'pagination','detailViewSet']"
:custom-table-title.sync="tools.customTableTitle"
:from="fromRoute.notebook"
:search-msg="searchMsg"
@search="search"
:detailType="detailType"
@changeDetailType="changeDetailType"
@getTableData="getTableData"
>
<template v-slot:top-tool-right>
<button v-has="'role_add'" :title="$t('overall.createDatacenter')" class="top-tool-btn margin-r-10" type="button" @click="add">
<i class="nz-icon-create-square nz-icon"></i>
</button>
<top-tool-more-options
:delete-objs="batchDeleteObjs"
ref="export"
id="model"
:params="searchLabel"
:permissions="{
import: 'role_add',
export: 'role_edit'
}"
class="top-tool-export margin-r-10"
export-file-name="notebook"
export-url="/visual/notebook/export"
import-url="/visual/notebook/import"
@afterImport="getTableData"
v-has="['role_add','role_edit','role_delete']"
>
<template v-slot:before>
<div>
<el-dropdown-item :disabled="batchDeleteObjs.length==0" :class="'nz-el-dropdown-menu-item'">
<delete-button
ref="deleteButton"
:single="false"
:from="'notebook'"
:forceDeleteShow="false"
:deleteTitle="'overall.notebook'"
:type="'link'"
:title="$t('overall.batchDel')"
id="account-list-batch-delete"
v-has="'role_delete'"
:delete-objs="batchDeleteObjs"
api="visual/notebook"
@after="getTableData"
></delete-button>
</el-dropdown-item>
</div>
</template>
</top-tool-more-options>
</template>
<template v-slot:default="slotProps">
<notebook-table
ref="dataTable"
:orderByFa="orderBy"
v-my-loading="tools.loading"
:loading="tools.loading"
:api="url"
:custom-table-title="tools.customTableTitle"
:height="mainTableHeight"
:table-data="tableData"
@del="del"
@edit="edit"
@copy="copy"
@orderBy="tableDataSort"
@reload="getTableData"
@topology="topology"
@selectionChange="selectionChange"
@showBottomBox="(targetTab, object) => { $refs.dataList.showBottomBox(targetTab, object) }"></notebook-table>
</template>
<!-- 分页组件 -->
<template v-slot:pagination>
<Pagination ref="Pagination" :pageObj="pageObj" :tableId="tableId" @pageNo='pageNo' @pageSize='pageSize'></Pagination>
</template>
</nz-data-list>
</div>
</template>
<script>
import deleteButton from '@/components/common/deleteButton'
import nzDataList from '@/components/common/table/nzDataList'
import dataListMixin from '@/components/common/mixin/dataList'
import notebookTable from '@/components/common/table/settings/notebookTable'
import topToolMoreOptions from '@/components/common/popBox/topToolMoreOptions'
import nzDetailView from '@/components/common/detailView/nzDetailView'
import detailViewMixin from '@/components/common/mixin/detailViewMixin'
import notebookDetail from '@/components/common/detailView/list/notebook/notebookDetail'
import bus from '@/libs/bus'
export default {
name: 'notebook',
components: {
deleteButton,
nzDataList,
notebookTable,
topToolMoreOptions,
nzDetailView,
notebookDetail
},
mixins: [dataListMixin, detailViewMixin],
data () {
return {
url: 'visual/notebook',
tableId: 'notebookTable', // 需要分页的table的id用于记录每页数量
blankObject: {
id: '',
name: '',
type: 'none',
remark: 'none'
},
searchMsg: { // 给搜索框子组件传递的信息
zheze_none: true,
searchLabelList: [
{
name: 'ID',
type: 'input',
label: 'ids',
disabled: false
},
{
name: this.$t('overall.name'),
type: 'input',
label: 'name',
disabled: false
}
]
}
}
},
methods: {
add () {
this.$store.commit('setNotebookEdit', true)
const username = localStorage.getItem('nz-username')
const date = bus.timeFormate(bus.computeTimezone(new Date().getTime()))
const name = username + ' ' + date
if (this.detailType === 'list') {
this.$refs.dataList.showBottomBox('notebookTab', { name })
} else {
this.detailViewRightObj = this.$lodash.cloneDeep({ name })
}
},
copy (u) {
this.$confirm(this.$t('tip.confirmDuplicateNotebook'), {
confirmButtonText: this.$t('tip.yes'),
cancelButtonText: this.$t('tip.no'),
type: 'warning'
}).then(() => {
const username = localStorage.getItem('nz-username')
const date = bus.timeFormate(bus.computeTimezone(new Date().getTime()))
const param = {
id: u.id,
name: username + ' ' + date
}
this.$post('/visual/notebook/duplicate', param).then(res => {
if (res.code === 200) {
this.getTableData()
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
} else {
this.$message.error(res.msg)
}
})
}).catch(() => {
})
}
},
created () {
const searchKeys = {
// key: path 键
// value: vue set 参数
pageNo: { target: this.pageObj, propertyName: 'pageNo', type: 'number' },
pageSize: { target: this.pageObj, propertyName: 'pageSize', type: 'number' },
orderBy: { target: this.$data, propertyName: 'orderBy', type: 'string' },
ids: {
target: this.searchLabel,
isSearchInput: true,
propertyName: 'ids',
type: 'string',
defaultJson: {
disabled: false,
id: 'ids',
label: 'ids',
name: 'ID',
type: 'input',
val: ''
},
jsonKey: 'val'
},
name: {
target: this.searchLabel,
isSearchInput: true,
propertyName: 'name',
type: 'string',
defaultJson: {
disabled: false,
id: 'name',
label: 'name',
name: 'Name',
type: 'input',
val: ''
},
jsonKey: 'val'
}
}
this.initQueryFromPath(searchKeys)
},
mounted () {
}
}
</script>

View File

@@ -0,0 +1,221 @@
<template>
<div class="notebook-list">
<grid-layout
v-if="gridLayoutShow"
ref="layout"
:class="firstInit ? 'no-animation' : ''"
:col-num="12"
:is-draggable="notebookEdit"
:is-resizable="notebookEdit"
:layout.sync="copyDataList"
:margin="[20, 20]"
:vertical-compact="true"
:use-css-transforms="false"
>
<grid-item
v-for="item in copyDataList"
:key="item.id"
:h="item.h"
:i="item.i"
:w="item.w"
:x="item.x"
:y="item.y"
:min-w="12"
:static="item.static"
:class="{
'opacityItem': item.static,
}"
:ref="'grid-item' + item.id"
dragAllowFrom=".chart-header"
dragIgnoreFrom=".chart-header__tools"
@resized="resizedEvent"
@moved="movedEvent"
>
<panel-chart
:from="from"
:variablesInit="true"
:ref="'chart' + item.id"
:chart-info="item"
:time-range="timeRange"
:isExportHtml="isExportHtml"
:dataJson="dataJson"
></panel-chart>
</grid-item>
</grid-layout>
</div>
</template>
<script>
import GridLayout from '@/components/chart/chart/grid/GridLayout'
import GridItem from '@/components/chart/chart/grid/GridItem'
import panelChart from '@/components/chart/panelChart'
import groupData from '@/components/chart/tempGroup'
import { lineChartMove } from '@/components/common/js/common'
export default {
name: 'notebookList',
props: {
from: { type: String },
timeRange: Array, // 时间范围
dataList: Array,
variablesInit: {
type: Boolean,
default: true
},
isExportHtml: {
type: Boolean,
default: false
},
dataJson: {
type: Object,
default: () => {
return {}
}
}
},
components: {
GridLayout: GridLayout,
GridItem: GridItem,
panelChart
},
computed: {
notebookEdit () { // 是否是编辑状态
return this.$store.getters.getNotebookEdit
}
},
data () {
return {
gridLayoutShow: false,
firstInit: true,
copyDataList: [],
noData: false, // no data
scrollTop: 0,
scrollTopTimer: null
}
},
mounted () {
window.addEventListener('resize', this.resize)
if (!document.onmousemove) { // 添加鼠标移动事件监听
document.onmousemove = lineChartMove
}
},
beforeDestroy () {
window.removeEventListener('resize', this.resize)
document.onmousemove = null
},
methods: {
addNotebook (position) {
this.$emit('addNotebook', position)
},
refreshData (refreshData) {
this.copyDataList.forEach(item => {
this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0] && this.$refs['chart' + item.id][0].getChartData(refreshData)
})
},
resizedEvent (i, newH, newW, newHPx, newWPx) {
// TODO 重新渲染图表向后端发送put请求
setTimeout(() => {
this.$refs['chart' + i][0].resize()
this.onScroll(this.scrollTop)
}, 100)
},
movedEvent (i, newX, newY) {
this.onScroll(this.scrollTop)
},
onScroll (scrollTop = 0) {
const self = this
if (this.scrollTopTimer) {
clearTimeout(this.scrollTopTimer)
this.scrollTopTimer = null
}
this.scrollTopTimer = setTimeout(() => {
this.copyDataList.forEach(item => {
if (!this.$refs['grid-item' + item.id] || !this.$refs['grid-item' + item.id][0]) {
return
}
const dom = this.$refs['grid-item' + item.id][0].$el
if (dom) {
let top = dom.style.top
top = Number(top.substring(0, top.length - 2))
if (item.loaded) {
return
}
const itemHeight = dom.offsetHeight
const mainOffsetTop = top
self.scrollTop = scrollTop
// 4.浏览器可见区域的高度
const windowHeight = (window.innerHeight || document.documentElement.clientHeight) - 50 - 70
if ((mainOffsetTop + itemHeight / 4) < (scrollTop + windowHeight)) {
item.loaded = true
this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0] && this.$refs['chart' + item.id][0].getChartData()
}
}
})
}, 200)
},
resize () {
this.copyDataList.forEach(item => {
if (item.type === 'group') {
this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0].groupShow(item.param.collapse)
this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0].$refs.chart && this.$refs['chart' + item.id][0].$refs.chart.$refs['chart' + item.id] && this.$refs['chart' + item.id][0].$refs.chart.$refs['chart' + item.id].$refs.chartList.resize()
}
try {
this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0].resize()
} catch (error) {
}
})
}
},
watch: {
dataList: {
immediate: true,
deep: true,
handler (n) {
this.noData = !n || n.length < 1
this.gridLayoutShow = false
this.firstInit = true
const cloneDataList = this.$lodash.cloneDeep(n)
const tempList = cloneDataList.map((item, index) => {
const height = item.height || ''
const id = item.id || index
return {
...item,
id,
i: id,
w: 12,
h: height || 4,
x: item.x || 0,
y: item.y || 0
}
})
// 添加占位元素 防止向上塌陷
tempList.push({
...groupData,
i: -2,
w: 12,
h: 0,
x: 0,
y: 0,
static: true
})
this.$nextTick(() => {
console.log(tempList)
this.copyDataList = this.$lodash.cloneDeep(tempList)
this.gridLayoutShow = true
if (!this.isExportHtml) {
this.onScroll()
} else {
this.onScroll(999999)
}
setTimeout(() => {
this.firstInit = false
}, 2000)
})
}
}
}
}
</script>
<style>
</style>

View File

@@ -8,7 +8,7 @@ import VueResource from 'vue-resource'
import bus from '@/libs/bus'
Vue.use(VueResource)
const loginWhiteList = ['/setup', '/sys/license/upload', '/sys/license/state', '/sys/appearance', '/i18n', '/terminal'] // 免登陆白名单
const loginWhiteList = ['/setup', '/sys/license/upload', '/sys/license/state', '/sys/appearance', '/i18n', '/terminal', '/notebook'] // 免登陆白名单
export const permissionWhiteList = ['/profile', '/menu', ...loginWhiteList] // 权限白名单
router.beforeEach((to, from, next) => {
if (window.entrance) {

View File

@@ -239,6 +239,10 @@ export default new Router({
{
path: '/softwareAsset',
component: resolve => require(['@/components/page/asset/software/softwareAsset'], resolve)
},
{
path: '/notebook',
component: resolve => require(['@/components/page/notebook/notebook'], resolve)
}
]
},

View File

@@ -27,7 +27,8 @@ const panel = {
currentMousemove: 0,
variablesArr: [],
timeBoxClass: '',
homeLoading: false
homeLoading: false,
notebookEdit: false
},
mutations: {
setShowRightBox (state, flag) {
@@ -101,6 +102,9 @@ const panel = {
},
setHomeLoading (state, value) {
state.homeLoading = value
},
setNotebookEdit (state, value) {
state.notebookEdit = value
}
},
getters: {
@@ -160,6 +164,9 @@ const panel = {
},
getHomeLoading (state, value) {
return state.homeLoading
},
getNotebookEdit (state, value) {
return state.notebookEdit
}
},
actions: {