mirror of
https://github.com/veops/cmdb.git
synced 2025-08-08 10:25:34 +08:00
relation view has been optimised
This commit is contained in:
@@ -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' } || {} "
|
||||
|
@@ -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=""view-" + (relationViews.views[view] || []).join("")" style="height:200px"></div>
|
||||
<div :id=""view-" + (relationViews.views[view].topo_flatten || []).join("")" 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
|
||||
|
||||
|
@@ -119,6 +119,7 @@ export default {
|
||||
.then(res => {
|
||||
this.$message.success(`添加成功`)
|
||||
this.onClose()
|
||||
this.$emit('refresh')
|
||||
})
|
||||
.catch(err => this.requestFailed(err))
|
||||
},
|
||||
|
@@ -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>
|
||||
|
Reference in New Issue
Block a user