NEZ-2577 feat:集成页面开发

This commit is contained in:
zyh
2023-02-23 14:48:03 +08:00
parent 55d4357895
commit 0d3686d931
18 changed files with 353 additions and 64 deletions

View File

@@ -1742,9 +1742,9 @@
"integrity": "sha512-0VoTMXNIdyHzdzgAMw4pQk8hMuXxtt2LAw7Urt0rmCpAFGcNrsbMWIB6rn5Avu8xyYEPcprKJh2tVpUDeWUVhA=="
},
"@meta2d/core": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@meta2d/core/-/core-1.0.0.tgz",
"integrity": "sha512-urCDDZd6226L0vjaOy5yByXMSCus4wbDsvwm4F0e7PdxC+++gVqJruXVhUxUG65nSQxxENx4VzOPz+kbTIe0BQ==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@meta2d/core/-/core-1.0.2.tgz",
"integrity": "sha512-0X+LRGbqHZbDlJJojqQJZbYmarzFAupgrrC5KMCBQpGhRSP4jL7Mpy25HJ125sGliocXGkiwMUYkqnzzW5Ph3w==",
"requires": {
"mitt": "^2.1.0",
"mqtt": "^4.2.6"
@@ -4885,7 +4885,7 @@
},
"clipboard": {
"version": "2.0.11",
"resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz",
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
"requires": {
"good-listener": "^1.2.2",
@@ -7210,7 +7210,7 @@
},
"delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
"resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
},
"delegates": {
@@ -9541,7 +9541,7 @@
},
"good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
"resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
"requires": {
"delegate": "^3.1.2"
@@ -16432,7 +16432,7 @@
},
"select": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
"resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
},
"select-hose": {
@@ -18359,7 +18359,7 @@
},
"tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
},
"tinycolor2": {
@@ -19073,7 +19073,7 @@
},
"vue-clipboard2": {
"version": "0.3.3",
"resolved": "https://registry.npmmirror.com/vue-clipboard2/-/vue-clipboard2-0.3.3.tgz",
"resolved": "https://registry.npmjs.org/vue-clipboard2/-/vue-clipboard2-0.3.3.tgz",
"integrity": "sha512-aNWXIL2DKgJyY/1OOeITwAQz1fHaCIGvUFHf9h8UcoQBG5a74MkdhS/xqoYe7DNZdQmZRL+TAdIbtUs9OyVjbw==",
"requires": {
"clipboard": "^2.0.0"

View File

@@ -25,7 +25,7 @@
"@meta2d/activity-diagram": "^1.0.0",
"@meta2d/chart-diagram": "^1.0.0",
"@meta2d/class-diagram": "^1.0.0",
"@meta2d/core": "^1.0.0",
"@meta2d/core": "^1.0.2",
"@meta2d/flow-diagram": "^1.0.0",
"@meta2d/sequence-diagram": "^1.0.0",
"@riophae/vue-treeselect": "^0.4.0",

View File

@@ -193,6 +193,7 @@
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
h3{
font-family: Roboto-Medium;
font-size: 14px;
@@ -200,21 +201,32 @@
font-weight: 600;
}
.nz-btn{
width: 80px;
height: 30px;
padding: 0 10px;
border-radius: 4px;
background-color: $--color-primary;
border: none !important;
i{
font-size: 16px;
}
span{
font-size: 14px;
}
&.no-choose{
cursor: default;
background: $--background-color-base;
color: $--web-ssh-color-text-disable;
pointer-events: none;
}
}
}
.integration-configuration{
box-sizing: border-box;
padding: 30px;
padding-top: 15px;
padding-right: 10px;
margin-right: 20px;
height: 100%;
overflow-y: auto;
.integration-configuration-title{
@@ -280,5 +292,39 @@
height: 100%;
}
}
.integration-alert{
height: 100%;
box-sizing: border-box;
padding: 30px;
padding-top: 0;
.list-page{
height: calc(100% - 60px);
.nz-table-list{
padding: 0;
height: 100%;
.gutter{
position: unset;
}
}
}
}
.integration-metric{
height: 100%;
box-sizing: border-box;
padding: 30px;
padding-top: 20px;
.list-page{
height: 100%;
.nz-table-list{
padding: 0;
height: 100%;
.gutter{
position: unset;
}
}
}
}
}
}

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,13 @@
"css_prefix_text": "nz-icon-",
"description": "",
"glyphs": [
{
"icon_id": "34168331",
"name": "Integration",
"font_class": "Integration",
"unicode": "e7d0",
"unicode_decimal": 59344
},
{
"icon_id": "34053254",
"name": "编组 2",

File diff suppressed because one or more lines are too long

View File

@@ -56,7 +56,7 @@
<i class="nz-icon nz-icon-info-normal tool__icon"></i>
</el-tooltip>
</span>
<span v-if="chartInfo.type=='group'&&!chartInfo.repeatIndex" class="chart-header__tool" @click="addChartGroup">
<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>
<!-- </el-tooltip> -->
@@ -71,7 +71,7 @@
<i class="nz-icon nz-icon-maxview tool__icon"></i>
</div>
</span>
<span class="chart-header__tool" v-if="!chartInfo.repeatIndex">
<span class="chart-header__tool" v-if="!chartInfo.repeatIndex&&from!=='integration'">
<el-dropdown v-clickoutside="clickos" v-has="['main_edit','main_delete','main_add']" trigger="click">
<i class="el-icon-more tool__icon" @click.stop="dropdownMenuShow = !dropdownMenuShow" :title="$t('overall.more')"></i>
<el-dropdown-menu style="display: none" class="temp-dropdown"></el-dropdown-menu>

View File

@@ -491,7 +491,7 @@ export default {
// 比较变量 图表是否显示/隐藏
compareVariables () {
// 防止group中的chartList执行
if (this.groupInfo) {
if (this.isGroup) {
return
}
const isRegExp = (v) => {
@@ -585,7 +585,7 @@ export default {
// group设置repeat 便利变量重复渲染图表
repeatVariableFn () {
// 防止group中的chartList执行
if (this.groupInfo) {
if (this.isGroup) {
return
}
// 先删除掉复制的数据

View File

@@ -7,6 +7,7 @@
:is-group="isGroup(chartInfo.type)"
:isExportHtml="isExportHtml"
:isError="isError"
:from="from"
:chartData="chartData"
:chart-info="chartInfo"
:showAllData.sync="showAllData"

View File

@@ -1,26 +1,158 @@
<template>
<div class="integration-alert">
<p>alert</p>
<div class="integration-tool" style="padding: 0 10px;">
<h3></h3>
<button class="nz-btn el-button--small nz-btn-style-normal" :class="{'no-choose':!batchObjs.length}" @click="importFn">
<i class="nz-icon nz-icon-upload"></i>
<span>{{$t('overall.importExcel')}}</span>
</button>
</div>
<div class="list-page">
<div class="nz-table-list">
<el-table
v-my-loading="loading"
ref="dataTable"
:height="'100%'"
:data="tableData"
border
@header-dragend="dragend"
@selection-change="selectionChange"
>
<el-table-column
:resizable="false"
align="center"
type="selection"
width="55">
</el-table-column>
<el-table-column
v-for="(item, index) in tableTitle"
:key="`col-${index}`"
:label="item.label"
:min-width="`${item.minWidth}`"
:prop="item.prop"
:resizable="true"
:width="`${item.width}`"
class="data-column"
:sortable="item.sortable"
>
<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 === 'type'">
<span v-if="scope.row[item.prop] === 1">{{ $t('overall.metric') }}</span>
<span v-else-if="scope.row[item.prop] === 2">{{ $t('overall.logs') }}</span>
<span v-else-if="scope.row[item.prop] === 3">SNMP trap</span>
<span v-else>-</span>
</template>
<template v-else-if="item.prop === 'threshold'">{{formatThreshold(scope.row[item.prop], scope.row.unit)}}</template>
<span v-else-if="item.prop === 'severity'&&scope.row[item.prop]" class="severity">
<i class="nz-icon nz-icon-circle" :style="{color:scope.row[item.prop].color,'font-size':'12px','margin-right':'5px'}"></i> {{scope.row[item.prop].name}}
</span>
<span v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
<template v-else>-</template>
</template>
</el-table-column>
<el-table-column
:resizable="false"
:width="100"
fixed="right">
<div slot="header" class="table-operation-title">{{$t('overall.option')}}</div>
<div class="table-operation-items">
<button class="table-operation-item" @click="importFn" :title="$t('overall.importExcel')"><i class="nz-icon nz-icon-upload"></i></button>
</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>
</div>
</div>
</div>
</template>
<script>
import chartDataFormat from '@/components/chart/chartDataFormat'
export default {
name: 'integration-alert',
props: {
active: Boolean
moduleId: Number
},
data () {
return {
tableTitle: [
{
label: this.$t('alert.alertName'),
prop: 'name',
minWidth: 150
}, {
label: this.$t('overall.type'),
prop: 'type',
show: true,
minWidth: 90
}, {
label: this.$t('config.exprTemp.expression'),
prop: 'expr',
minWidth: 180
}, {
label: this.$t('alert.config.threshold'),
prop: 'threshold',
minWidth: 100
}, {
label: this.$t('alert.summary'),
prop: 'summary',
minWidth: 160
}, {
label: this.$t('alert.severity'),
prop: 'severity',
minWidth: 100
}, {
label: this.$t('asset.snmpCredential'),
prop: '',
minWidth: 150
}
],
loading: false,
tableData: [],
batchObjs: []
}
},
mounted () {
this.getTableData()
},
methods: {
getData () {
async getTableData () {
this.loading = true
const res = await this.$get('/integration/alertRule', { moduleIds: this.moduleId, pageSize: -1 })
this.tableData = res.data.list
this.loading = false
},
selectionChange (objs) {
this.batchObjs = objs
},
formatThreshold (value, unit) {
const unitMethod = chartDataFormat.getUnit(unit)
if (unitMethod && value) {
return unitMethod.compute(value, null, 2)
} else {
return value
}
},
watch: {
importFn () {
},
dragend () {
this.$nextTick(() => {
this.$refs.dataTable.doLayout()
})
}
}
}
</script>

View File

@@ -1,7 +1,7 @@
<template>
<div class="integration-dashboard">
<div class="integration-tool" style="padding: 0 10px;">
<h3>Dashboard name</h3>
<h3>{{showPanel.name}}</h3>
<top-tool-more-options
type='integration'
@@ -16,7 +16,7 @@
@afterImport="afterImport"
>
<template>
<button class="nz-btn el-button--small nz-btn-style-normal" :class="{'nz-btn-disabled':prevent_opt.import}" @click="importFn">
<button class="nz-btn el-button--small nz-btn-style-normal" @click="importFn">
<i class="nz-icon nz-icon-upload"></i>
<span>{{$t('overall.importExcel')}}</span>
</button>
@@ -57,6 +57,7 @@ import bus from '../../../../libs/bus'
import { fromRoute } from '@/components/common/js/constants'
import topToolMoreOptions from '@/components/common/popBox/topToolMoreOptions'
import panelVariables from '@/components/common/panel/panelVariables'
import chartDataFormat from '@/components/chart/chartDataFormat'
export default {
name: 'integration-dashboard',
props: {
@@ -73,7 +74,6 @@ export default {
data () {
return {
fromRoute,
showTopBtn: false, // top按钮
chartListLoading: true,
searchTime: bus.getTimezontDateRange(),
panel: { // 新增panel
@@ -87,9 +87,10 @@ export default {
},
showPanel: {
name: '',
type: 'dashboard',
type: 'integration',
id: null
},
showTopLine: false,
nowTimeType: {},
scrollbarWrap: null,
variables: [],
@@ -110,24 +111,46 @@ export default {
onScroll () {
const _self = this
this.scrollbarWrap.addEventListener('scroll', bus.debounce(function () {
_self.showTopBtn = _self.scrollbarWrap.scrollTop > 50
_self.$refs.chartList.onScroll(_self.scrollbarWrap.scrollTop)
}, 300))
}, 300, function () {
_self.showTopLine = _self.scrollbarWrap.scrollTop > 10
}))
},
getUnitValue (type) {
const unitsList = []
chartDataFormat.unitOptions().forEach((item, index) => {
item.children.forEach((n, i) => {
unitsList.push({ ...n, type: item.label })
})
})
const findItem = unitsList.find(item => item.label.replace(/\s*/g, '') == type.replace(/\s*/g, ''))
return findItem ? findItem.value : 2
},
getData () {
// if (!this.hasButton('panel_view')) {
// return
// }
this.dataList = this.showPanel.charts.map(item => {
return {
...item,
span: Number(item.span),
height: Number(item.height),
x: Number(item.x),
y: Number(item.y),
loaded: false
if (!this.hasButton('panel_view')) {
return
}
let num = 0
this.showPanel.charts.forEach(item => {
item.id = ++num
item.span = Number(item.span)
item.height = Number(item.height)
item.x = Number(item.x)
item.y = Number(item.y)
item.type = item.type.split(' ')[0].toLowerCase()
item.unit = this.getUnitValue(item.unit)
item.loaded = false
item.children && item.children.forEach(subItem => {
subItem.id = ++num
subItem.span = Number(subItem.span)
subItem.height = Number(subItem.height)
subItem.x = Number(subItem.x)
subItem.y = Number(subItem.y)
subItem.type = subItem.type.split(' ')[0].toLowerCase()
subItem.unit = this.getUnitValue(subItem.unit)
})
})
this.dataList = this.showPanel.charts
this.chartListLoading = false
},
// 公用操作
@@ -150,6 +173,7 @@ export default {
},
mounted () {
this.scrollbarWrap = this.$refs.dashboardScrollbar
this.onScroll()
this.getTableData()
},
watch: {

View File

@@ -6,8 +6,8 @@
<div class="integration-tabs-content">
<configuration v-if="tabId==='configuration'" :configuration="detailsObj.configuration"></configuration>
<dashboard v-if="tabId==='dashboard'" :dashboardTemplate="detailsObj.dashboardTemplate"></dashboard>
<alert v-if="tabId==='alert'"></alert>
<metric v-if="tabId==='metric'"></metric>
<alert v-if="tabId==='alert'" :moduleId="detailsObj.id"></alert>
<metric v-if="tabId==='metric'" :moduleId="detailsObj.id"></metric>
</div>
</div>
</template>
@@ -20,9 +20,7 @@ import metric from './metric.vue'
export default {
name: 'integration-tabs',
props: {
detailsObj: {
type: Object
}
detailsObj: Object
},
components: {
configuration,

View File

@@ -1,6 +1,50 @@
<template>
<div class="integration-metric">
<p>metric</p>
<div class="list-page">
<div class="nz-table-list">
<el-table
v-my-loading="loading"
ref="dataTable"
:height="'100%'"
:data="tableData"
border
@header-dragend="dragend"
@selection-change="selectionChange"
>
<el-table-column
v-for="(item, index) in tableTitle"
:key="`col-${index}`"
:label="item.label"
:min-width="`${item.minWidth}`"
:prop="item.prop"
:resizable="true"
:width="`${item.width}`"
class="data-column"
:sortable="item.sortable"
>
<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 === 'type'">
</template>
<span v-else-if="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
<template v-else>-</template>
</template>
</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>
</div>
</div>
</div>
</template>
@@ -8,19 +52,49 @@
export default {
name: 'integration-metric',
props: {
active: Boolean
moduleId: Number
},
data () {
return {
tableTitle: [
{
label: this.$t('overall.name'),
prop: 'name',
minWidth: 180
}, {
label: this.$t('overall.remark'),
prop: 'remark',
show: true,
minWidth: 250
}, {
label: this.$t('alert.config.unit'),
prop: 'unit',
width: 150
}
],
loading: false,
tableData: [],
batchObjs: []
}
},
mounted () {
this.getTableData()
},
methods: {
getData () {
}
async getTableData () {
this.loading = true
const res = await this.$get('/integration/metadata', { moduleIds: this.moduleId, pageSize: -1 })
this.tableData = res.data.list
this.loading = false
},
watch: {
selectionChange (objs) {
this.batchObjs = objs
},
dragend () {
this.$nextTick(() => {
this.$refs.dataTable.doLayout()
})
}
}
}
</script>

View File

@@ -3,7 +3,7 @@
<!-- NZ-talon -->
<p class="integration-title" style="margin-top:10px;">NZ-talon</p>
<ul class="integration-list">
<li class="integration-item" @click="details">
<li class="integration-item">
<img class="integration-icon" src="https://static.datadoghq.com/static/images/logos/azure_avatar.svg" alt="">
<h2 class="integration-name">NZ-talontalontalontalontalontalontalontalontalontalon</h2>
<p class="integration-remark">Check content name check contentname check content Check content name name check content name check content namecheck content namecheck content namecheck content name</p>
@@ -33,11 +33,11 @@
<!-- introduce -->
<div class="integration-dialog-top">
<div class="integration-dialog-top-logo">
<img src="https://static.datadoghq.com/static/images/logos/azure_avatar.svg" alt="">
<img :src="detailsObj.icon" alt="">
</div>
<div class="integration-dialog-introduce">
<h2 class="integration-name">Azure Usage and Quotas</h2>
<p class="integration-remark">Azure Usage and Quotas allows you to keep track of your current usages and limits limilimitslimitstslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimitslimits.</p>
<h2 class="integration-name">{{detailsObj.name}}</h2>
<p class="integration-remark">{{detailsObj.remark}}</p>
</div>
</div>
<!-- tabs -->
@@ -66,7 +66,6 @@ export default {
async getDataList () {
const res = await this.$get('/integration/module', { pageSize: -1 })
this.dataList = res.data.list
console.log(res)
},
// 详情
details (val) {