|
@@ -3,7 +3,7 @@
|
|
<div class="edb-history-page-wrap">
|
|
<div class="edb-history-page-wrap">
|
|
<div class="edb-title">{{currentLang==='en'?(treeData.EdbNameEn||treeData.EdbName):treeData.EdbName}}</div>
|
|
<div class="edb-title">{{currentLang==='en'?(treeData.EdbNameEn||treeData.EdbName):treeData.EdbName}}</div>
|
|
<div class="edb-source-wrap">
|
|
<div class="edb-source-wrap">
|
|
- <vue2-org-tree
|
|
|
|
|
|
+ <!-- <vue2-org-tree
|
|
:data="treeData"
|
|
:data="treeData"
|
|
:props="{
|
|
:props="{
|
|
label: 'EdbName',
|
|
label: 'EdbName',
|
|
@@ -12,17 +12,34 @@
|
|
:horizontal="false"
|
|
:horizontal="false"
|
|
:render-content="renderContent"
|
|
:render-content="renderContent"
|
|
@on-node-click="handleClickNode"
|
|
@on-node-click="handleClickNode"
|
|
- />
|
|
|
|
|
|
+ /> -->
|
|
|
|
+ <div class="sandbox-body">
|
|
|
|
+ <div class="sand-chart-body" id="sand-chart-body"></div>
|
|
|
|
+ <div id="minimap" class="minimap"></div>
|
|
|
|
+ </div>
|
|
</div>
|
|
</div>
|
|
|
|
+ <!-- 确定每个Node节点大小用 -->
|
|
|
|
+ <div id="mould"><span id="mould-text"></span></div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
|
|
|
|
<script>
|
|
<script>
|
|
import { dataBaseInterface } from '@/api/api.js';
|
|
import { dataBaseInterface } from '@/api/api.js';
|
|
|
|
+import { Graph} from '@antv/x6';
|
|
|
|
+import '@antv/x6-vue-shape'
|
|
|
|
+import toolTipCom from '../components/antvVueComponents/tooltipCom.vue';
|
|
|
|
+import dagre from "dagre"
|
|
export default {
|
|
export default {
|
|
|
|
+ components:{toolTipCom},
|
|
data() {
|
|
data() {
|
|
return {
|
|
return {
|
|
- treeData:{}
|
|
|
|
|
|
+ treeData:{},
|
|
|
|
+ graph:null,
|
|
|
|
+ mould:null,
|
|
|
|
+ mouldText:null,
|
|
|
|
+ params:{
|
|
|
|
+ stopNodeClick:false
|
|
|
|
+ }
|
|
};
|
|
};
|
|
},
|
|
},
|
|
computed: {
|
|
computed: {
|
|
@@ -31,33 +48,277 @@ export default {
|
|
}
|
|
}
|
|
},
|
|
},
|
|
methods: {
|
|
methods: {
|
|
- renderContent(h, data) {
|
|
|
|
- let name = this.currentLang === 'en'?(data.EdbNameEn||data.EdbName):data.EdbName;
|
|
|
|
-
|
|
|
|
- return (
|
|
|
|
- <el-tooltip content={data.RuleTitle} placement='top' popper-class='node-tooltip'>
|
|
|
|
- {
|
|
|
|
- data.IsStop?<span class='node stop'>{name+'(暂停更新)'}</span>
|
|
|
|
- :<span class='node'>{name}</span>
|
|
|
|
|
|
+ // renderContent(h, data) {
|
|
|
|
+ // return (
|
|
|
|
+ // <el-tooltip content={data.RuleTitle} placement='top' popper-class='node-tooltip'>
|
|
|
|
+ // {
|
|
|
|
+ // data.IsStop?<span class='node stop'>{data.EdbName+'(暂停更新)'}</span>
|
|
|
|
+ // :<span class='node'>{data.EdbName}</span>
|
|
|
|
+ // }
|
|
|
|
+ // </el-tooltip>
|
|
|
|
+ // )
|
|
|
|
+ // },
|
|
|
|
+ // handleClickNode(e, data) {
|
|
|
|
+ // //EdbInfoType=1 跳预测指标详情,=0跳指标库详情
|
|
|
|
+ // const { ClassifyId, UniqueCode, EdbInfoId, EdbInfoType } = data
|
|
|
|
+ // let { href } =
|
|
|
|
+ // this.$router.resolve({ path: EdbInfoType === 1 ? '/predictEdb' : '/database', query: { code: UniqueCode, id:
|
|
|
|
+ // EdbInfoId, classifyId: ClassifyId } });
|
|
|
|
+ // window.open(href, '_blank');
|
|
|
|
+ // },
|
|
|
|
+ async getData() {
|
|
|
|
+ const res = await dataBaseInterface.getEdbCreateHistory({ UniqueCode: this.$route.query.code})
|
|
|
|
+ if (res.Ret !== 200) return
|
|
|
|
+ this.treeData = res.Data;
|
|
|
|
+
|
|
|
|
+ this.$nextTick(()=>{
|
|
|
|
+ this.init()
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ init() {
|
|
|
|
+ this.graph=new Graph({
|
|
|
|
+ container: document.getElementById('sand-chart-body'),
|
|
|
|
+ autoResize: false,
|
|
|
|
+ async:true,//不异步时,显示隐藏会卡死
|
|
|
|
+ background: {
|
|
|
|
+ color: '#fff',
|
|
|
|
+ },
|
|
|
|
+ scroller: {
|
|
|
|
+ enabled: true,
|
|
|
|
+ pannable: true,
|
|
|
|
+ minVisibleWidth: 50,
|
|
|
|
+ minVisibleHeight: 50,
|
|
|
|
+ },
|
|
|
|
+ interacting:{
|
|
|
|
+ nodeMovable:false,
|
|
|
|
+ magnetConnectable:false,
|
|
|
|
+ edgeMovable:false,
|
|
|
|
+ edgeLabelMovable:false,
|
|
|
|
+ arrowheadMovable:false,
|
|
|
|
+ vertexMovable:false,
|
|
|
|
+ vertexMovable:false,
|
|
|
|
+ vertexDeletable:false
|
|
|
|
+ },
|
|
|
|
+ mousewheel:{
|
|
|
|
+ enabled: true,
|
|
|
|
+ modifiers:['ctrl','meta']
|
|
|
|
+ }, //滚轮缩放
|
|
|
|
+ scaling: {
|
|
|
|
+ min: 0.5,
|
|
|
|
+ max: 2
|
|
|
|
+ },
|
|
|
|
+ //小地图
|
|
|
|
+ minimap: {
|
|
|
|
+ enabled: true,
|
|
|
|
+ container: document.getElementById("minimap"),
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ this.graph.on('node:mousemove',()=>{
|
|
|
|
+ // 拖动画布的时候 阻止节点的点击操作
|
|
|
|
+ this.params.stopNodeClick=true
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ this.graph.on('node:mouseup',()=>{
|
|
|
|
+ // 延迟释放
|
|
|
|
+ requestAnimationFrame(()=>{
|
|
|
|
+ this.params.stopNodeClick=false
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ let that = this
|
|
|
|
+ Graph.registerVueComponent(
|
|
|
|
+ "custom-rect",
|
|
|
|
+ {
|
|
|
|
+ template: `<tool-tip-com :params="params"/>`,
|
|
|
|
+ components: {
|
|
|
|
+ toolTipCom,
|
|
|
|
+ },
|
|
|
|
+ router:this.$router, //将router传进去,不然组件里面拿不到
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ // 传一个对象进去
|
|
|
|
+ params:that.params,
|
|
}
|
|
}
|
|
- </el-tooltip>
|
|
|
|
|
|
+ },
|
|
|
|
+ },true);
|
|
|
|
+
|
|
|
|
+ Graph.registerEdge(
|
|
|
|
+ 'org-edge',
|
|
|
|
+ {
|
|
|
|
+ attrs: {
|
|
|
|
+ line: {
|
|
|
|
+ strokeWidth: 1,
|
|
|
|
+ stroke: '#dddddd',
|
|
|
|
+ sourceMarker: null,
|
|
|
|
+ targetMarker: null,
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ zIndex:0
|
|
|
|
+ },
|
|
|
|
+ true,
|
|
)
|
|
)
|
|
|
|
+
|
|
|
|
+ this.mould = document.getElementById('mould')
|
|
|
|
+ this.mouldText = document.getElementById('mould-text')
|
|
|
|
+
|
|
|
|
+ let edbName=this.treeData.EdbName+(this.treeData.IsStop?'(暂停更新)':'')
|
|
|
|
+ this.mouldText.innerText=edbName
|
|
|
|
+ let node = this.graph.createNode({
|
|
|
|
+ shape: 'vue-shape',
|
|
|
|
+ component: 'custom-rect',
|
|
|
|
+ width:this.mould.offsetWidth+1,
|
|
|
|
+ height:this.mould.offsetHeight,
|
|
|
|
+ attrs: {
|
|
|
|
+ body: {
|
|
|
|
+ rx: 4,
|
|
|
|
+ ry: 4,
|
|
|
|
+ strokeWidth: 1,
|
|
|
|
+ class:'body-class'
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ data:{
|
|
|
|
+ EdbName:edbName,
|
|
|
|
+ RuleTitle:this.treeData.RuleTitle,
|
|
|
|
+ routeQuery:{
|
|
|
|
+ ClassifyId:this.treeData.ClassifyId,
|
|
|
|
+ UniqueCode:this.treeData.UniqueCode,
|
|
|
|
+ EdbInfoId:this.treeData.EdbInfoId,
|
|
|
|
+ EdbInfoType:this.treeData.EdbInfoType
|
|
|
|
+ },
|
|
|
|
+ isRoot:true,
|
|
|
|
+ isLeaf:(this.treeData.Child && this.treeData.Child.length>0)?false:true,
|
|
|
|
+ style:{
|
|
|
|
+ color:this.treeData.IsStop?"red!important":'#ffffff!important',
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ let cells = [node,...this.createCells(this.treeData.Child,node)]
|
|
|
|
+ this.graph.resetCells(cells)
|
|
|
|
+ this.layout()
|
|
|
|
+ this.graph.positionCell(node,'top',{padding:{top:20}})
|
|
},
|
|
},
|
|
- handleClickNode(e, data) {
|
|
|
|
- //EdbInfoType=1 跳预测指标详情,=0跳指标库详情
|
|
|
|
- const { ClassifyId, UniqueCode, EdbInfoId, EdbInfoType,HaveOperaAuth } = data
|
|
|
|
- if(!HaveOperaAuth) return this.$message.warning(this.$t('MsgPrompt.no_edb_auth'))
|
|
|
|
|
|
+ createCells(list,parentNode){
|
|
|
|
+ if(!(list && list.length>0)){
|
|
|
|
+ return []
|
|
|
|
+ }
|
|
|
|
+ let dataList = []
|
|
|
|
+ list.forEach(element => {
|
|
|
|
+ let edbName=element.EdbName+(element.IsStop?'(暂停更新)':'')
|
|
|
|
+
|
|
|
|
+ this.mouldText.innerText=edbName
|
|
|
|
+ let node = this.graph.createNode({
|
|
|
|
+ shape: 'vue-shape',
|
|
|
|
+ component: 'custom-rect',
|
|
|
|
+ width:this.mould.offsetWidth+1,
|
|
|
|
+ height:this.mould.offsetHeight,
|
|
|
|
+ attrs: {
|
|
|
|
+ body: {
|
|
|
|
+ rx: 4,
|
|
|
|
+ ry: 4,
|
|
|
|
+ strokeWidth: 1,
|
|
|
|
+ class:'body-class'
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ data:{
|
|
|
|
+ style:{
|
|
|
|
+ backgroundColor:'#f2f6fa',
|
|
|
|
+ color:element.IsStop?"red!important":'#000000',
|
|
|
|
+ },
|
|
|
|
+ EdbName:edbName,
|
|
|
|
+ RuleTitle:element.RuleTitle,
|
|
|
|
+ routeQuery:{
|
|
|
|
+ ClassifyId:element.ClassifyId,
|
|
|
|
+ UniqueCode:element.UniqueCode,
|
|
|
|
+ EdbInfoId:element.EdbInfoId,
|
|
|
|
+ EdbInfoType:element.EdbInfoType
|
|
|
|
+ },
|
|
|
|
+ isRoot:false,
|
|
|
|
+ isLeaf:(element.Child && element.Child.length>0)?false:true
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ let side = this.graph.createEdge({
|
|
|
|
+ shape: 'org-edge',
|
|
|
|
+ source: { cell: parentNode.id },
|
|
|
|
+ target: { cell: node.id },
|
|
|
|
+ })
|
|
|
|
+ dataList.push(node)
|
|
|
|
+ dataList.push(side)
|
|
|
|
+ dataList=[...dataList,...this.createCells(element.Child,node)]
|
|
|
|
+ });
|
|
|
|
+ return dataList
|
|
|
|
+ },
|
|
|
|
+ layout(){
|
|
|
|
+ const dir = 'TB'
|
|
|
|
+ const nodes = this.graph.getNodes()
|
|
|
|
+ const edges = this.graph.getEdges()
|
|
|
|
+ const g = new dagre.graphlib.Graph()
|
|
|
|
+
|
|
|
|
+ g.setDefaultEdgeLabel(() => ({}))
|
|
|
|
+ nodes.forEach((node) => {
|
|
|
|
+ g.setNode(node.id, { width:node.size().width, height:node.size().height })
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ let heights=nodes.map(item =>{
|
|
|
|
+ // 为了防止重叠,不知道他内部怎么排的,先调整这样。
|
|
|
|
+ if(item.data.isLeaf){
|
|
|
|
+ return item.size().height*1.5-100
|
|
|
|
+ }else{
|
|
|
|
+ return item.size().height/2
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ let maxHeight = Math.max(...heights)
|
|
|
|
+ // console.log(maxHeight,'maxHeight');
|
|
|
|
+ g.setGraph({ rankdir: dir,nodesep:50,ranksep:maxHeight})
|
|
|
|
+ edges.forEach((edge) => {
|
|
|
|
+ const source = edge.getSource()
|
|
|
|
+ const target = edge.getTarget()
|
|
|
|
+ g.setEdge(source.cell, target.cell)
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ dagre.layout(g)
|
|
|
|
|
|
- let { href } =
|
|
|
|
- this.$router.resolve({ path: EdbInfoType === 1 ? '/predictEdb' : '/database', query: { code: UniqueCode, id:
|
|
|
|
- EdbInfoId, classifyId: ClassifyId } });
|
|
|
|
- window.open(href, '_blank');
|
|
|
|
|
|
+ g.nodes().forEach((id) => {
|
|
|
|
+ const node = this.graph.getCellById(id)
|
|
|
|
+ if (node) {
|
|
|
|
+ const pos = g.node(id)
|
|
|
|
+ node.position(pos.x, pos.y)
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ edges.forEach((edge) => {
|
|
|
|
+ const source = edge.getSourceNode()
|
|
|
|
+ const target = edge.getTargetNode()
|
|
|
|
+ const sourceBBox = source.getBBox()
|
|
|
|
+ const targetBBox = target.getBBox()
|
|
|
|
+
|
|
|
|
+ if ((dir === 'LR' || dir === 'RL') && sourceBBox.y !== targetBBox.y) {
|
|
|
|
+ const gap =
|
|
|
|
+ dir === 'LR'
|
|
|
|
+ ? targetBBox.x - sourceBBox.x - sourceBBox.width
|
|
|
|
+ : -sourceBBox.x + targetBBox.x + targetBBox.width
|
|
|
|
+ const fix = dir === 'LR' ? sourceBBox.width : 0
|
|
|
|
+ const x = sourceBBox.x + fix + gap / 2
|
|
|
|
+ edge.setVertices([
|
|
|
|
+ { x, y: sourceBBox.center.y },
|
|
|
|
+ { x, y: targetBBox.center.y },
|
|
|
|
+ ])
|
|
|
|
+ } else if (
|
|
|
|
+ (dir === 'TB' || dir === 'BT')) {
|
|
|
|
+ const gap =
|
|
|
|
+ dir === 'TB'
|
|
|
|
+ ? targetBBox.y - sourceBBox.y - sourceBBox.height
|
|
|
|
+ : -sourceBBox.y + targetBBox.y + targetBBox.height
|
|
|
|
+ const fix = dir === 'TB' ? sourceBBox.height : 0
|
|
|
|
+ const y = sourceBBox.y + fix + gap / 2
|
|
|
|
+
|
|
|
|
+ edge.setVertices([
|
|
|
|
+ { x: sourceBBox.center.x, y },
|
|
|
|
+ { x: targetBBox.center.x, y },
|
|
|
|
+ ])
|
|
|
|
+ } else {
|
|
|
|
+ edge.setVertices([])
|
|
|
|
+ }
|
|
|
|
+ })
|
|
},
|
|
},
|
|
- async getData() {
|
|
|
|
- const res = await dataBaseInterface.getEdbCreateHistory({ UniqueCode: this.$route.query.code})
|
|
|
|
- if (res.Ret !== 200) return
|
|
|
|
- this.treeData = res.Data;
|
|
|
|
- }
|
|
|
|
},
|
|
},
|
|
mounted(){
|
|
mounted(){
|
|
if(this.$route.query.code){
|
|
if(this.$route.query.code){
|
|
@@ -77,24 +338,48 @@ export default {
|
|
border-radius: 4px;
|
|
border-radius: 4px;
|
|
border:1px solid #C8CDD9;
|
|
border:1px solid #C8CDD9;
|
|
box-sizing: border-box;
|
|
box-sizing: border-box;
|
|
- padding:30px;
|
|
|
|
|
|
+ // padding:30px;
|
|
.edb-title{
|
|
.edb-title{
|
|
margin:0 -30px;
|
|
margin:0 -30px;
|
|
text-align: center;
|
|
text-align: center;
|
|
- padding-bottom: 30px;
|
|
|
|
|
|
+ padding: 30px;
|
|
border-bottom: 1px solid #C8CDD9;
|
|
border-bottom: 1px solid #C8CDD9;
|
|
font-size: 16px;
|
|
font-size: 16px;
|
|
}
|
|
}
|
|
.edb-source-wrap{
|
|
.edb-source-wrap{
|
|
text-align: center;
|
|
text-align: center;
|
|
- }
|
|
|
|
- .edb-source-wrap{
|
|
|
|
flex: 1;
|
|
flex: 1;
|
|
overflow: auto;
|
|
overflow: auto;
|
|
|
|
+ .sandbox-body{
|
|
|
|
+ height: 100%;
|
|
|
|
+ display: flex;
|
|
|
|
+ position: relative;
|
|
|
|
+ .minimap{
|
|
|
|
+ position:absolute;
|
|
|
|
+ right:6px;
|
|
|
|
+ bottom:6px;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ }
|
|
|
|
+ #sand-chart-body{
|
|
|
|
+ flex: 1;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ #mould{
|
|
|
|
+ position: absolute;
|
|
|
|
+ max-width: 100px;
|
|
|
|
+ padding: 20px;
|
|
|
|
+ background-color: red;
|
|
|
|
+ font-size:16px;
|
|
|
|
+ text-align: center;
|
|
|
|
+ border-radius: 4px;
|
|
|
|
+ top: -10000px;
|
|
|
|
+ opacity: 0;
|
|
|
|
+ word-break: break-all;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|
|
</style>
|
|
-<style lang="scss">
|
|
|
|
|
|
+<!-- <style lang="scss">
|
|
.edb-history-page-wrap{
|
|
.edb-history-page-wrap{
|
|
.org-tree-container {
|
|
.org-tree-container {
|
|
margin: 0 auto;
|
|
margin: 0 auto;
|
|
@@ -139,4 +424,32 @@ export default {
|
|
padding:10px;
|
|
padding:10px;
|
|
text-align: center;
|
|
text-align: center;
|
|
}
|
|
}
|
|
-</style>
|
|
|
|
|
|
+</style> -->
|
|
|
|
+<style lang="scss">
|
|
|
|
+.sandbox-body{
|
|
|
|
+ .x6-graph-scroller {
|
|
|
|
+ flex: 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .x6-port-body {
|
|
|
|
+ display: none;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* reseize 框样式 */
|
|
|
|
+ .x6-widget-transform {
|
|
|
|
+ .x6-widget-transform-resize {
|
|
|
|
+ border-radius: 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .x6-widget-minimap-viewport{
|
|
|
|
+ border-color: red;
|
|
|
|
+ .x6-widget-minimap-viewport-zoom{
|
|
|
|
+ border-color: red;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ .x6-widget-minimap{
|
|
|
|
+ width: auto !important;
|
|
|
|
+ height: auto !important;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|