|
@@ -1,216 +0,0 @@
|
|
|
-<template>
|
|
|
- <div class="main-box">
|
|
|
- <div class="card filter">
|
|
|
- <el-tree
|
|
|
- class="scroller"
|
|
|
- :load="loadNode"
|
|
|
- :expand-on-click-node="true"
|
|
|
- :highlight-current="true"
|
|
|
- :render-content="renderContent"
|
|
|
- @node-click="handleNodeClick"
|
|
|
- :lazy="true"
|
|
|
- >
|
|
|
- </el-tree>
|
|
|
- </div>
|
|
|
- <div class="table-box card content-box-c">
|
|
|
- <div class="table-container">
|
|
|
- <span>当前表:{{ currentNode.schemaName }} / {{ currentNode.tableName }}</span>
|
|
|
- <el-tabs v-model="activeName" class="demo-tabs">
|
|
|
- <el-tab-pane label="基本信息" name="1">
|
|
|
- <el-descriptions title="元数据" size="small" :column="1" colon border>
|
|
|
- <el-descriptions-item label="表名称">{{ tableMeta.tableName }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="表类型">{{ tableMeta.type }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="模式名">{{ tableMeta.schemaName }}</el-descriptions-item>
|
|
|
- <el-descriptions-item label="表注释">
|
|
|
- <el-input type="textarea" :rows="2" v-model="tableMeta.remarks" auto-complete="off" :readonly="true"></el-input>
|
|
|
- </el-descriptions-item>
|
|
|
- <el-descriptions-item label="建表DDL">
|
|
|
- <el-input type="textarea" :rows="16" v-model="tableMeta.createSql" auto-complete="off" :readonly="true"></el-input>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions>
|
|
|
- </el-tab-pane>
|
|
|
- <el-tab-pane label="字段信息" name="2">
|
|
|
- <ProTable :pagination="false" :is-show-search="false" :tool-button="false" :columns="fieldColumns" :data="tableMeta.columns">
|
|
|
- <!-- 表格操作 -->
|
|
|
- <template #empty>
|
|
|
- <span>单击左侧展开"数据源"来查看表的元数据记录</span>
|
|
|
- </template>
|
|
|
- </ProTable>
|
|
|
- </el-tab-pane>
|
|
|
- <el-tab-pane label="索引信息" name="3">
|
|
|
- <ProTable :pagination="false" :is-show-search="false" :tool-button="false" :columns="indexColumns" :data="tableMeta.indexes">
|
|
|
- <!-- 表格操作 -->
|
|
|
- <template #empty>
|
|
|
- <span>单击左侧展开"数据源"来查看表的元数据记录</span>
|
|
|
- </template>
|
|
|
- </ProTable>
|
|
|
- </el-tab-pane>
|
|
|
- <el-tab-pane label="取样数据" name="4">
|
|
|
- <el-table :data="sampleData?.rows" border>
|
|
|
- <template #empty>
|
|
|
- <span>单击左侧展开"数据源导航树"来查看表的数据记录</span>
|
|
|
- </template>
|
|
|
- <el-table-column v-for="(item, index) in sampleData?.columns" :prop="item" :label="item" :key="index" show-overflow-tooltip>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
- </el-tab-pane>
|
|
|
- </el-tabs>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script setup lang="tsx" name="UserManage">
|
|
|
-import { ref, reactive } from 'vue'
|
|
|
-// import TreeFilter from '@/components/TreeFilter/index.vue'
|
|
|
-import { getNameListApi } from '@/api/modules/db/connection'
|
|
|
-import { getSchemasApi, getTablesApi, getTablesMetaApi, getTablesDataApi } from '@/api/modules/db/metadata'
|
|
|
-// import type { TabsPaneContext } from 'element-plus'
|
|
|
-import ProTable from '@/components/ProTable/index.vue'
|
|
|
-import { ColumnProps } from '@/components/ProTable/interface'
|
|
|
-const activeName = ref('1')
|
|
|
-const tableMeta = ref({
|
|
|
- tableName: '-',
|
|
|
- schemaName: '-',
|
|
|
- remarks: '',
|
|
|
- type: '-',
|
|
|
- createSql: '',
|
|
|
- primaryKeys: [],
|
|
|
- columns: [],
|
|
|
- indexes: []
|
|
|
-})
|
|
|
-const currentNode = ref({
|
|
|
- tableName: '-',
|
|
|
- schemaName: '-'
|
|
|
-})
|
|
|
-
|
|
|
-let sampleData = ref<any>()
|
|
|
-
|
|
|
-// const handleClick = (tab: TabsPaneContext, event: Event) => {
|
|
|
-// console.log(tab, event)
|
|
|
-// }
|
|
|
-const loadNode = (node, resolve) => {
|
|
|
- if (node.level === 0) {
|
|
|
- const rootNode = [{ label: '数据源导航树', value: 0, hasChild: true, children: 'child' }]
|
|
|
- return resolve(rootNode)
|
|
|
- }
|
|
|
-
|
|
|
- setTimeout(() => {
|
|
|
- if (node.level === 1) {
|
|
|
- getNameListApi().then(res => {
|
|
|
- res.data.forEach(item => {
|
|
|
- item['label'] = item.name
|
|
|
- item['parent'] = 0
|
|
|
- item['value'] = item.id
|
|
|
- item['hasChild'] = true
|
|
|
- item['children'] = 'child'
|
|
|
- })
|
|
|
- resolve(res.data)
|
|
|
- })
|
|
|
- } else if (node.level === 2) {
|
|
|
- getSchemasApi(node.data.value).then(res => {
|
|
|
- res.data.forEach(item => {
|
|
|
- item['label'] = item.schema
|
|
|
- item['parent'] = node.data.value
|
|
|
- item['value'] = item.connection
|
|
|
- item['hasChild'] = true
|
|
|
- item['children'] = 'child'
|
|
|
- })
|
|
|
- resolve(res.data)
|
|
|
- })
|
|
|
- } else if (node.level === 3) {
|
|
|
- getTablesApi(node.data.parent, { schema: node.data.label }).then(res => {
|
|
|
- res.data.forEach(item => {
|
|
|
- item['label'] = item.tableName
|
|
|
- item['parent'] = node.data.label
|
|
|
- item['id'] = node.data.parent
|
|
|
- item['value'] = item.type
|
|
|
- item['hasChild'] = false
|
|
|
- item['children'] = 'child'
|
|
|
- })
|
|
|
- resolve(res.data)
|
|
|
- })
|
|
|
- } else if (node.level == 4) {
|
|
|
- resolve([])
|
|
|
- } else {
|
|
|
- resolve([])
|
|
|
- }
|
|
|
- }, 500)
|
|
|
-}
|
|
|
-const handleNodeClick = data => {
|
|
|
- let id = data.id
|
|
|
- let schema = data.schemaName
|
|
|
- let table = data.tableName
|
|
|
- if (!data.hasChild && id && schema && table) {
|
|
|
- activeName.value = '1'
|
|
|
- getTablesMetaApi(id, { schema, table }).then(res => {
|
|
|
- tableMeta.value = res.data
|
|
|
- currentNode.value.tableName = table
|
|
|
- currentNode.value.schemaName = schema
|
|
|
- })
|
|
|
- getTablesDataApi(id, { schema, table }).then(res => {
|
|
|
- sampleData.value = res.data
|
|
|
- })
|
|
|
- }
|
|
|
-}
|
|
|
-const renderContent = (h, { node, data }) => {
|
|
|
- if (node.level === 1) {
|
|
|
- return (
|
|
|
- <div class="custom-tree-node">
|
|
|
- <i class="el-icon-takeaway-box"></i>
|
|
|
- <span>{data.label}</span>
|
|
|
- </div>
|
|
|
- )
|
|
|
- } else if (node.level === 2) {
|
|
|
- return (
|
|
|
- <div class="custom-tree-node">
|
|
|
- <i class="el-icon-folder-opened"></i>
|
|
|
- <span>{data.label}</span>
|
|
|
- </div>
|
|
|
- )
|
|
|
- } else if (node.level === 3) {
|
|
|
- return (
|
|
|
- <div class="custom-tree-node">
|
|
|
- <i class="iconfont icon-shujuku1"></i>
|
|
|
- <span>{data.label}</span>
|
|
|
- </div>
|
|
|
- )
|
|
|
- } else {
|
|
|
- let icon_pic = 'iconfont icon-shitu_biaoge'
|
|
|
- if (data.value === 'VIEW') {
|
|
|
- icon_pic = 'iconfont icon-viewList'
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <div class="custom-tree-node">
|
|
|
- <i class={icon_pic}></i>
|
|
|
- <el-tooltip class="item" content={node.label} effect="light" placement="left">
|
|
|
- <span>{data.label}</span>
|
|
|
- </el-tooltip>
|
|
|
- </div>
|
|
|
- )
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 表格配置项
|
|
|
-const fieldColumns = reactive<ColumnProps<any>[]>([
|
|
|
- { prop: 'fieldName', label: '名称' },
|
|
|
- { prop: 'typeName', label: '类型' },
|
|
|
- { prop: 'fieldType', label: 'jdbcType' },
|
|
|
- { prop: 'displaySize', label: '长度' },
|
|
|
- { prop: 'precision', label: '精度' },
|
|
|
- { prop: 'scale', label: '位数' },
|
|
|
- { prop: 'isPrimaryKey', label: '主键' },
|
|
|
- { prop: 'isAutoIncrement', label: '自增' },
|
|
|
- { prop: 'isNullable', label: '可空' },
|
|
|
- { prop: 'remarks', label: '注释' }
|
|
|
-])
|
|
|
-const indexColumns = reactive<ColumnProps<any>[]>([
|
|
|
- { prop: 'indexType', label: '索引类型' },
|
|
|
- { prop: 'indexName', label: '索引名称' },
|
|
|
- { prop: 'indexFields', label: '索引字段' }
|
|
|
-])
|
|
|
-</script>
|
|
|
-<style scoped lang="scss">
|
|
|
-@import './index.scss';
|
|
|
-</style>
|