standard-query.vue 7.89 KB
<route lang="yaml">
    name: metadataStandardQuery
    </route>

<script lang="ts" setup name="metadataStandardQuery">
import { ref } from 'vue';
import { ElMessage, ElMessageBox } from "element-plus";
import Sankey from './components/Sankey.vue';
import Tree from '@/components/Tree/index.vue';
import RelationNetwork from '@/components/RelationNetwork/index.vue';
import {
} from '@/api/modules/dataMetaService';

import { useRouter, useRoute } from "vue-router";
import useDataMetaStore from "@/store/modules/dataMeta"

const router = useRouter();
const route = useRoute()

const switchGraphDisplay = ref(true); //true表示关系网,false表示桑基图

const { proxy } = getCurrentInstance() as any;

const relationNetworkRef = ref();

const treeInfo = ref({
  id: "data-meta-standard-tree",
  filter: true,
  queryValue: "",
  queryPlaceholder: "输入库/表名称搜索",
  props: {
    label: "name",
    value: "guid",
    isLeaf: "isLeaf",
  },
  nodeKey: 'guid',
  expandedKey: ['1'],
  currentNodeKey: '',
  expandOnNodeClick: false,
  data: <any>[],
  loading: false
});

/** 获取左侧树数据. */
const getTreeData = async () => {
  treeInfo.value.loading = true
  // let params = {}
  // const res: any = await getMetaTreeData(params)
  // if (res.code == proxy.$passCode) {
  //   const data = res.data || [];
  //   let treeData: any = Object.keys(data).length ? [data] : [];
  //   treeInfo.value.data = treeData;
  //   allTreeData.value = treeData;
  //   if (treeData.length) {
  //     treeInfo.value.currentNodeKey = treeData[0].guid;
  //     treeInfo.value.expandedKey = <any>[treeData[0].guid];
  //   }
  // } else {
  //   ElMessage.error(res.msg);
  // }
  treeInfo.value.data = [{
    guid: '1',
    name: '第一级1',
    children: [{
      guid: '1-1',
      name: '第二级1-1',
      children: [{
        guid: '1-1-1',
        name: '第三级1-1-1'
      }]
    }, {
      guid: '1-2',
      name: '第二级1-2'
    }, {
      guid: '1-3',
      name: '第二级1-3'
    }]
  }, {
    guid: '2',
    name: '第一级2',
    children: [{
      guid: '2-1',
      name: '第二级1-1'
    }, {
      guid: '2-2',
      name: '第二级1-2'
    }]
  }];
  treeInfo.value.loading = false
  treeInfo.value.currentNodeKey = '1';
  nodeClick(treeInfo.value.data[0])
}
/** 左侧树的的组件引用. */
const treeInfoRef = ref();

/** 当前选中的树节点数据data */
const lastClickNode: any = ref({});

const treeDataLoading = ref(false);

/** 数据血缘关系图组件 */
const lineageGraph: any = ref();

/** 点击左侧树节点,更新对应的血缘关系图. */
const nodeClick = (data) => {
  console.log(data);
  const ele = <HTMLElement>document.querySelector(".g6-component-contextmenu")
  if (ele) {
    ele.style.display = "none"
  }
  nextTick(() => {
    lineageGraph.value?.tooltip1.hide()
  })
  treeInfo.value.currentNodeKey = data.guid;
  treeInfo.value.expandedKey = <any>[data.guid];
  lastClickNode.value = data;
}

