Commit 40b419d8 by 史敦盼

数据成图

1 parent c7cd055f
......@@ -14,6 +14,7 @@
></script>
<script type="text/javascript" src="./jsmind/dom-to-image.js"></script>
<script type="text/javascript" src="./jsmind/jsmind.screenshot.js"></script>
<script type="text/javascript" src="./mxClient.min.js"></script>
<!-- <script type="text/javascript" src="./echarts.min.js"></script> -->
</head>
<body>
......
This diff could not be displayed because it is too large.
......@@ -553,6 +553,15 @@ export const routes = [
keepAlive: true
},
},
{
path: '/main/dataMapping', // 数据成图
name: 'dataMapping',
component: () => import('@/views/dataMapping/index.vue'),
meta: {
title: '数据成图',
keepAlive: true
},
},
],
},
]
......
......@@ -88,6 +88,10 @@ export const menuOptions = [
],
},
{
name: '数据成图',
path: '/main/dataMapping',
},
{
name: '企业中台服务清单',
path: '/main/comCenterServeList',
},
......
<template>
<div id="mxGraph_root" class="w-100 h-100"></div>
</template>
<script>
export default {
data() {
return {
graph: null,
model: null,
graphData: []
}
},
components: {},
computed: {
mockData() {
return this.$store.state.graphData.graphData
},
},
mounted() {
this.graph = new mxGraph(document.getElementById('mxGraph_root'))
this.model = this.graph.getModel()
console.log('this.model', this.model)
// console.log('this.graph', this.graph)
},
methods: {
clear() {
this.model.clear()
},
init() {
this.graphData = [{
name: '业务能力视图',
children: this.mockData
}]
console.log('mockData', this.mockData)
// mxgraph 被暴露在window下,所以可以直接调用
const parent = this.graph.getDefaultParent()
this.graph.removeCells(this.graph.getChildVertices(parent)); //清空画布
const model = this.graph.getModel()
// 启动一次更新会话
model.beginUpdate()
try {
//设置元素可编辑,不然无法自动布局
this.graph.setCellsLocked(false)
// 插入一个矩形
const v1 = this.graph.insertVertex(
parent,
null,
this.graphData[0].name,
20,
20,
null,
null,
'html=1;fontColor=#000000;fillColor=#dcf8e5;labelPosition=center;verticalAlign=top;align=center;strokeColor=#7fc2a0;',
)
this.insertVertex(v1, this.graphData[0].children)
// console.log(v1)
console.log('parent', parent)
// 调整父节点宽高
var geometry = model.getGeometry(parent.children[0])
geometry.height += 40
geometry.width += 40
model.setGeometry(v1, geometry)
// 子节点宽高调整
this.setGeometry(parent.children[0].children)
return
// 重新调整整体布局
const allCellData = parent.children[0].children
// 获取最大宽度
let maxWidthArr = []
let maxHeight = 0
allCellData.forEach(v => {
const currentItem = model.getGeometry(v)
maxWidthArr.push(currentItem.width)
})
const maxWidth = Math.max(...maxWidthArr)
allCellData.forEach((v, i) => {
let currentMiddleItemGeometry = model.getGeometry(v)
// let lastMiddleItemGeometry = model.getGeometry(allCellData[i - 1])
if(i > 2) {
// 计算中间每条的坐标值
let lastGeoArr = allCellData.filter((v, i2) => i2 < i && i2 > 2 )
let y = 20
lastGeoArr.forEach(val => {
const cur = model.getGeometry(val)
y += cur.height + 20
})
currentMiddleItemGeometry.y = y
// console.log('currentMiddleItemGeometry', currentMiddleItemGeometry.y)
currentMiddleItemGeometry.width = maxWidth
}
// 右侧
if(i == 1) {
const lastMiddleItemGeometry = model.getGeometry(allCellData[i - 1])
// console.log(maxWidth, maxWidthArr, lastMiddleItemGeometry)
currentMiddleItemGeometry.x = maxWidth + lastMiddleItemGeometry.width + 60
// currentMiddleItemGeometry.height = maxHeight
}
if(i === 0) {
// currentMiddleItemGeometry.height = maxHeight
}
})
} finally {
model.endUpdate()
// 获取xml
var encoder = new mxCodec()
var node = encoder.encode(model)
console.log('node', node)
}
},
insertVertex(node, list) {
if (list && list.length) {
list.forEach((v, idx) => {
var cell = this.graph.insertVertex(
node,
null,
v.name,
this.getItemX(v, idx),
this.getItemY(v, idx),
// idx > 2 ? getItemY(idx, v.children) + 20 : 20,
v.checkChildren ? null : 100,
v.checkChildren ? null : 40,
`html=1;fontColor=#000000;fillColor=${
v.checkChildren ? '#dcf8e5' : '#f2fcf5'
};labelPosition=center;verticalAlign=${
v.checkChildren ? 'top' : 'middle'
};align=center;strokeColor=#7fc2a0;`,
)
// console.log('cell', cell)
if (v.checkChildren && v.checkChildren.length) {
this.insertVertex(cell, v.checkChildren)
}
})
}
},
// 计算cell的x坐标
getItemX(item, idx) {
if (item.children) {
return idx * (130 * 3) + 20
const col = (idx + 1) % 3
// console.log('col', idx, col)
// console.log('---', col > 0 ? col * (110 * 3) + 20 : 3 * (110 * 3) + 20 )
return col > 0 ? (col - 1) * (130 * 3) + 20 : 2 * (130 * 3) + 20
} else {
if (idx > 2) {
if ((idx + 1) % 3 === 1) {
return 20
} else if ((idx + 1) % 3 === 2) {
return 140
} else {
return 2 * 120 + 20
}
} else {
return idx * 120 + 20
}
}
},
getItemY(item, idx) {
const rows = Math.ceil((idx + 1) / 3)
if (item.children) {
return 20
const h = Math.ceil(item.children.length / 3)
if (idx > 2) {
return rows * (h * 50) + 20
} else {
return 30
}
} else {
if (idx > 2) {
console.log('rows', rows)
if (rows > 2) {
return rows * 40 + (rows - 2) * 20
} else {
return rows * 40
}
} else {
return 20
}
}
},
setGeometry(list) {
for (let index = 0; index < list.length; index++) {
const v = list[index]
if (!v.children) return
// console.log('v', v)
let geometry = this.model.getGeometry(v)
geometry.height += 20
geometry.width += 20
this.model.setGeometry(v, geometry)
// if (!v.children) {
// return this.setGeometry(v.children)
// }
}
},
},
}
</script>
<style scoped lang="scss"></style>
<!--
* @Description: 数据成图
* @Version: 2.0
* @Autor: pan
* @Date: 2024-04-23 11:30:05
* @LastEditors: pan
* @LastEditTime: 2024-04-24 15:42:01
-->
<template>
<div class="dataMapping w-100">
<div class="top-content-tab w-100">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane
:label="item.label"
:name="item.value"
v-for="item in tabOptions"
:key="item.value"
>
</el-tab-pane>
</el-tabs>
</div>
<div class="flex w-100 flex-1" style="min-height: 0">
<div class="left-content">
<div class="filter-input m-10">
<el-input placeholder="输入关键字进行过滤" v-model="filterText">
</el-input>
</div>
<div class="tree-content">
<!-- :check-strictly="true" -->
<el-tree
ref="tree"
default-expand-all
:highlight-current="true"
:data="treeData"
:props="treeProps"
show-checkbox
node-key="id"
check-on-click-node
:check-strictly="true"
:expand-on-click-node="false"
:filter-node-method="filterNode"
@check="handleNodeClick"
></el-tree>
</div>
<div class="flex-e-c m-10">
<el-button icon="el-icon-document-checked" type="primary" plain
>保存</el-button
>
<el-button
v-preventReClick
@click="fnGraph()"
icon="el-icon-picture-outline"
type="primary"
plain
>绘图</el-button
>
</div>
</div>
<div class="right-content flex-1">
<MxGraph ref="graph" />
</div>
</div>
</div>
</template>
<script>
import MxGraph from './MxGraph.vue'
import { getAutomaticGraphing, query_jia_gou_ceng_ci_new } from '@/api'
export default {
name: 'dataMapping',
data() {
return {
treeData: [],
treeProps: {
children: 'children',
label: 'assetName',
},
filterText: '',
graphData: [],
tabOptions: [],
activeName: '',
}
},
components: { MxGraph },
created() {
this.getOptions()
},
watch: {
filterText(val) {
this.$refs.tree.filter(val)
},
},
methods: {
handleClick() {
this.$refs['graph'].clear()
this.fnGetAutomaticGraphing()
},
getOptions() {
query_jia_gou_ceng_ci_new({ typeValue: 'archi_belong' }).then((res) => {
if (res.code == 200) {
this.tabOptions = res.data
this.activeName = this.tabOptions[0].value
this.fnGetAutomaticGraphing()
} else {
this.$message.warning(res.msg)
}
})
},
fnGraph() {
this.getCheckedNodes()
},
getCheckedNodes() {
console.log(this.$refs.tree.getCheckedNodes())
const checkedNodes = this.$refs.tree.getCheckedNodes()
this.graphData = checkedNodes.filter((v) => v.parentId === '0')
const childNodes = checkedNodes.filter((v) => v.parentId !== '0')
this.handleGraphData(this.graphData, childNodes)
console.log('this.graphData', this.graphData)
this.$store.commit('graphData/CHANGE_GRAPH_DATA', this.graphData)
this.$refs['graph'].init()
},
handleGraphData(parentNodes, childNodes) {
parentNodes.forEach((v) => {
v.checkChildren = []
childNodes.forEach((v2) => {
if (v.id === v2.parentId) {
v.checkChildren.push(v2)
}
})
})
},
getCheckedKeys() {
console.log(this.$refs.tree.getCheckedKeys())
},
fnGetAutomaticGraphing() {
getAutomaticGraphing({ archiBelongId: this.activeName }).then((res) => {
if (res.code == 200) {
this.treeData = res.data
}
})
},
filterNode(value, data) {
if (!value) return true
return data.assetName.indexOf(value) !== -1
},
handleNodeClick(data) {
const node = this.$refs.tree.getNode(data.id)
// console.log('data', data)
// console.log('node',node)
this.setNode(node)
},
setNode(node) {
if (node.checked) {
//如果当前是选中checkbox,则递归设置父节点和父父节点++选中
this.setParentNode(node)
} else {
//当前是取消选中,将所有子节点都取消选中
this.setChildenNode(node)
}
},
setParentNode(node) {
if (node.parent) {
for (const key in node) {
if (key === 'parent') {
node[key].checked = true
this.setParentNode(node[key])
}
}
}
},
setChildenNode(node) {
let len = node.childNodes.length
for (let i = 0; i < len; i++) {
node.childNodes[i].checked = false
this.setChildenNode(node.childNodes[i])
}
},
},
}
</script>
<style scoped lang="scss">
.dataMapping {
margin: 16px;
flex-direction: column;
display: flex;
.left-content {
width: 335px;
height: 100%;
// overflow-y: auto;
margin: 0 10px;
box-sizing: border-box;
// border: 1px solid #abeaee;
box-shadow: 0px 0px 2px 1px #abeaee;
.tree-content {
height: calc(100% - 120px);
overflow-y: auto;
}
}
.right-content {
height: 100%;
box-sizing: border-box;
background-color: rgb(255, 255, 255);
background-position: -1px -1px;
box-shadow: 0px 0px 2px 1px #d1d1d1;
overflow: auto;
background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImdyaWQiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTSAwIDEwIEwgNDAgMTAgTSAxMCAwIEwgMTAgNDAgTSAwIDIwIEwgNDAgMjAgTSAyMCAwIEwgMjAgNDAgTSAwIDMwIEwgNDAgMzAgTSAzMCAwIEwgMzAgNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2QwZDBkMCIgb3BhY2l0eT0iMC4yIiBzdHJva2Utd2lkdGg9IjEiLz48cGF0aCBkPSJNIDQwIDAgTCAwIDAgMCA0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZDBkMGQwIiBzdHJva2Utd2lkdGg9IjEiLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JpZCkiLz48L3N2Zz4=');
}
/deep/ .el-tree {
flex: 1;
min-height: 0;
overflow: auto;
padding-right: 10px;
margin-bottom: 10px;
.el-tree-node__expand-icon.el-icon-caret-right.is-leaf {
background-color: #ffffff !important;
}
.el-tree-node__content:hover {
.is-leaf {
background-color: #f5f7fa !important;
}
}
}
/deep/
.el-tree--highlight-current
.el-tree-node.is-current
> .el-tree-node__content {
background-color: #c0ebe4 !important;
// color: #999999;
.is-leaf {
background-color: #c0ebe4 !important;
}
}
}
</style>
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!