relation view has been optimised

This commit is contained in:
pycook
2019-12-03 19:10:54 +08:00
parent 8ee7c6daf8
commit 92dd4c5dfe
13 changed files with 241 additions and 83 deletions

View File

@@ -68,7 +68,7 @@
</a-col>
</template>
<a-col :lg="!advanced && 6 || 24" :md="!advanced && 8 || 24" :sm="24" style="float: right">
<a-col :lg="!advanced && 6 || 24" :md="!advanced && 8 || 24" :sm="24" style="float: right; padding-left: 0">
<span
class="table-page-search-submitButtons"
:style="advanced && { float: 'right', overflow: 'hidden' } || {} "

View File

@@ -1,7 +1,13 @@
<template>
<div>
<a-card :bordered="true" title="关系视图定义面板">
<a-card-meta description="点击右键可选择节点"></a-card-meta>
<a-card-meta description="先打开右上角的开关,便可选择树的节点"></a-card-meta>
<a-switch
slot="extra"
@change="toggleSelect"
checkedChildren="on"
unCheckedChildren="off"
/>
<div
id="visualization"
style="height:400px"
@@ -9,7 +15,7 @@
@mouseup="mouseUp"
@mousemove="mouseMove">
</div>
<relation-view-form ref="relationViewForm"></relation-view-form>
<relation-view-form @refresh="reload" ref="relationViewForm"></relation-view-form>
</a-card>
<a-row :gutter="0">
@@ -23,7 +29,7 @@
v-for="view in Object.keys(relationViews.views)">
<a-card :bordered="true" :title="view">
<a slot="extra"><a-icon type="close" @click="deleteView(view)"></a-icon></a>
<div :id="&quot;view-&quot; + (relationViews.views[view] || []).join(&quot;&quot;)" style="height:200px"></div>
<div :id="&quot;view-&quot; + (relationViews.views[view].topo_flatten || []).join(&quot;&quot;)" style="height:200px"></div>
</a-card>
</a-col>
</a-row>
@@ -32,7 +38,6 @@
</template>
<script>
// 按需引入
import { DataSet, Network } from 'vis-network'
import { getCITypeRelations } from '@/api/cmdb/CITypeRelation'
import { getRelationView, deleteRelationView } from '@/api/cmdb/preference'
@@ -48,12 +53,15 @@ export default {
relationViews: { views: {} },
relations: [],
network: null,
options: {},
viewData: {},
container: null,
nodes: null,
edges: null,
canvas: null,
ctx: null,
drag: false,
canSelect: false,
rect: {},
drawingSurfaceImageData: null
}
@@ -61,6 +69,7 @@ export default {
created () {
this.create()
},
inject: ['reload'],
methods: {
create () {
getRelationView().then(res => {
@@ -145,30 +154,54 @@ export default {
// initialize your network!
this.container.oncontextmenu = () => { return false }
this.options = options
this.viewData = data
this.network = new Network(this.container, data, options)
this.canvas = this.network.canvas.frame.canvas
this.ctx = this.canvas.getContext('2d')
})
},
toggleSelect (checked) {
if (checked) {
this.canSelect = true
this.options.autoResize = false
this.options.interaction.hover = false
this.options.interaction.dragView = false
this.options.interaction.dragNodes = false
this.network = new Network(this.container, this.viewData, this.options)
this.canvas = this.network.canvas.frame.canvas
this.ctx = this.canvas.getContext('2d')
} else {
this.canSelect = false
this.options.autoResize = true
this.options.interaction.hover = true
this.options.interaction.dragView = true
this.options.interaction.dragNodes = true
this.network = new Network(this.container, this.viewData, this.options)
this.canvas = this.network.canvas.frame.canvas
this.ctx = this.canvas.getContext('2d')
}
},
createRelationViews () {
Object.keys(this.relationViews.views).forEach(viewName => {
const nodes = []
const edges = []
const len = this.relationViews.views[viewName].length
this.relationViews.views[viewName].slice(0, len - 1).forEach((fromId, idx) => {
const len = this.relationViews.views[viewName].topo_flatten.length
this.relationViews.views[viewName].topo_flatten.slice(0, len - 1).forEach((fromId, idx) => {
nodes.push({
id: fromId,
label: this.relationViews.id2type[fromId].alias
})
edges.push({
from: fromId,
to: this.relationViews.views[viewName][idx + 1]
to: this.relationViews.views[viewName].topo_flatten[idx + 1]
})
})
nodes.push({
id: this.relationViews.views[viewName][len - 1],
label: this.relationViews.id2type[this.relationViews.views[viewName][len - 1]].alias
id: this.relationViews.views[viewName].topo_flatten[len - 1],
label: this.relationViews.id2type[this.relationViews.views[viewName].topo_flatten[len - 1]].alias
})
const _nodes = new DataSet(nodes)
const _edges = new DataSet(edges)
@@ -208,9 +241,9 @@ export default {
}
}
setTimeout(() => {
const container = document.querySelector('#view-' + this.relationViews.views[viewName].join(''))
const container = document.querySelector('#view-' + this.relationViews.views[viewName].topo_flatten.join(''))
const n = new Network(container, data, options)
console.log(n)
console.log(n) // TODO
}, 100)
})
},
@@ -274,7 +307,7 @@ export default {
},
mouseDown () {
if (event.button === 2) {
if (event.button === 0 && this.canSelect) {
this.saveDrawingSurface()
this.rect.startX = event.offsetX
this.rect.startY = event.offsetY
@@ -284,7 +317,7 @@ export default {
},
mouseUp () {
if (event.button === 2) {
if (event.button === 0 && this.canSelect) {
this.restoreDrawingSurface()
this.drag = false

View File

@@ -119,6 +119,7 @@ export default {
.then(res => {
this.$message.success(`添加成功`)
this.onClose()
this.$emit('refresh')
})
.catch(err => this.requestFailed(err))
},

View File

@@ -1,6 +1,6 @@
<template>
<a-card :bordered="false">
<a-menu v-model="current" mode="horizontal" v-if="relationViews.name2id && relationViews.name2id.length">
<a-card :bordered="false" class="relation-card">
<a-menu v-model="currentView" mode="horizontal" v-if="relationViews.name2id && relationViews.name2id.length">
<a-menu-item :key="item[1]" v-for="item in relationViews.name2id">
<router-link
:to="{name: 'cmdb_relation_views_item', params: { viewId: item[1]} }"
@@ -15,9 +15,14 @@
<a-tree showLine :loadData="onLoadData" @select="onSelect" :treeData="treeData"></a-tree>
</a-col>
<a-col :span="19">
<search-form ref="search" @refresh="refreshTable" :preferenceAttrList="preferenceAttrList" />
<a-menu v-model="currentTypeId" mode="horizontal" v-if="showTypeIds && showTypeIds.length > 1">
<a-menu-item :key="item.id" v-for="item in showTypes">
<a @click="changeCIType(item.id)">{{ item.alias || item.name }}</a>
</a-menu-item>
</a-menu>
<search-form style="margin-top: 10px" ref="search" @refresh="refreshTable" :preferenceAttrList="preferenceAttrList" />
<s-table
v-if="levels.length > 1"
v-if="levels.length"
bordered
ref="table"
size="middle"
@@ -49,16 +54,22 @@ export default {
},
data () {
return {
parameter: {},
treeData: [],
triggerSelect: false,
treeNode: null,
ciTypes: [],
relationViews: {},
levels: [],
showTypeIds: [],
showTypes: [],
leaf2showTypes: {},
leaf: [],
typeId: null,
viewId: null,
viewName: null,
current: [],
currentView: [],
currentTypeId: [],
instanceList: [],
treeKeys: [],
columns: [],
@@ -70,8 +81,9 @@ export default {
loadInstances: parameter => {
console.log(parameter, 'load instances')
this.parameter = parameter
const params = Object.assign(parameter || {}, this.$refs.search.queryParam)
let q = `q=_type:${this.levels[this.levels.length - 1]}`
let q = `q=_type:${this.currentTypeId[0]}`
Object.keys(params).forEach(key => {
if (!['pageNo', 'pageSize', 'sortField', 'sortOrder'].includes(key) && params[key] + '' !== '') {
if (typeof params[key] === 'object' && params[key].length > 1) {
@@ -109,15 +121,36 @@ export default {
if (res.numfound !== 0) {
setTimeout(() => {
this.setColumnWidth()
}, 200)
console.log('set column')
}, 300)
}
this.loadRoot()
return result
})
}
q += `&root_id=${this.treeKeys[this.treeKeys.length - 1]}`
q += `&level=${this.levels.length - this.treeKeys.length}`
q += `&root_id=${this.treeKeys[this.treeKeys.length - 1].split('_')[0]}`
const typeId = parseInt(this.treeKeys[this.treeKeys.length - 1].split('_')[1])
let level = []
if (!this.leaf.includes(typeId)) {
let startIdx = 0
this.levels.forEach((item, idx) => {
if (item.includes(typeId)) {
startIdx = idx
}
})
this.leaf.forEach(leafId => {
this.levels.forEach((item, levelIdx) => {
if (item.includes(leafId) && levelIdx - startIdx + 1 > 0) {
level.push(levelIdx - startIdx + 1)
}
})
})
} else {
level = [1]
}
q += `&level=${level.join(',')}`
if (q[0] === '&') {
q = q.slice(1)
}
@@ -133,10 +166,10 @@ export default {
if (res.numfound !== 0) {
setTimeout(() => {
this.setColumnWidth()
}, 200)
this.loadNoRoot(this.treeKeys[this.treeKeys.length - 1], this.levels.length - this.treeKeys.length - 1)
console.log('set column')
}, 300)
this.loadNoRoot(this.treeKeys[this.treeKeys.length - 1], level)
}
return result
})
}
@@ -161,40 +194,63 @@ export default {
this.$refs.table.refresh(bool)
},
loadRoot () {
searchCI(`q=_type:${this.levels[0]}&count=10000`).then(res => {
changeCIType (typeId) {
this.currentTypeId = [typeId]
this.loadColumns(typeId)
this.$refs.table.renderClear()
setTimeout(() => {
this.refreshTable(true)
}, 100)
},
async loadRoot () {
searchCI(`q=_type:(${this.levels[0].join(';')})&count=10000`).then(async res => {
const facet = []
const ciIds = []
res.result.forEach(item => {
facet.push([item[item.unique], 0, item.ci_id])
facet.push([item[item.unique], 0, item.ci_id, item.type_id])
ciIds.push(item.ci_id)
})
statisticsCIRelation({ root_ids: ciIds.join(','), level: this.levels.length - 1 }).then(num => {
facet.forEach((item, idx) => {
item[1] = num[ciIds[idx] + '']
const promises = this.leaf.map(leafId => {
let level = 0
this.levels.forEach((item, idx) => {
if (item.includes(leafId)) {
level = idx + 1
}
})
return statisticsCIRelation({ root_ids: ciIds.join(','), level: level }).then(num => {
facet.forEach((item, idx) => {
item[1] += num[ciIds[idx] + '']
})
})
this.wrapTreeData(facet)
})
await Promise.all(promises)
this.wrapTreeData(facet)
})
},
loadNoRoot (rootId, level) {
if (level === 0) {
return
}
searchCIRelation(`root_id=${rootId}&level=1&count=10000`).then(res => {
async loadNoRoot (rootIdAndTypeId, level) {
const rootId = rootIdAndTypeId.split('_')[0]
searchCIRelation(`root_id=${rootId}&level=1&count=10000`).then(async res => {
const facet = []
const ciIds = []
res.result.forEach(item => {
facet.push([item[item.unique], 0, item.ci_id])
facet.push([item[item.unique], 0, item.ci_id, item.type_id])
ciIds.push(item.ci_id)
})
statisticsCIRelation({ root_ids: ciIds.join(','), level: level }).then(num => {
facet.forEach((item, idx) => {
item[1] = num[ciIds[idx] + '']
})
this.wrapTreeData(facet)
const promises = level.map(_level => {
if (_level > 1) {
return statisticsCIRelation({ root_ids: ciIds.join(','), level: _level - 1 }).then(num => {
facet.forEach((item, idx) => {
item[1] += num[ciIds[idx] + '']
})
})
}
})
await Promise.all(promises)
this.wrapTreeData(facet)
})
},
@@ -214,8 +270,8 @@ export default {
facet.forEach(item => {
treeData.push({
title: `${item[0]} (${item[1]})`,
key: this.treeKeys.join('-') + '-' + item[2],
isLeaf: this.levels.length - 2 === this.treeKeys.length
key: this.treeKeys.join('-') + '-' + item[2] + '_' + item[3],
isLeaf: this.leaf.includes(item[3])
})
})
if (this.treeNode === null) {
@@ -269,16 +325,25 @@ export default {
this.viewName = item[0]
}
})
this.levels = this.relationViews.views[this.viewName]
this.current = [this.viewId]
this.typeId = this.levels[0]
this.levels = this.relationViews.views[this.viewName].topo
this.showTypes = this.relationViews.views[this.viewName].show_types
const showTypeIds = []
this.showTypes.forEach(item => {
showTypeIds.push(item.id)
})
this.showTypeIds = showTypeIds
this.leaf2showTypes = this.relationViews.views[this.viewName].leaf2show_types
this.leaf = this.relationViews.views[this.viewName].leaf
this.currentView = [this.viewId]
this.currentTypeId = [this.showTypeIds[0]]
this.typeId = this.levels[0][0]
this.loadColumns()
this.$refs.table && this.$refs.table.refresh(true)
}
})
},
loadColumns () {
getSubscribeAttributes(this.levels[this.levels.length - 1]).then(res => {
getSubscribeAttributes(this.currentTypeId[0]).then(res => {
const prefAttrList = res.attributes
this.preferenceAttrList = prefAttrList
@@ -309,11 +374,14 @@ export default {
}
</script>
<style scoped>
<style lang='less'>
.ant-menu-horizontal {
border-bottom: 1px solid #ebedf0 !important;
}
.ant-menu-horizontal {
border-bottom: 1px solid #ebedf0 !important;
}
.relation-card > .ant-card-body {
padding-top: 0 !important;
}
</style>