/** 选中树节点后自动滚动到可视范围内. */
const scrollToNode = (nodeId) => {
  nextTick(() => {
    const nodeElement = treeInfoRef.value.treeRef.$el.querySelector(`[data-key="${nodeId}"]`);
    if (nodeElement) {
      nodeElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
  });
}

/** 处理从详情处跳转而来的默认展示. */
const processRouter = () => {
  const { guid, databaseName, tableName, databaseChName, databaseGuid, fieldGuid, fieldEnName, set } = useDataMetaStore()
  let isFL = useDataMetaStore().isFieldLineage;
  if (fieldGuid) {//查看字段血缘的
    nextTick(() => {
      treeInfo.value.expandedKey = <any>[databaseGuid, guid];
      treeInfo.value.currentNodeKey = fieldGuid as string;
      scrollToNode(fieldGuid);
      treeInfoRef.value.setCurrentKey(fieldGuid);
    })
    lastClickNode.value = { guid: fieldGuid, tableGuid: guid, databaseGuid: databaseGuid, enName: fieldEnName, tableName, databaseName, type: 4, isLeaf: true, databaseChName };
    // getTableFieldLineageMap();
    set()
  } else if (guid) {
    treeInfo.value.currentNodeKey = guid as string;
    treeInfo.value.expandedKey = <any>[databaseGuid, guid];
    lastClickNode.value = { guid: guid, tableName, databaseName, type: 3, databaseChName };
    scrollToNode(guid);
    switchGraphDisplay.value = isFL;
    // if (isFL) {
    //   getAllTableFieldLineageMap();
    // } else {
    //   getTableLineageMap()
    // }
    set()
  }
}

onActivated(() => {
  processRouter();
});

onBeforeMount(async () => {
  await getTreeData()
  processRouter();
})

onMounted(() => { })

const isGraphDisplay = ref(true);

const displaySwitchChange = (val) => {
  isGraphDisplay.value = val;
}

const handleNodeItemClick = (graph, nodeItem) => {
  const nodeId = nodeItem.get('id');
  const parentData = graph.findDataById(nodeId);
  if (!parentData.children) {
    parentData.children = [];
  }
  treeDataLoading.value = true;
  let childData = [{
    guid: '33',
    isField: true,
    name: '字段1'
  }, {
    guid: '44',
    isField: true,
    name: '字段2字段2字段2字段2字段2字段2字段2字段2字段2xx2字段22字段22字段22字段22字段22字段2'
  }, {
    guid: '55',
    isField: true,
    name: '字段3'
  }]
  //    parentData.collapsed = true;
  // nodeItem.getModel().collapsed = true;
  parentData.children = childData;
  setTimeout(() => {
    treeDataLoading.value = false;
    graph.changeData();
    // parentData.collapsed = true;
    // graph.updateChildren(childData, parentData.id);
    //  graph.changeData(lastClickNode.value);
    //graph.data(lastClickNode.value);
  }, 2000)
}

const handleContextMenu = (nodeData) => {
  //TODO,新建引用数据集
}

onBeforeUnmount(() => {
  relationNetworkRef.value.destroy();
})

</script>

<template>
  <div class="container_wrap full flex">
    <div class="aside_wrap">
      <div class="aside_title">数据库目录列表</div>
      <Tree ref="treeInfoRef" :treeInfo="treeInfo" @nodeClick="nodeClick" />
    </div>
    <div class="main_wrap">
      <div className='g6-component-topbar'>
        <graphTopbar ref="topBarRef" @displaySwitchChange="displaySwitchChange" :isGraphDisplay="isGraphDisplay" />
      </div>
      <RelationNetwork v-show="isGraphDisplay" ref="relationNetworkRef" :tree-data="lastClickNode"
        v-loading="treeDataLoading" @nodeItemClick="handleNodeItemClick" @contextMenu="handleContextMenu">
      </RelationNetwork>
      <Sankey v-show="!isGraphDisplay"></Sankey>
      <!-- <div v-show="lastClickNode && lastClickNode?.type !== 3 && lastClickNode?.type !== 4" class="main-placeholder">
        <img src="../../assets/images/no-data.png" :style="{ width: '96px', height: '96px' }" />
        <div class="empty-text">暂无标准数据</div>
      </div> -->
    </div>
  </div>
</template>

<style scoped lang="scss">
.container_wrap {

  .aside_wrap {
    width: 200px;
    margin-right: 1px;
  }

  .main_wrap {
    position: relative;

    :deep(.canvas-wrapper) {
      background-color: #f7f7f9;
    }

    .main-placeholder {
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;

      .empty-text {
        font-size: 14px;
        color: #b2b2b2;
      }
    }
  }

}

.g6-component-topbar {
  position: absolute;
  left: 24px;
  bottom: unset;
  top: 14px;
  padding: 0;
  text-align: center;
  z-index: 999;
}

.container_wrap.flex .main_wrap {
  padding: 0px;
}

.tree_panel {
  height: calc(100% - 36px);
  padding-top: 0;

  :deep(.el-tree) {
    margin: 0;
    overflow: hidden auto;
  }
}

.card-noData {
  height: 100%;
  width: 100%;
  background: #fafafa;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #909399;
  font-size: 14px;
}

:deep(.el-form .el-form-item) {
  width: calc(100%);
  // margin-right: 8px;
}

:deep(.el-message) {
  position: fixed;
  /* 使用fixed或absolute定位 */
  z-index: 10000;
  /* 设置一个较高的z-index值确保在最上层显示 */
}
</style>