2023-01-31 10:37:40 +08:00
|
|
|
|
<template>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
<tag-menu :instanceMenuMaxHeight="instanceMenuMaxHeight" :tags="instances.tags">
|
|
|
|
|
|
<template #submenu="props">
|
|
|
|
|
|
<!-- 第二级:数据库实例 -->
|
|
|
|
|
|
<el-sub-menu v-for="inst in instances.tree[props.tag.tagId]" :index="'instance-' + inst.id"
|
|
|
|
|
|
:key="'instance-' + inst.id" @click.stop="changeInstance(inst, () => { })">
|
|
|
|
|
|
<template #title>
|
|
|
|
|
|
<el-popover placement="right-start" title="数据库实例信息" trigger="hover" :width="210">
|
|
|
|
|
|
<template #reference>
|
|
|
|
|
|
<span> <el-icon>
|
|
|
|
|
|
<MostlyCloudy color="#409eff" />
|
|
|
|
|
|
</el-icon>{{ inst.name }}</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<template #default>
|
|
|
|
|
|
<el-form class="instances-pop-form" label-width="55px" :size="'small'">
|
|
|
|
|
|
<el-form-item label="类型:">{{ inst.type }}</el-form-item>
|
|
|
|
|
|
<el-form-item label="链接:">{{ inst.host }}:{{ inst.port }}</el-form-item>
|
|
|
|
|
|
<el-form-item label="用户:">{{ inst.username }}</el-form-item>
|
|
|
|
|
|
<el-form-item v-if="inst.remark" label="备注:">{{
|
|
|
|
|
|
inst.remark
|
|
|
|
|
|
}}</el-form-item>
|
|
|
|
|
|
</el-form>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-popover>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<!-- 第三级:数据库 -->
|
|
|
|
|
|
<el-sub-menu v-for="schema in instances.dbs[inst.id]" :index="inst.id + schema" :key="inst.id + schema"
|
|
|
|
|
|
:class="state.nowSchema === (inst.id + schema) && 'checked'"
|
|
|
|
|
|
@click.stop="changeSchema(inst, schema)">
|
|
|
|
|
|
<template #title>
|
|
|
|
|
|
<el-icon>
|
|
|
|
|
|
<Coin color="#67c23a" />
|
|
|
|
|
|
</el-icon>
|
|
|
|
|
|
<span class="checked-schema">{{ schema }}</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
<!-- 第四级 01:表 -->
|
|
|
|
|
|
<el-sub-menu :index="inst.id + schema + '-table'">
|
2023-02-06 17:14:16 +08:00
|
|
|
|
<template #title>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
<div style="width: 100%" @click="loadTableNames(inst, schema, () => { })">
|
|
|
|
|
|
<el-icon>
|
|
|
|
|
|
<Calendar color="#409eff" />
|
|
|
|
|
|
</el-icon>
|
|
|
|
|
|
<span>表</span>
|
|
|
|
|
|
<el-icon v-show="state.loading[inst.id + schema]" class="is-loading">
|
|
|
|
|
|
<Loading />
|
|
|
|
|
|
</el-icon>
|
|
|
|
|
|
</div>
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</template>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
<el-menu-item :index="inst.id + schema + '-tableSearch'"
|
|
|
|
|
|
:key="inst.id + schema + '-tableSearch'">
|
2023-02-06 17:14:16 +08:00
|
|
|
|
<template #title>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
|
|
|
|
|
|
<el-input size="small" placeholder="过滤表" clearable
|
|
|
|
|
|
@change="filterTableName(inst.id, schema)"
|
|
|
|
|
|
@keyup="(e: any) => filterTableName(inst.id, schema, e)"
|
|
|
|
|
|
v-model="state.filterParam[inst.id + schema]" />
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</template>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
</el-menu-item>
|
|
|
|
|
|
|
|
|
|
|
|
<template v-for="tb in instances.tables[inst.id + schema]">
|
|
|
|
|
|
<el-menu-item :index="inst.id + schema + tb.tableName"
|
|
|
|
|
|
:key="inst.id + schema + tb.tableName" v-if="tb.show"
|
|
|
|
|
|
@click="loadTableData(inst, schema, tb.tableName)">
|
2023-02-06 17:14:16 +08:00
|
|
|
|
<template #title>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
<div style="width: 100%">
|
|
|
|
|
|
<el-icon>
|
|
|
|
|
|
<Calendar color="#409eff" />
|
|
|
|
|
|
</el-icon>
|
|
|
|
|
|
<el-tooltip v-if="tb.tableComment" effect="customized"
|
|
|
|
|
|
:content="tb.tableComment" placement="right">
|
|
|
|
|
|
{{ tb.tableName }}
|
|
|
|
|
|
</el-tooltip>
|
|
|
|
|
|
<span v-else>{{ tb.tableName }}</span>
|
|
|
|
|
|
</div>
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</template>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
</el-menu-item>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-sub-menu>
|
|
|
|
|
|
<!-- 第四级 02:sql -->
|
|
|
|
|
|
<el-sub-menu :index="inst.id + schema + '-sql'">
|
|
|
|
|
|
<template #title>
|
|
|
|
|
|
<el-icon>
|
|
|
|
|
|
<List color="#f56c6c" />
|
|
|
|
|
|
</el-icon>
|
|
|
|
|
|
<span>sql</span>
|
|
|
|
|
|
</template>
|
2023-01-31 10:37:40 +08:00
|
|
|
|
|
2023-02-07 16:54:44 +08:00
|
|
|
|
<template v-for="sql in instances.sqls[inst.id + schema]">
|
|
|
|
|
|
<el-menu-item :index="inst.id + schema + sql.name" :key="inst.id + schema + sql.name"
|
|
|
|
|
|
v-if="sql.show" @click="loadSql(inst, schema, sql.name)">
|
|
|
|
|
|
<template #title>
|
|
|
|
|
|
<div style="width: 100%">
|
|
|
|
|
|
<el-icon>
|
|
|
|
|
|
<Calendar color="#409eff" />
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</el-icon>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
<span>{{ sql.name }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-menu-item>
|
|
|
|
|
|
</template>
|
2023-02-06 17:14:16 +08:00
|
|
|
|
</el-sub-menu>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
</el-sub-menu>
|
|
|
|
|
|
</el-sub-menu>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</tag-menu>
|
2023-01-31 10:37:40 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2023-02-07 16:54:44 +08:00
|
|
|
|
import { nextTick, onBeforeMount, onMounted, reactive, ref, Ref, watch } from 'vue';
|
|
|
|
|
|
import { store } from '@/store';
|
|
|
|
|
|
import TagMenu from '../../component/TagMenu.vue';
|
2023-01-31 10:37:40 +08:00
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
2023-02-06 17:14:16 +08:00
|
|
|
|
instanceMenuMaxHeight: {
|
|
|
|
|
|
type: [Number, String],
|
|
|
|
|
|
},
|
|
|
|
|
|
instances: {
|
|
|
|
|
|
type: Object, required: true
|
|
|
|
|
|
},
|
2023-01-31 10:37:40 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
2023-02-06 17:14:16 +08:00
|
|
|
|
const emits = defineEmits(['initLoadInstances', 'changeInstance', 'loadTableNames', 'loadTableData', 'changeSchema'])
|
2023-01-31 10:37:40 +08:00
|
|
|
|
|
2023-02-06 17:14:16 +08:00
|
|
|
|
onBeforeMount(async () => {
|
|
|
|
|
|
await initLoadInstances()
|
2023-01-31 10:37:40 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
2023-02-07 10:32:42 +08:00
|
|
|
|
const menuRef = ref(null) as Ref
|
|
|
|
|
|
|
2023-01-31 10:37:40 +08:00
|
|
|
|
const state = reactive({
|
2023-02-06 17:14:16 +08:00
|
|
|
|
nowSchema: '',
|
|
|
|
|
|
filterParam: {},
|
|
|
|
|
|
loading: {}
|
2023-01-31 10:37:40 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化加载实例数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
const initLoadInstances = () => {
|
2023-02-06 17:14:16 +08:00
|
|
|
|
emits('initLoadInstances')
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 改变选中的数据库实例
|
|
|
|
|
|
* @param inst 选中的实例对象
|
2023-02-07 10:32:42 +08:00
|
|
|
|
* @param fn 选中的实例对象后的回调函数
|
2023-01-31 10:37:40 +08:00
|
|
|
|
*/
|
2023-02-07 16:54:44 +08:00
|
|
|
|
const changeInstance = (inst: any, fn: Function) => {
|
|
|
|
|
|
emits('changeInstance', inst, fn)
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 改变选中的数据库schema
|
|
|
|
|
|
* @param inst 选中的实例对象
|
|
|
|
|
|
* @param schema 选中的数据库schema
|
|
|
|
|
|
*/
|
2023-02-06 17:14:16 +08:00
|
|
|
|
const changeSchema = (inst: any, schema: string) => {
|
|
|
|
|
|
state.nowSchema = inst.id + schema
|
|
|
|
|
|
emits('changeSchema', inst, schema)
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载schema下所有表
|
|
|
|
|
|
* @param inst 数据库实例
|
|
|
|
|
|
* @param schema database名
|
2023-02-07 10:32:42 +08:00
|
|
|
|
* @param fn 加载表集合后的回调函数,参数:res 表集合
|
2023-01-31 10:37:40 +08:00
|
|
|
|
*/
|
2023-02-07 10:32:42 +08:00
|
|
|
|
const loadTableNames = async (inst: any, schema: string, fn: Function) => {
|
2023-02-06 17:14:16 +08:00
|
|
|
|
state.loading[inst.id + schema] = true
|
2023-02-07 16:54:44 +08:00
|
|
|
|
await emits('loadTableNames', inst, schema, (res: any[]) => {
|
2023-02-06 17:14:16 +08:00
|
|
|
|
state.loading[inst.id + schema] = false
|
2023-02-07 16:54:44 +08:00
|
|
|
|
fn && fn(res)
|
2023-02-06 17:14:16 +08:00
|
|
|
|
})
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载选中表数据
|
|
|
|
|
|
* @param inst 数据库实例
|
|
|
|
|
|
* @param schema database名
|
|
|
|
|
|
* @param tableName 表名
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadTableData = (inst: any, schema: string, tableName: string) => {
|
2023-02-06 17:14:16 +08:00
|
|
|
|
emits('loadTableData', inst, schema, tableName)
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const filterTableName = (instId: number, schema: string, event?: any) => {
|
2023-02-06 17:14:16 +08:00
|
|
|
|
if (event) {
|
|
|
|
|
|
state.filterParam[instId + schema] = event.target.value
|
|
|
|
|
|
}
|
|
|
|
|
|
let param = state.filterParam[instId + schema] as string
|
|
|
|
|
|
param = param?.replace('/', '\/')
|
|
|
|
|
|
const key = instId + schema;
|
|
|
|
|
|
props.instances.tables[key].forEach((a: any) => {
|
|
|
|
|
|
a.show = param ? eval('/' + param.split('').join('[_\w]*') + '[_\w]*/ig').test(a.tableName) : true
|
|
|
|
|
|
})
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-07 10:32:42 +08:00
|
|
|
|
const selectDb = async (val?: any) => {
|
2023-02-07 16:54:44 +08:00
|
|
|
|
let info = val || store.state.sqlExecInfo.dbOptInfo;
|
|
|
|
|
|
if (info && info.dbId) {
|
|
|
|
|
|
const { tagPath, dbId, db } = info
|
|
|
|
|
|
menuRef.value.open(tagPath);
|
|
|
|
|
|
menuRef.value.open('instance-' + dbId);
|
|
|
|
|
|
await changeInstance({ id: dbId }, () => {
|
|
|
|
|
|
// 加载数据库
|
|
|
|
|
|
nextTick(async () => {
|
|
|
|
|
|
menuRef.value.open(dbId + db)
|
|
|
|
|
|
state.nowSchema = (dbId + db)
|
|
|
|
|
|
// 加载集合列表
|
|
|
|
|
|
await nextTick(async () => {
|
|
|
|
|
|
await loadTableNames({ id: dbId }, db, (res: any[]) => {
|
|
|
|
|
|
// 展开集合列表
|
|
|
|
|
|
menuRef.value.open(dbId + db + '-table')
|
|
|
|
|
|
console.log(res)
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
2023-02-07 10:32:42 +08:00
|
|
|
|
})
|
2023-02-07 16:54:44 +08:00
|
|
|
|
}
|
2023-02-07 10:32:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-02-07 16:54:44 +08:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
selectDb();
|
2023-02-07 10:32:42 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
2023-02-07 16:54:44 +08:00
|
|
|
|
watch(() => store.state.sqlExecInfo.dbOptInfo, async newValue => {
|
|
|
|
|
|
await selectDb(newValue)
|
2023-02-07 10:32:42 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-01-31 10:37:40 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
2023-02-06 17:14:16 +08:00
|
|
|
|
.instances-pop-form {
|
|
|
|
|
|
.el-form-item {
|
|
|
|
|
|
margin-bottom: unset;
|
|
|
|
|
|
}
|
2023-01-31 10:37:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
</style>
|