feat:集成页面搭建

This commit is contained in:
zyh
2023-02-22 18:32:54 +08:00
parent 1480e92c4c
commit cc599d102c
19 changed files with 906 additions and 295 deletions

View File

@@ -120,6 +120,7 @@
@import './page/monitor/project/project.scss';
@import './page/tool/ping.scss';
@import './page/tool/trace.scss';
@import './page/integration/integration.scss';
@import './common/v-selectpagenew/selectpage.scss';
@import './common/selectTable.scss';

View File

@@ -0,0 +1,284 @@
.integration{
width: 100%;
height: 100%;
background-color: $--background-color-empty;
padding: 20px;
box-sizing: border-box;
overflow-y: auto;
.integration-title{
font-family: Roboto-Medium;
font-size: 16px;
color: $--color-text-primary;
letter-spacing: 0;
font-weight: 600;
line-height: 100%;
}
.integration-list{
display: flex;
flex-wrap: wrap;
margin-left: -16px;
.integration-item{
margin-top: 16px;
margin-left: 16px;
width: 260px;
height: 214px;
border: 1px solid $--border-color-light;
border-radius: 4px;
padding: 0 20px;
box-sizing: border-box;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
transition: all 0.2s;
&:hover{
border: 1px solid $--color-primary;
background: rgba(250, 144, 28, 0.02);
}
.integration-icon{
margin-top: 30px;
width: 50px;
height: 50px;
}
.integration-name{
margin-top: 15px;
font-family: Roboto-Medium;
font-size: 14px;
color: $--color-text-primary;
letter-spacing: 0;
font-weight: 600;
width: 100%;
text-align: center;
line-height: 16px;
word-break: break-all;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.integration-remark{
margin-top: 20px;
font-family: Roboto-Regular;
font-size: 12px;
color: $--color-text-secondary;
letter-spacing: 0;
line-height: 16px;
font-weight: 400;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
}
.integration-internal{
padding: 0 8px;
border: 1px solid $--color-primary;
border-radius: 4px;
box-sizing: border-box;
height: 24px;
line-height: 24px;
text-align: center;
position: absolute;
right: 12px;
top: 12px;
color: $--color-primary;
font-size: 12px;
}
}
}
}
.integration-dialog{
&>.el-dialog{
width: 95%;
max-width: 1200px;
height: 90%;
max-height: 1024px;
transform: none;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto !important;
}
.el-dialog__header{
padding-top: 20px;
padding-bottom: 12px;
}
.el-dialog__body{
height: calc(100% - 32px);
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 0;
.integration-dialog-top{
display: flex;
align-items: center;
padding-bottom: 20px;
margin: 0 30px;
.integration-dialog-top-logo{
line-height: 0;
img{
width: 72px;
height: 72px;
}
}
.integration-dialog-introduce{
width: calc(100% - 72px);
padding-left: 25px;
box-sizing: border-box;
.integration-name{
font-family: Roboto-Medium;
font-size: 16px;
color: $--color-text-primary;
letter-spacing: 0;
font-weight: 600;
line-height: 20px;
}
.integration-remark{
margin-top: 8px;
font-family: Roboto-Regular;
font-size: 14px;
color: $--color-text-secondary;
letter-spacing: 0;
line-height: 16px;
font-weight: 400;
}
}
}
.integration-dialog-content{
flex: 1;
overflow: hidden;
}
}
}
.integration-tabs{
width: 100%;
height: 100%;
.integration-tabs-nav{
margin:0 30px;
height: 42px;
box-sizing: border-box;
border-bottom: 1px solid $--border-color-light;
display: flex;
.integration-tabs-nav-item{
width: 120px;
text-align: center;
cursor: pointer;
font-family: Roboto-Regular;
font-size: 14px;
color: $--color-text-regular;
font-weight: 400;
line-height: 42px;
position: relative;
}
.integration-tabs-nav-item.active{
color: $--color-primary;
&::after{
position: absolute;
left: 0;
right: 0;
bottom: 0;
content: "";
display: block;
height: 2px;
background-color: $--color-primary;
}
}
}
.integration-tabs-content{
height: calc(100% - 42px);
.integration-tool{
height: 60px;
display: flex;
justify-content: space-between;
align-items: center;
h3{
font-family: Roboto-Medium;
font-size: 14px;
color: $--color-text-primary;
font-weight: 600;
}
.nz-btn{
height: 30px;
padding: 0 10px;
border-radius: 4px;
i{
font-size: 16px;
}
span{
font-size: 14px;
}
}
}
.integration-configuration{
box-sizing: border-box;
padding: 30px;
padding-top: 15px;
height: 100%;
overflow-y: auto;
.integration-configuration-title{
font-family: Roboto-Medium;
font-size: 14px;
color: $--color-text-primary;
line-height: 20px;
font-weight: 600;
margin-top: 10px;
}
.integration-configuration-msg{
font-family: Roboto-Regular;
font-size: 14px;
color: $--color-text-regular;
line-height: 20px;
font-weight: 400;
margin-top: 6px;
&+p{
margin-top: 0;
}
}
.integration-configuration-pre{
width: 100%;
// max-height: 295px;
overflow-y: auto;
box-sizing: border-box;
padding: 14px;
background: $--select-page-hover-background-color;
border: 1px solid $--border-color-light;
opacity: 0.9;
border-radius: 2px;
overflow-wrap: break-word;
word-break: break-word;
white-space: pre-wrap;
margin-top: 6px;
}
}
.integration-dashboard{
box-sizing: border-box;
padding: 20px;
padding-top: 0;
padding-bottom: 30px;
height: 100%;
.dashboard-container{
height: calc(100% - 60px);
.table-list{
height: 100%;
.no-data {
text-align: center;
position: absolute;
width: 100%;
top: 50%;
margin-top: -54px;
.no-data-div {
color: $--color-text-regular;
}
}
}
}
.right-box.right-box-chart{
top: 0;
height: 100%;
}
}
}
}

View File

@@ -1273,7 +1273,7 @@ li {
&>span{
margin-right: 12px;
}
.exists-select{
.select-auto{
top: auto !important;
left: auto !important;
}

View File

@@ -16,6 +16,7 @@
:multipleTime="multipleTime"
:showAllData="showAllData"
@chartIsNoData="chartIsNoData"
:from="from"
></chart-time-series>
<chart-pie
:ref="'chart' + chartInfo.id"

View File

@@ -42,6 +42,7 @@ export default {
chartLegend: legend
},
props: {
from: String,
multipleTime: {},
minusTime: {}
},
@@ -113,6 +114,10 @@ export default {
this.isStack = this.chartInfo.param.stack
} catch (e) {}
const chartOption = lodash.cloneDeep(chartOptions)
// 防止tootip超出内容区域
if (this.from === 'integration' || this.from === 'dashboardTemp') {
chartOption.tooltip.appendToBody = false
}
if (this.chartInfo.isAlertMessage) {
chartOption.title = {
show: true,
@@ -528,4 +533,4 @@ export default {
this.chartInfo.loaded && this.initChart(this.chartOption)
}
}
</script>
</script>

View File

@@ -69,13 +69,13 @@
</div>
<!-- 全屏查看 -->
<el-dialog
class="nz-dialog chart-fullscreen"
v-if="fullscreen.visible"
:visible.sync="fullscreen.visible"
:show-close="false"
class="nz-dialog chart-fullscreen"
destroy-on-close
fullscreen
:modal-append-to-body="false"
:append-to-body="true"
>
<panel-chart
:ref="'chart-fullscreen' + fullscreen.chartInfo.id"

View File

@@ -225,7 +225,7 @@ export default {
switch (this.chartInfo.datasource) {
case 'metrics':
case 'logs': {
if (this.from === fromRoute.chartTemp || this.from === fromRoute.dashboardTemp) {
if (this.from === fromRoute.chartTemp || this.from === fromRoute.dashboardTemp || this.from === fromRoute.integration) {
setTimeout(() => {
this.chartData = [chartTempData.data.result]
this.chartData.forEach(item => {
@@ -669,6 +669,9 @@ export default {
if (this.chartInfo.type === 'group' && !flag) {
this.chartData = lodash.get(this, 'chartInfo.children', [])
}
if (!this.chartInfo.param) {
this.chartInfo.param = {}
}
this.chartInfo.param.collapse = flag
this.groupInit()
bus.$emit('groupMove', '', '', true)

View File

@@ -138,7 +138,6 @@
</nz-bottom-data-list>
<transition name="right-box">
<!-- <chart-box v-if="rightBox.chart.show" ref="addChartModal" :chart="chart" :from="from" :panel-data="panelData" :show-panel="showPanel" @close="closeRightBox" @delete-chart="delChart" @on-create-success="createSuccess" @on-delete-success="delChartOk"></chart-box> -->
<chart-right-box
v-if="chartRightBoxShow"
v-my-loading="rightBox.loading"
@@ -150,9 +149,7 @@
@close="closeRightBox"
@reload="panelReload"
@reloadOnlyPanel="panelReloadOnlyPanel"
@delete-chart="delChart"
@on-create-success="createSuccess"
@on-delete-success="delChartOk"
></chart-right-box>
</transition>
<transition name="right-box">
@@ -279,13 +276,11 @@ export default {
searchLabel: {}, // 搜索参数
// ---图表相关参数--start
dataList: [], // 数据列表
// searchName: '', // 搜索名称
filter: { // 过滤条件
// productId: 0,
panelId: 0,
start_time: '',
end_time: '',
searchName: ''
end_time: ''
},
showPanel: {
name: '',
@@ -505,10 +500,9 @@ export default {
this.chart.panelId = this.showPanel.id
this.chart.panelName = this.showPanel.name
this.chart.isGroup = true
this.rightBox.chart.show = true
},
delChartOk () {
this.getData(this.filter)
this.$nextTick(() => {
this.$refs.addChartModal.isStable = 'stable'
})
},
// 图表创建成功回调panel页面进行图表的刷新
createSuccess (msg, data, params) {
@@ -535,7 +529,6 @@ export default {
this.dataList = response.data.list.map(item => {
return {
...item,
hide: item.name.indexOf(this.filter.searchName) === -1, // 搜索条件
loaded: false
}
})
@@ -596,13 +589,10 @@ export default {
},
// 公用操作
getTableData (linkId) {
this.variablesInit = false
if (this.from === this.fromRoute.alertRule) {
this.variablesInit = true
this.getData(this.filter)
} else {
if (this.from === this.fromRoute.chartTemp) {
this.variablesInit = true
if (this.obj.type === 'group') {
this.$get('/visual/panel/chart', { ids: this.obj.id }).then(res => {
this.panelDataList = res.data.list
@@ -706,11 +696,6 @@ export default {
this.pageObj.pageSize = val
this.getTableData(this.obj.id)
},
search () {
if (this.$refs.chartList) {
this.$refs.chartList.searchCharts(this.filter.searchName)
}
},
// 滚动事件触发下拉加载
onScroll () {
const _self = this
@@ -720,24 +705,6 @@ export default {
_self.$refs.chartList.onScroll(_self.scrollbarWrap.scrollTop)
}, 300))
},
focusInput () {
let classVal = document.getElementById('queryPanel').parentElement.getAttribute('class')
classVal = classVal.replace('query-input-inactive', 'query-input-active')
document.getElementById('queryPanel').parentElement.setAttribute('class', classVal)
this.$refs.queryPanel.focus()
},
blurInput () {
if (!this.filter.searchName || this.filter.searchName == '') {
setTimeout(function () {
let classVal = document.getElementById('queryPanel').parentElement.getAttribute('class')
classVal = classVal.replace('query-input-active', 'query-input-inactive')
document.getElementById('queryPanel').parentElement.setAttribute('class', classVal)
}, 100)
}
},
clearInput () {
this.$refs.queryPanel.focus()
},
syncChart () {
if (this.from == this.fromRoute.asset || this.from == this.fromRoute.model) {
this.$confirm(this.$t('tip.syncTip'), {
@@ -891,12 +858,6 @@ export default {
})
},
watch: {
'filter.searchName' (n, o) {
const temp = this
setTimeout(function () {
temp.search()
}, 1000)
},
obj: {
immediate: true,
handler (n, o) {

View File

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

View File

@@ -1,6 +1,6 @@
<template>
<div>
<el-dropdown trigger="click" :size="size" class="nz-el-dropdown">
<el-dropdown trigger="click" :size="size" class="nz-el-dropdown" v-if="type!=='integration'">
<button id="more" :class="triggerButtonClass" :title="$t('overall.more')">
<i class="nz-icon nz-icon-more2"></i>
</button>
@@ -26,209 +26,211 @@
<slot name="after"></slot>
</template>
</el-dropdown-menu>
</el-dropdown>
<el-dialog
:close-on-click-modal="importBox.type!=3"
destroy-on-close
:show-close="true"
:title="importBox.title"
:visible.sync="importBox.show"
width="580px"
:append-to-body="true"
@close="closeDialog"
:class="{'import-failContent-dialog':importBox.type==3}"
class="nz-dialog">
<slot v-else></slot>
<!-- 新版导入 -->
<div v-if="importBox.type == 1">
<div class="upload-body">
<el-upload :id="id+'-xlsx-input-file'" ref="uploadExcel" :auto-upload="false" :file-list="importFileList" :on-change="importChange" :accept="!isDashboard?'.xlsx,.xls,.csv,.json':'.json'" action="" class="import-upload" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">{{$t('overall.dragFileTip')}}{{$t('overall.or')}}&nbsp;<em>{{$t('overall.clickUpload')}}</em></div>
<div class="el-upload__tip" >{{!isDashboard?$t('overall.importSupport'):$t('overall.supportJson')}}</div>
</el-upload>
</div>
<div class="import-select">
<div class="exists">
<span>{{$t('overall.existed')}}</span>
<el-select v-model="importBox.existed" :popper-append-to-body="false" style="flex:1" size="medium" popper-class="exists-select">
<el-option
v-for="item in existedArr"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</div>
<ul class="import-select-list">
<li class="import-select-item">
<el-checkbox v-model="importBox.ignoreError">{{$t('overall.ignoreError')}}</el-checkbox>
</li>
<li v-if="showSyncDashboard" class="import-select-item">
<el-checkbox v-model="importBox.syncDashboard">{{$t('overall.syncDashboard')}}</el-checkbox>
</li>
<li v-if="showSyncEndpoint" class="import-select-item">
<el-checkbox v-model="importBox.syncEndpoint">{{$t('overall.syncEndpoint')}}</el-checkbox>
</li>
</ul>
</div>
<div class="footer">
<div class="el-message-box__btns" style="text-align: right;">
<el-popover
v-if="!isDashboard"
placement="bottom-start"
trigger="click">
<div class="template-pop">
<p style="margin-bottom:8px">{{$t('overall.selectTemplate')}}</p>
<el-radio-group v-model="importBox.templateFormat" size="small">
<el-radio-button :label="item.value" v-for="(item,index) in formatArr" :key="index" @click.native="downloadTemplate(item.value)">{{item.name}}</el-radio-button>
</el-radio-group>
</div>
<button slot="reference" :id="id+'-xlsx-import-template'" class="nz-btn el-button el-button--default el-button--small">
<span>{{$t('upload.template')}}</span>
<i class="el-icon-arrow-down el-icon--right"></i>
</button>
</el-popover>
<button :id="id+'-xlsx-import-add'" :class="{'nz-btn-disabled':prevent_opt.import}" :disabled="prevent_opt.import" class="nz-btn el-button el-button--default el-button--small" @click="importExcel">
<span>{{$t('overall.importExcel')}}</span>
</button>
<button :id="id+'-xlsx-import-esc'" class="nz-btn el-button el-button--default el-button--small" @click="closeDialog">
<span>{{$t('overall.cancel')}}</span>
</button>
</div>
</div>
<el-dialog
:close-on-click-modal="importBox.type!=3"
destroy-on-close
:show-close="true"
:title="importBox.title"
:visible.sync="importBox.show"
width="580px"
:append-to-body="true"
@close="closeDialog"
:class="{'import-failContent-dialog':importBox.type==3}"
class="nz-dialog">
<!-- 新版导入 -->
<div v-if="importBox.type == 1">
<div class="upload-body">
<el-upload :id="id+'-xlsx-input-file'" ref="uploadExcel" :auto-upload="false" :file-list="importFileList" :on-change="importChange" :accept="!isDashboard?'.xlsx,.xls,.csv,.json':'.json'" action="" class="import-upload" drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">{{$t('overall.dragFileTip')}}{{$t('overall.or')}}&nbsp;<em>{{$t('overall.clickUpload')}}</em></div>
<div class="el-upload__tip" >{{!isDashboard?$t('overall.importSupport'):$t('overall.supportJson')}}</div>
</el-upload>
</div>
<!-- 导出 -->
<div v-else-if="importBox.type == 2">
<div class="upload-body" style="height: 200px">
<div class="export-box">
<span class="export-title">{{$t('export.records')}}</span>
<el-radio-group v-model="importBox.record" size="small">
<el-radio-button :label="item.value" v-for="(item,index) in recordArr" :key="index" :disabled="item.value==='records'&&!deleteObjs.length">
{{item.name}}
<span v-if="item.value==='records'&&deleteObjs.length">({{deleteObjs.length}})</span>
</el-radio-button>
</el-radio-group>
</div>
<div class="export-box">
<span class="export-title">{{$t('export.fileFormat')}}</span>
<el-radio-group v-model="importBox.format" size="small">
<el-radio-button :label="item.value" v-for="(item,index) in formatArr" :key="index" :disabled="isDashboard&&item.name!='JSON'">{{item.name}}</el-radio-button>
</el-radio-group>
</div>
</div>
<div class="footer">
<div class="el-message-box__btns">
<button :id="id+'-xlsx-import-export'" class="nz-btn el-button--small nz-btn-style-normal" @click="exportData">
<span style="text-transform:Capitalize">{{$t('overall.exportExcel')}}</span>
</button>
<button :id="id+'-xlsx-import-close'" class="nz-btn el-button el-button--small el-button--default" @click="closeDialog">
<span>{{$t('overall.close')}}</span>
</button>
</div>
<div class="import-select">
<div class="exists">
<span>{{$t('overall.existed')}}</span>
<el-select v-model="importBox.existed" :popper-append-to-body="false" style="flex:1" size="medium" popper-class="select-auto">
<el-option
v-for="item in existedArr"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</div>
<ul class="import-select-list">
<li class="import-select-item">
<el-checkbox v-model="importBox.ignoreError">{{$t('overall.ignoreError')}}</el-checkbox>
</li>
<li v-if="showSyncDashboard" class="import-select-item">
<el-checkbox v-model="importBox.syncDashboard">{{$t('overall.syncDashboard')}}</el-checkbox>
</li>
<li v-if="showSyncEndpoint" class="import-select-item">
<el-checkbox v-model="importBox.syncEndpoint">{{$t('overall.syncEndpoint')}}</el-checkbox>
</li>
</ul>
</div>
<!-- 导入结果展示导出失败记录 -->
<div v-if="importBox.type==3">
<div class="upload-body result-body">
<!-- 失败提示 -->
<div v-if="importResult&&importResult.failNum">
<!-- success number-->
<div class="result-title-top">
<div class="result-number">
<span>
<i class="nz-icon nz-icon-import-success"/>
{{$t('overall.result.successful')}}
</span>
<span>{{importResult.successNum}}</span>
</div>
<div class="result-number" style="padding-left:20px;">
<span>
<i class="nz-icon nz-icon-New"/>
{{$t('overall.result.newQuantity')}}
</span>
<span>{{importResult.addNum}}</span>
</div>
<div class="result-number" style="padding-left:20px;">
<span>
<i class="nz-icon nz-icon-Update"/>
{{$t('overall.result.updates')}}
</span>
<span>{{importResult.updateNum}}</span>
</div>
<!-- fail number-->
<div class="result-number fail">
<span>
<i class="nz-icon nz-icon-import-failed"/>
{{$t('overall.result.fail')}}
</span>
<span>{{importResult.failNum}}</span>
</div>
<div class="footer">
<div class="el-message-box__btns" style="text-align: right;">
<el-popover
v-if="!isDashboard"
placement="bottom-start"
trigger="click">
<div class="template-pop">
<p style="margin-bottom:8px">{{$t('overall.selectTemplate')}}</p>
<el-radio-group v-model="importBox.templateFormat" size="small">
<el-radio-button :label="item.value" v-for="(item,index) in formatArr" :key="index" @click.native="downloadTemplate(item.value)">{{item.name}}</el-radio-button>
</el-radio-group>
</div>
<div>
<div v-if="importResult&&importResult.failDetail" class="result-detail">
<div style="height: 100%; overflow: auto">
<template v-for="(item, index) in importResult.failDetail">
<div :key="index" class="import-result-block">
<div class="import-result-item">
<span class="import-result-item-left"></span>
<div class="import-result-item-right">
<span class="line-num">{{$t('overall.result.line',[item.lineNo])}}</span>
<span class="line-content" :title="item.errorMsg">{{item.errorMsg}}</span>
</div>
<button slot="reference" :id="id+'-xlsx-import-template'" class="nz-btn el-button el-button--default el-button--small">
<span>{{$t('upload.template')}}</span>
<i class="el-icon-arrow-down el-icon--right"></i>
</button>
</el-popover>
<button :id="id+'-xlsx-import-add'" :class="{'nz-btn-disabled':prevent_opt.import}" :disabled="prevent_opt.import" class="nz-btn el-button el-button--default el-button--small" @click="importExcel">
<span>{{$t('overall.importExcel')}}</span>
</button>
<button :id="id+'-xlsx-import-esc'" class="nz-btn el-button el-button--default el-button--small" @click="closeDialog">
<span>{{$t('overall.cancel')}}</span>
</button>
</div>
</div>
</div>
<!-- 导出 -->
<div v-else-if="importBox.type == 2">
<div class="upload-body" style="height: 200px">
<div class="export-box">
<span class="export-title">{{$t('export.records')}}</span>
<el-radio-group v-model="importBox.record" size="small">
<el-radio-button :label="item.value" v-for="(item,index) in recordArr" :key="index" :disabled="item.value==='records'&&!deleteObjs.length">
{{item.name}}
<span v-if="item.value==='records'&&deleteObjs.length">({{deleteObjs.length}})</span>
</el-radio-button>
</el-radio-group>
</div>
<div class="export-box">
<span class="export-title">{{$t('export.fileFormat')}}</span>
<el-radio-group v-model="importBox.format" size="small">
<el-radio-button :label="item.value" v-for="(item,index) in formatArr" :key="index" :disabled="isDashboard&&item.name!='JSON'">{{item.name}}</el-radio-button>
</el-radio-group>
</div>
</div>
<div class="footer">
<div class="el-message-box__btns">
<button :id="id+'-xlsx-import-export'" class="nz-btn el-button--small nz-btn-style-normal" @click="exportData">
<span style="text-transform:Capitalize">{{$t('overall.exportExcel')}}</span>
</button>
<button :id="id+'-xlsx-import-close'" class="nz-btn el-button el-button--small el-button--default" @click="closeDialog">
<span>{{$t('overall.close')}}</span>
</button>
</div>
</div>
</div>
<!-- 导入结果展示导出失败记录 -->
<div v-if="importBox.type==3">
<div class="upload-body result-body">
<!-- 失败提示 -->
<div v-if="importResult&&importResult.failNum">
<!-- success number-->
<div class="result-title-top">
<div class="result-number">
<span>
<i class="nz-icon nz-icon-import-success"/>
{{$t('overall.result.successful')}}
</span>
<span>{{importResult.successNum}}</span>
</div>
<div class="result-number" style="padding-left:20px;">
<span>
<i class="nz-icon nz-icon-New"/>
{{$t('overall.result.newQuantity')}}
</span>
<span>{{importResult.addNum}}</span>
</div>
<div class="result-number" style="padding-left:20px;">
<span>
<i class="nz-icon nz-icon-Update"/>
{{$t('overall.result.updates')}}
</span>
<span>{{importResult.updateNum}}</span>
</div>
<!-- fail number-->
<div class="result-number fail">
<span>
<i class="nz-icon nz-icon-import-failed"/>
{{$t('overall.result.fail')}}
</span>
<span>{{importResult.failNum}}</span>
</div>
</div>
<div>
<div v-if="importResult&&importResult.failDetail" class="result-detail">
<div style="height: 100%; overflow: auto">
<template v-for="(item, index) in importResult.failDetail">
<div :key="index" class="import-result-block">
<div class="import-result-item">
<span class="import-result-item-left"></span>
<div class="import-result-item-right">
<span class="line-num">{{$t('overall.result.line',[item.lineNo])}}</span>
<span class="line-content" :title="item.errorMsg">{{item.errorMsg}}</span>
</div>
</div>
</template>
</div>
<i class="nz-icon nz-icon-override" @click="copyFailDetail(importResult.failDetail)"></i>
</div>
</div>
</div>
<!-- 成功提示 -->
<div v-else class="result-success-box">
<div style="height:80px;line-height:80px;">
<i class="nz-icon nz-icon-import-success" style="margin-right:0" />
</div>
<div style="margin-top:30px">
<div class="success-number">
<span>
{{$t('overall.result.importedRecords')}}
</span>
<span>{{importResult.successNum}}</span>
</div>
<div class="success-number" style="margin-top:8px">
<span>
<i class="nz-icon nz-icon-New"/>
{{$t('overall.result.newRecords')}}
</span>
<span>{{importResult.addNum}}</span>
</div>
<div class="success-number" style="margin-top:4px">
<span>
<i class="nz-icon nz-icon-Update"/>
{{$t('overall.result.updatedRecords')}}
</span>
<span>{{importResult.updateNum}}</span>
</div>
</template>
</div>
<i class="nz-icon nz-icon-override" @click="copyFailDetail(importResult.failDetail)"></i>
</div>
</div>
</div>
<div class="footer">
<div class="el-message-box__btns">
<button v-if="importResult&&importResult.failNum" :id="id+'-xlsx-import-downloadFail'" class="nz-btn el-button el-button--small nz-btn-style-error" @click="downloadFail">
<span>{{$t('overall.result.downloadFail')}}</span>
</button>
<button :id="id+'-xlsx-import-close'" class="nz-btn el-button el-button--small el-button--default" @click="closeDialog">
<span>{{$t('overall.close')}}</span>
</button>
<!-- 成功提示 -->
<div v-else class="result-success-box">
<div style="height:80px;line-height:80px;">
<i class="nz-icon nz-icon-import-success" style="margin-right:0" />
</div>
<div style="margin-top:30px">
<div class="success-number">
<span>
{{$t('overall.result.importedRecords')}}
</span>
<span>{{importResult.successNum}}</span>
</div>
<div class="success-number" style="margin-top:8px">
<span>
<i class="nz-icon nz-icon-New"/>
{{$t('overall.result.newRecords')}}
</span>
<span>{{importResult.addNum}}</span>
</div>
<div class="success-number" style="margin-top:4px">
<span>
<i class="nz-icon nz-icon-Update"/>
{{$t('overall.result.updatedRecords')}}
</span>
<span>{{importResult.updateNum}}</span>
</div>
</div>
</div>
</div>
<div class="footer">
<div class="el-message-box__btns">
<button v-if="importResult&&importResult.failNum" :id="id+'-xlsx-import-downloadFail'" class="nz-btn el-button el-button--small nz-btn-style-error" @click="downloadFail">
<span>{{$t('overall.result.downloadFail')}}</span>
</button>
<button :id="id+'-xlsx-import-close'" class="nz-btn el-button el-button--small el-button--default" @click="closeDialog">
<span>{{$t('overall.close')}}</span>
</button>
</div>
</div>
</div>
</el-dialog>
</el-dropdown>
</el-dialog>
<transition name="right-box">
<panel-box v-if="rightBox.panel.show" ref="panelBox" :obj="panel" @close="closePanelBox" :isBottom="true" :panelType="params.from"></panel-box>
</transition>
@@ -273,7 +275,8 @@ export default {
deleteObjs: Array,
exportBoxShow: {
type: Boolean, default: false
}
},
type:String
},
computed: {
language () { return this.$store.getters.getLanguage },

View File

@@ -33,7 +33,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 && from!=='chartTemp' && from!=='dashboardTemp'"
v-if="showPanel.type !== fromRoute.project && showPanel.type !== fromRoute.asset && showPanel.type !== fromRoute.endpoint && showPanel.type !== fromRoute.model && from!=='dashboardTemp'"
:label="$t('overall.dashboard')"
prop="panelName"
>
@@ -48,14 +48,6 @@
</template>
</select-panel>
</el-form-item>
<!-- varType -->
<el-form-item :label="$t('dashboard.panel.chartForm.varType')" class="form-item--half-width" v-if="from === 'chartTemp'">
<el-select id="chart-box-varType" v-model="editChart.varType" :disabled="!!editChart.id" class="right-box__select" popper-class="right-box-select-top prevent-clickoutside" clearable placeholder="" size="small" value-key="chartType">
<el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in varTypeArr">
<span class="panel-dropdown-label-txt" >{{item.name}}</span>
</el-option>
</el-select>
</el-form-item>
<!--group-->
<el-form-item :label="$t('dashboard.panel.chartForm.group')" class="form-item--half-width" prop="group">
<el-select id="chart-box-group" v-model="editChart.groupId" :disabled="editChart.type==='group'" clearable placeholder="" popper-class="right-box-select-top prevent-clickoutside" size="small" value-key="chartType">

View File

@@ -43,11 +43,6 @@
</div>
<div class="top-tool-right">
<!-- <div class="top-tool-search margin-r-20">
<el-input id="queryPanel" ref="queryPanel" v-model="filter.searchName" class="query-input-inactive" clearable size="small" @blur="blurInput" @clear="clearInput" @focus="focusInput">
<i slot="suffix" class="el-input__icon nz-icon nz-icon-search" style="float: right" @click="focusInput"></i>
</el-input>
</div> -->
<pick-time id="panel" ref="pickTime" v-model="searchTime" :refresh-data-func="dateChange" :use-chart-unit="false" class="margin-r-10" :sign="showPanel.id"></pick-time>
@@ -141,9 +136,7 @@
@close="closeChartBox"
@reload="panelReload"
@reloadOnlyPanel="panelReloadOnlyPanel"
@delete-chart="delChart"
@on-create-success="createSuccess"
@on-delete-success="delChartOk"
></chart-right-box>
</transition>
<transition name="right-box">
@@ -324,7 +317,6 @@ export default {
panelId: 0,
start_time: '',
end_time: '',
searchName: '',
id: 4
},
panelId: 0,
@@ -396,8 +388,6 @@ export default {
return false
}
this.variablesInit = false
this.filter.searchName = ''
// this.$refs.searchInput.select();
this.showPanel = val
this.variables = this.$loadsh.get(this, 'showPanel.param.variables', []) || []
this.showPanel.type = 'dashboard'
@@ -643,12 +633,8 @@ export default {
}
},
closeChartBox (refresh) {
// this.rightBox.chart.show = false
this.chart = {}
this.$store.dispatch('clearPanel')
/* if (refresh) {
this.getData(this.filter)
} */
},
closeChartTempBox (refresh) {
this.rightBox.chartTemp.show = false
@@ -698,10 +684,6 @@ export default {
this.$store.dispatch('clearPanel')
})
},
delChartOk () {
this.filter.panelId = this.showPanel.id
this.getData(this.filter)
},
// 图表创建成功回调panel页面进行图表的刷新
createSuccess (msg, data, params, panel) {
this.filter.panelId = this.showPanel.id
@@ -740,7 +722,6 @@ export default {
this.dataList = response.data.list.map(item => {
return {
...item,
hide: item.name.indexOf(this.filter.searchName) === -1, // 搜索条件
loaded: false
}
})
@@ -926,11 +907,6 @@ export default {
this.pageObj.pageSize = val
this.getTableData()
},
search: function () {
if (this.$refs.chartList) {
// this.$refs.chartList.searchCharts(this.filter.searchName)
}
},
// 滚动事件触发下拉加载
onScroll () {
const _self = this
@@ -942,24 +918,6 @@ export default {
_self.showTopLine = _self.scrollbarWrap.scrollTop > 10
}))
},
focusInput () {
let classVal = document.getElementById('queryPanel').parentElement.getAttribute('class')
classVal = classVal.replace('query-input-inactive', 'query-input-active')
document.getElementById('queryPanel').parentElement.setAttribute('class', classVal)
this.$refs.queryPanel.focus()
},
blurInput () {
if (!this.filter.searchName || this.filter.searchName == '') {
setTimeout(function () {
let classVal = document.getElementById('queryPanel').parentElement.getAttribute('class')
classVal = classVal.replace('query-input-active', 'query-input-inactive')
document.getElementById('queryPanel').parentElement.setAttribute('class', classVal)
}, 100)
}
},
clearInput () {
this.$refs.queryPanel.focus()
},
tableListEnter () {
this.tableHover = true
},
@@ -1196,12 +1154,6 @@ export default {
}
}
},
'filter.searchName': function (n, o) {
const temp = this
setTimeout(function () {
temp.search()
}, 1000)
},
searchTime: {
immediate: true,
deep: true,
@@ -1271,6 +1223,8 @@ export default {
this.$store.commit('setCurrentMousemove', 0)
this.$store.commit('setConnect', 'none')
echarts.disconnect('timeSeriesGroup')
this.$store.commit('setMode', '')
}
}
</script>

View File

@@ -0,0 +1,26 @@
<template>
<div class="integration-alert">
<p>alert</p>
</div>
</template>
<script>
export default {
name: 'integration-alert',
props: {
active: Boolean
},
data () {
return {
}
},
methods: {
getData () {
}
},
watch: {
}
}
</script>

View File

@@ -0,0 +1,22 @@
<template>
<div class="integration-configuration">
<pre class="integration-configuration-pre">{{configuration}}</pre>
</div>
</template>
<script>
export default {
name: 'integration-configuration',
props: {
configuration: String
},
data () {
return {
}
},
methods: {
},
watch: {
}
}
</script>

View File

@@ -0,0 +1,191 @@
<template>
<div class="integration-dashboard">
<div class="integration-tool" style="padding: 0 10px;">
<h3>Dashboard name</h3>
<top-tool-more-options
type='integration'
ref="topTool"
id="integration-dashboard-tool"
:params="filter"
:params-type="'template'"
class="top-tool-export margin-r-10"
export-url="/visual/panel/export"
import-url="/visual/panel/import"
export-file-name="dashboard-temp"
@afterImport="afterImport"
>
<template>
<button class="nz-btn el-button--small nz-btn-style-normal" :class="{'nz-btn-disabled':prevent_opt.import}" @click="importFn">
<i class="nz-icon nz-icon-upload"></i>
<span>{{$t('overall.importExcel')}}</span>
</button>
</template>
</top-tool-more-options>
</div>
<div class="dashboard-container">
<!--图表-->
<div id="tableList" class="table-list" style='overflow-y: unset'>
<div class="table-list-box">
<div id="dashboardScrollbar" class="box-content" v-my-loading="chartListLoading" ref="dashboardScrollbar" style='overflow-y: auto;display: flex;flex-direction: column;overflow-x: hidden'>
<panel-variables :labelArrs="variables" :time-range="searchTime" @getPanelData="getPanelData"></panel-variables>
<chart-list
ref="chartList"
:variablesInit="variablesInit"
name="panel"
:panelId="showPanel.id"
:data-list="dataList"
:is-export-html="false"
:nowTimeType="nowTimeType"
:from="fromRoute.integration"
:time-range="searchTime"
:loading="chartListLoading"
></chart-list>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { chartCache } from '@/components/common/js/common'
import chartList from '@/components/chart/chartList'
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'
export default {
name: 'integration-dashboard',
props: {
dashboardTemplate: String
},
computed: {
chartRightBoxShow () {
return this.$store.getters.getShowRightBox
},
delChartFlag () {
return this.$store.getters.getDelChart
}
},
data () {
return {
fromRoute,
showTopBtn: false, // top按钮
chartListLoading: true,
searchTime: bus.getTimezontDateRange(),
panel: { // 新增panel
id: '',
name: ''
},
panelData: [],
// ---图表相关参数--start
dataList: [], // 数据列表
filter: {
},
showPanel: {
name: '',
type: 'dashboard',
id: null
},
nowTimeType: {},
scrollbarWrap: null,
variables: [],
variablesInit: false
}
},
components: {
chartList,
topToolMoreOptions,
panelVariables // 处理panel变量的组件
},
methods: {
importFn () {
},
afterImport () {
},
// 滚动事件触发下拉加载
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))
},
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
}
})
this.chartListLoading = false
},
// 公用操作
getTableData () {
this.panelData = JSON.parse(this.dashboardTemplate)
if (this.panelData.length > 0) {
this.showPanel = this.$loadsh.cloneDeep(this.panelData[0])
this.variables = this.$loadsh.get(this.panelData, '[0].param.variables')
this.getData()
} else {
this.chartListLoading = false
}
},
getPanelData () {
this.variablesInit = true
this.$nextTick(() => {
this.$refs.chartList.onScroll(this.scrollbarWrap.scrollTop)
})
}
},
mounted () {
this.scrollbarWrap = this.$refs.dashboardScrollbar
this.getTableData()
},
watch: {
// 监听图表联动配置panelId
'showPanel.param.chartShare': {
handler (value) {
// 每次切换联动模式 tooltip设置显示
const option = {
tooltip: {
className: 'chart-time-series'
}
}
for (const key in chartCache) {
if (!chartCache[key] || chartCache[key].group !== 'timeSeriesGroup') {
continue
}
chartCache[key].setOption(option)
}
this.$store.commit('setCurrentMousemove', 0)
if (value && value !== 'none') {
this.$store.commit('setConnect', value)
echarts.connect('timeSeriesGroup')
} else {
this.$store.commit('setConnect', value)
echarts.disconnect('timeSeriesGroup')
}
}
}
},
beforeDestroy () {
this.scrollbarWrap && this.scrollbarWrap.removeEventListener('scroll', bus.debounce)
// 页面销毁 清除图表联动
this.$store.commit('setCurrentMousemove', 0)
this.$store.commit('setConnect', 'none')
echarts.disconnect('timeSeriesGroup')
}
}
</script>

View File

@@ -0,0 +1,52 @@
<template>
<div class="integration-tabs">
<ul class="integration-tabs-nav">
<li class="integration-tabs-nav-item" :class="{active:tabId===item.id}" v-for="item in tabs" :key="item.id" @click="tabChange(item.id)">{{item.name}}</li>
</ul>
<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>
</div>
</div>
</template>
<script>
import configuration from './configuration.vue'
import dashboard from './dashboard.vue'
import alert from './alert.vue'
import metric from './metric.vue'
export default {
name: 'integration-tabs',
props: {
detailsObj: {
type: Object
}
},
components: {
configuration,
dashboard,
alert,
metric
},
data () {
return {
tabs:
[
{ id: 'configuration', name: this.$t('project.module.configs') },
{ id: 'dashboard', name: this.$t('overall.dashboard') },
{ id: 'alert', name: this.$t('overall.alert') },
{ id: 'metric', name: this.$t('overall.metric') }
],
tabId: 'configuration'
}
},
methods: {
tabChange (id) {
if (this.tabId === id) { return }
this.tabId = id
}
}
}
</script>

View File

@@ -0,0 +1,26 @@
<template>
<div class="integration-metric">
<p>metric</p>
</div>
</template>
<script>
export default {
name: 'integration-metric',
props: {
active: Boolean
},
data () {
return {
}
},
methods: {
getData () {
}
},
watch: {
}
}
</script>

View File

@@ -0,0 +1,85 @@
<template>
<div class="integration">
<!-- NZ-talon -->
<p class="integration-title" style="margin-top:10px;">NZ-talon</p>
<ul class="integration-list">
<li class="integration-item" @click="details">
<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>
<div class="integration-internal">{{$t('integration.internal')}}</div>
</li>
</ul>
<!-- Available Integration -->
<p class="integration-title" style="margin-top:20px;">{{$t('integration.availableIntegration')}}</p>
<ul class="integration-list">
<li class="integration-item" v-for="item in dataList" :key="item.id" @click="details(item)">
<img class="integration-icon" :src="item.icon" alt="">
<h2 class="integration-name">{{item.name}}</h2>
<p class="integration-remark">{{item.remark}}</p>
</li>
</ul>
<!-- 集成详情 -->
<el-dialog
class="integration-dialog"
v-if="dialogVisible"
:visible.sync="dialogVisible"
:show-close="true"
:append-to-body="false"
:z-index="1000"
@close="closeDialog"
>
<!-- 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="">
</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>
</div>
</div>
<!-- tabs -->
<div class="integration-dialog-content">
<integration-tabs :detailsObj="detailsObj"></integration-tabs>
</div>
</el-dialog>
</div>
</template>
<script>
import integrationTabs from './integration-tabs/integration-tabs.vue'
export default {
name: 'integration',
components: {
'integration-tabs': integrationTabs
},
data () {
return {
dialogVisible: false,
dataList: [],
detailsObj: {}
}
},
methods: {
async getDataList () {
const res = await this.$get('/integration/module', { pageSize: -1 })
this.dataList = res.data.list
console.log(res)
},
// 详情
details (val) {
this.detailsObj = val
this.dialogVisible = true
},
closeDialog () {
this.detailsObj = {}
this.dialogVisible = false
}
},
created () {
this.getDataList()
}
}
</script>

View File

@@ -219,6 +219,10 @@ export default new Router({
{
path: '/trace',
component: resolve => require(['@/components/page/tool/trace'], resolve)
},
{
path: '/integration',
component: resolve => require(['@/components/page/integration/integration'], resolve)
}
]
},