mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 15:30:25 +08:00
feat:mongo新增实例树
This commit is contained in:
@@ -1,96 +1,69 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="toolbar">
|
||||
<el-row type="flex" justify="space-between">
|
||||
<el-col :span="24">
|
||||
<el-form class="search-form" label-position="right" :inline="true">
|
||||
<el-form-item label="标签">
|
||||
<el-select @change="changeTag" @focus="getTags" v-model="query.tagPath" placeholder="请选择标签"
|
||||
filterable style="width: 250px">
|
||||
<el-option v-for="item in tags" :key="item" :label="item" :value="item"> </el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="实例" label-width="40px">
|
||||
<el-select v-model="mongoId" placeholder="请选择mongo" @change="changeMongo">
|
||||
<el-option v-for="item in mongoList" :key="item.id" :label="item.name" :value="item.id">
|
||||
<span style="float: left">{{ item.name }}</span>
|
||||
<span style="float: right; color: #8492a6; margin-left: 6px; font-size: 13px">{{ `
|
||||
[${item.uri}]`
|
||||
}}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="库" label-width="20px">
|
||||
<el-select v-model="database" placeholder="请选择库" @change="changeDatabase" filterable>
|
||||
<el-option v-for="item in databases" :key="item.Name" :label="item.Name"
|
||||
:value="item.Name">
|
||||
<span style="float: left">{{ item.Name }}</span>
|
||||
<span style="float: right; color: #8492a6; margin-left: 4px; font-size: 13px">{{
|
||||
` [${formatByteSize(item.SizeOnDisk)}]`
|
||||
}}</span>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="集合" label-width="40px">
|
||||
<el-select v-model="collection" placeholder="请选择集合" @change="changeCollection" filterable>
|
||||
<el-option v-for="item in collections" :key="item" :label="item" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<el-container id="data-exec" style="border: 1px solid #eee; margin-top: 1px">
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<mongo-instance-tree
|
||||
@init-load-instances="loadInstances"
|
||||
@change-instance="changeInstance"
|
||||
@change-schema="changeDatabase"
|
||||
@load-table-names="loadTableNames"
|
||||
@load-table-data="changeCollection"
|
||||
:instances="state.instances"/>
|
||||
</el-col>
|
||||
<el-col :span="20">
|
||||
<el-container id="data-exec" style="border: 1px solid #eee; margin-top: 1px">
|
||||
<el-tabs @tab-remove="removeDataTab" @tab-click="onDataTabClick" style="width: 100%; margin-left: 5px"
|
||||
v-model="activeName">
|
||||
<el-tab-pane closable v-for="dt in dataTabs" :key="dt.name" :label="dt.name" :name="dt.name">
|
||||
<el-row v-if="mongoId">
|
||||
<el-link @click="findCommand(activeName)" icon="refresh" :underline="false" class="ml5">
|
||||
</el-link>
|
||||
<el-link @click="showInsertDocDialog" class="ml5" type="primary" icon="plus" :underline="false">
|
||||
</el-link>
|
||||
</el-row>
|
||||
<el-row class="mt5 mb5">
|
||||
<el-input ref="findParamInputRef" v-model="dt.findParamStr" placeholder="点击输入相应查询条件"
|
||||
@focus="showFindDialog(dt.name)">
|
||||
<template #prepend>查询参数</template>
|
||||
</el-input>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="6" v-for="item in dt.datas" :key="item">
|
||||
<el-card :body-style="{ padding: '0px', position: 'relative' }">
|
||||
<el-input type="textarea" v-model="item.value" :rows="12" />
|
||||
<div style="padding: 3px; float: right" class="mr5 mongo-doc-btns">
|
||||
<div>
|
||||
<el-link @click="onJsonEditor(item)" :underline="false" type="success"
|
||||
icon="MagicStick"></el-link>
|
||||
v-model="state.activeName">
|
||||
<el-tab-pane closable v-for="dt in state.dataTabs" :key="dt.key" :label="dt.label" :name="dt.key">
|
||||
|
||||
<el-row class="mt5 mb5">
|
||||
<el-col :span="2">
|
||||
<el-link @click="findCommand(state.activeName)" icon="refresh" :underline="false" class="">
|
||||
</el-link>
|
||||
<el-link @click="showInsertDocDialog" class="" type="primary" icon="plus" :underline="false">
|
||||
</el-link>
|
||||
</el-col>
|
||||
<el-col :span="22">
|
||||
<el-input ref="findParamInputRef" v-model="dt.findParamStr" placeholder="点击输入相应查询条件"
|
||||
@focus="showFindDialog(dt.key)">
|
||||
<template #prepend>查询参数</template>
|
||||
</el-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="6" v-for="item in dt.datas" :key="item">
|
||||
<el-card :body-style="{ padding: '0px', position: 'relative' }">
|
||||
<el-input type="textarea" v-model="item.value" :rows="10" />
|
||||
<div style="padding: 3px; float: right" class="mr5 mongo-doc-btns">
|
||||
<div>
|
||||
<el-link @click="onJsonEditor(item)" :underline="false" type="success"
|
||||
icon="MagicStick"></el-link>
|
||||
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
|
||||
<el-link @click="onSaveDoc(item.value)" :underline="false" type="warning"
|
||||
icon="DocumentChecked"></el-link>
|
||||
<el-link @click="onSaveDoc(item.value)" :underline="false" type="warning"
|
||||
icon="DocumentChecked"></el-link>
|
||||
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
|
||||
<el-popconfirm @confirm="onDeleteDoc(item.value)" title="确定删除该文档?">
|
||||
<template #reference>
|
||||
<el-link :underline="false" type="danger" icon="DocumentDelete">
|
||||
</el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-popconfirm @confirm="onDeleteDoc(item.value)" title="确定删除该文档?">
|
||||
<template #reference>
|
||||
<el-link :underline="false" type="danger" icon="DocumentDelete">
|
||||
</el-link>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
|
||||
<el-dialog width="600px" title="find参数" v-model="findDialog.visible">
|
||||
<el-form label-width="70px">
|
||||
<el-form-item label="filter">
|
||||
@@ -116,7 +89,7 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog width="60%" :title="`新增'${activeName}'集合文档`" v-model="insertDocDialog.visible"
|
||||
<el-dialog width="60%" :title="`新增'${state.activeName}'集合文档`" v-model="insertDocDialog.visible"
|
||||
:close-on-click-modal="false">
|
||||
<monaco-editor v-model="insertDocDialog.doc" language="json" />
|
||||
<template #footer>
|
||||
@@ -127,9 +100,9 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog width="60%" title="json编辑器" v-model="jsoneditorDialog.visible" @close="onCloseJsonEditDialog"
|
||||
:close-on-click-modal="false">
|
||||
<monaco-editor v-model="jsoneditorDialog.doc" language="json" />
|
||||
<el-dialog width="60%" title="json编辑器" v-model="jsonEditorDialog.visible" @close="onCloseJsonEditDialog"
|
||||
:close-on-click-modal="false">
|
||||
<monaco-editor v-model="jsonEditorDialog.doc" language="json" />
|
||||
</el-dialog>
|
||||
|
||||
<div style="text-align: center; margin-top: 10px"></div>
|
||||
@@ -137,15 +110,14 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { mongoApi } from './api';
|
||||
import { toRefs, ref, reactive, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import {mongoApi} from './api';
|
||||
import {reactive, ref, toRefs} from 'vue';
|
||||
import {ElMessage} from 'element-plus';
|
||||
|
||||
import { isTrue, notBlank, notNull } from '@/common/assert';
|
||||
import { formatByteSize } from '@/common/utils/format';
|
||||
import { tagApi } from '../tag/api.ts';
|
||||
import { useStore } from '@/store/index.ts';
|
||||
import {isTrue, notBlank} from '@/common/assert';
|
||||
import {useStore} from '@/store/index.ts';
|
||||
import MonacoEditor from '@/components/monaco/MonacoEditor.vue';
|
||||
import MongoInstanceTree from '@/views/ops/mongo/MongoInstanceTree.vue';
|
||||
|
||||
const store = useStore();
|
||||
const findParamInputRef: any = ref(null);
|
||||
@@ -159,8 +131,6 @@ const state = reactive({
|
||||
database: '', // 当前选择操作的库
|
||||
collection: '', //当前选中的collection
|
||||
activeName: '', // 当前操作的tab
|
||||
databases: [] as any,
|
||||
collections: [] as any,
|
||||
dataTabs: {} as any, // 数据tabs
|
||||
findDialog: {
|
||||
visible: false,
|
||||
@@ -175,107 +145,80 @@ const state = reactive({
|
||||
visible: false,
|
||||
doc: '',
|
||||
},
|
||||
jsoneditorDialog: {
|
||||
jsonEditorDialog: {
|
||||
visible: false,
|
||||
doc: '',
|
||||
item: {} as any,
|
||||
},
|
||||
instances:{tags:{}, tree:{}, dbs:{}, tables:{}}
|
||||
});
|
||||
|
||||
const {
|
||||
tags,
|
||||
mongoList,
|
||||
query,
|
||||
mongoId,
|
||||
database,
|
||||
collection,
|
||||
activeName,
|
||||
databases,
|
||||
collections,
|
||||
dataTabs,
|
||||
findDialog,
|
||||
insertDocDialog,
|
||||
jsoneditorDialog,
|
||||
jsonEditorDialog,
|
||||
} = toRefs(state)
|
||||
|
||||
const searchMongo = async () => {
|
||||
notNull(state.query.tagPath, '请先选择标签');
|
||||
const res = await mongoApi.mongoList.request(state.query);
|
||||
state.mongoList = res.list;
|
||||
};
|
||||
|
||||
const changeTag = (tagPath: string) => {
|
||||
state.databases = [];
|
||||
state.collections = [];
|
||||
state.mongoId = null;
|
||||
state.collection = '';
|
||||
state.database = '';
|
||||
state.dataTabs = {};
|
||||
if (tagPath != null) {
|
||||
searchMongo();
|
||||
const changeInstance = async (inst: any) => {
|
||||
if (inst) {
|
||||
if (!state.instances.dbs[inst.id]) {
|
||||
const res = await mongoApi.databases.request({id: inst.id});
|
||||
state.instances.dbs[inst.id] = res.Databases;
|
||||
console.log(res.Databases)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const changeDatabase = async (inst: any, database: string) => {
|
||||
};
|
||||
|
||||
const getTags = async () => {
|
||||
state.tags = await tagApi.getAccountTags.request(null);
|
||||
const loadTableNames = async (inst: any, database: string, fn:Function) => {
|
||||
let tbs = await mongoApi.collections.request({ id: inst.id, database });
|
||||
let tables = [];
|
||||
for(let tb of tbs){
|
||||
tables.push({tableName: tb, show: true})
|
||||
}
|
||||
state.instances.tables[inst.id+database] = tables
|
||||
fn()
|
||||
}
|
||||
|
||||
const changeCollection = (inst: any, schema: string, collection: string) => {
|
||||
state.collection = collection
|
||||
state.mongoId = inst.id
|
||||
state.database = schema
|
||||
let key = inst.id + schema +collection
|
||||
let dataTab = state.dataTabs[key];
|
||||
if (!dataTab) {
|
||||
// 默认查询参数
|
||||
const findParam = {
|
||||
filter: '{}',
|
||||
sort: '{"_id": -1}',
|
||||
skip: 0,
|
||||
limit: 12,
|
||||
};
|
||||
state.dataTabs[key] = {
|
||||
key: key,
|
||||
label: schema+'.'+collection,
|
||||
name: inst.id+schema+collection,
|
||||
datas: [],
|
||||
findParamStr: JSON.stringify(findParam),
|
||||
findParam,
|
||||
};
|
||||
}
|
||||
state.activeName = key;
|
||||
findCommand(key);
|
||||
};
|
||||
|
||||
const changeMongo = () => {
|
||||
state.databases = [];
|
||||
state.collections = [];
|
||||
state.dataTabs = {};
|
||||
getDatabases();
|
||||
};
|
||||
|
||||
const getDatabases = async () => {
|
||||
const res = await mongoApi.databases.request({ id: state.mongoId });
|
||||
state.databases = res.Databases;
|
||||
};
|
||||
|
||||
const changeDatabase = () => {
|
||||
state.collections = [];
|
||||
state.collection = '';
|
||||
state.dataTabs = {};
|
||||
getCollections();
|
||||
};
|
||||
|
||||
const getCollections = async () => {
|
||||
state.collections = await mongoApi.collections.request({ id: state.mongoId, database: state.database });
|
||||
};
|
||||
|
||||
const changeCollection = () => {
|
||||
const collection = state.collection;
|
||||
let dataTab = state.dataTabs[collection];
|
||||
if (!dataTab) {
|
||||
// 默认查询参数
|
||||
const findParam = {
|
||||
filter: '{}',
|
||||
sort: '{"_id": -1}',
|
||||
skip: 0,
|
||||
limit: 12,
|
||||
},
|
||||
dataTab = {
|
||||
name: collection,
|
||||
datas: [],
|
||||
findParamStr: JSON.stringify(findParam),
|
||||
findParam,
|
||||
};
|
||||
state.dataTabs[collection] = dataTab;
|
||||
}
|
||||
state.activeName = collection;
|
||||
findCommand(collection);
|
||||
};
|
||||
|
||||
const showFindDialog = (collection: string) => {
|
||||
const showFindDialog = (key: string) => {
|
||||
// 获取当前tab的索引位置,将其输入框失去焦点,防止输入以及重复获取焦点
|
||||
const dataTabNames = Object.keys(state.dataTabs);
|
||||
for (let i = 0; i < dataTabNames.length; i++) {
|
||||
if (collection == dataTabNames[i]) {
|
||||
if (key == dataTabNames[i]) {
|
||||
findParamInputRef.value[i].blur();
|
||||
}
|
||||
}
|
||||
|
||||
state.findDialog.findParam = state.dataTabs[collection].findParam;
|
||||
state.findDialog.findParam = state.dataTabs[key].findParam;
|
||||
state.findDialog.visible = true;
|
||||
};
|
||||
|
||||
@@ -286,8 +229,8 @@ const confirmFindDialog = () => {
|
||||
findCommand(state.activeName);
|
||||
};
|
||||
|
||||
const findCommand = async (collection: string) => {
|
||||
const dataTab = state.dataTabs[collection];
|
||||
const findCommand = async (key: string) => {
|
||||
const dataTab = state.dataTabs[key];
|
||||
const findParma = dataTab.findParam;
|
||||
let filter, sort;
|
||||
try {
|
||||
@@ -300,13 +243,13 @@ const findCommand = async (collection: string) => {
|
||||
const datas = await mongoApi.findCommand.request({
|
||||
id: state.mongoId,
|
||||
database: state.database,
|
||||
collection,
|
||||
collection: state.collection,
|
||||
filter,
|
||||
sort,
|
||||
limit: findParma.limit || 12,
|
||||
skip: findParma.skip || 0,
|
||||
});
|
||||
state.dataTabs[collection].datas = wrapDatas(datas);
|
||||
state.dataTabs[key].datas = wrapDatas(datas);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -357,13 +300,13 @@ const onInsertDoc = async () => {
|
||||
};
|
||||
|
||||
const onJsonEditor = (item: any) => {
|
||||
state.jsoneditorDialog.item = item;
|
||||
state.jsoneditorDialog.doc = item.value;
|
||||
state.jsoneditorDialog.visible = true;
|
||||
state.jsonEditorDialog.item = item;
|
||||
state.jsonEditorDialog.doc = item.value;
|
||||
state.jsonEditorDialog.visible = true;
|
||||
};
|
||||
|
||||
const onCloseJsonEditDialog = () => {
|
||||
state.jsoneditorDialog.item.value = JSON.stringify(JSON.parse(state.jsoneditorDialog.doc), null, 4);
|
||||
state.jsonEditorDialog.item.value = JSON.stringify(JSON.parse(state.jsonEditorDialog.doc), null, 4);
|
||||
};
|
||||
|
||||
const onSaveDoc = async (doc: string) => {
|
||||
@@ -440,31 +383,21 @@ const removeDataTab = (targetName: string) => {
|
||||
delete state.dataTabs[targetName];
|
||||
};
|
||||
|
||||
// 加载选中的tagPath
|
||||
const setSelects = async (mongoDbOptInfo: any) => {
|
||||
const { tagPath, dbId, db } = mongoDbOptInfo.dbOptInfo;
|
||||
state.query.tagPath = tagPath
|
||||
await searchMongo();
|
||||
state.mongoId = dbId
|
||||
await getDatabases();
|
||||
state.database = db
|
||||
await getCollections();
|
||||
if (state.collection) {
|
||||
state.collection = ''
|
||||
state.dataTabs = {}
|
||||
}
|
||||
const loadInstances = async () => {
|
||||
const res = await mongoApi.mongoList.request({pageNum: 1, pageSize: 1000,});
|
||||
if(!res.total) return
|
||||
state.instances = {tags:{}, tree:{}, dbs:{}, tables:{}} ; // 初始化变量
|
||||
for (const db of res.list) {
|
||||
let arr = state.instances.tree[db.tagId] || []
|
||||
const {tagId, tagPath} = db
|
||||
// tags
|
||||
state.instances.tags[db.tagId]={tagId, tagPath}
|
||||
// 实例
|
||||
arr.push(db)
|
||||
state.instances.tree[db.tagId] = arr;
|
||||
}
|
||||
}
|
||||
|
||||
// 判断如果有数据则加载下拉选项
|
||||
let mongoDbOptInfo = store.state.mongoDbOptInfo
|
||||
if (mongoDbOptInfo.dbOptInfo.tagPath) {
|
||||
setSelects(mongoDbOptInfo)
|
||||
}
|
||||
|
||||
// 监听选中操作的db变化,并加载下拉选项
|
||||
watch(store.state.mongoDbOptInfo, async (newValue) => {
|
||||
await setSelects(newValue)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
225
mayfly_go_web/src/views/ops/mongo/MongoInstanceTree.vue
Normal file
225
mayfly_go_web/src/views/ops/mongo/MongoInstanceTree.vue
Normal file
@@ -0,0 +1,225 @@
|
||||
<template>
|
||||
<div class="instances-box layout-aside">
|
||||
<el-row type="flex" justify="space-between">
|
||||
<el-col :span="24" :style="{
|
||||
maxHeight: state.instanceMenuMaxHeight,
|
||||
height: state.instanceMenuMaxHeight,
|
||||
overflow:'auto'
|
||||
}" class="el-scrollbar flex-auto">
|
||||
|
||||
<el-menu background-color="transparent" :collapse-transition="false">
|
||||
<!-- 第一级:tag -->
|
||||
<el-sub-menu v-for="tag of instances.tags" :index="tag.tagPath" :key="tag.tagPath">
|
||||
<template #title>
|
||||
<el-icon><FolderOpened color="#e6a23c"/></el-icon>
|
||||
<span>{{ tag.tagPath }}</span>
|
||||
</template>
|
||||
<!-- 第二级:数据库实例 -->
|
||||
<el-sub-menu v-for="inst in instances.tree[tag.tagId]"
|
||||
:index="'mongo-instance-' + inst.id"
|
||||
:key="'mongo-instance-' + inst.id"
|
||||
@click.prevent="changeInstance(inst)"
|
||||
>
|
||||
<template #title>
|
||||
<el-popover
|
||||
placement="right-start"
|
||||
title="mongo数据库实例信息"
|
||||
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.name}}</el-form-item>
|
||||
<el-form-item label="链接:">{{inst.uri}}</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
<!-- 第三级:数据库 -->
|
||||
<el-sub-menu v-for="db in instances.dbs[inst.id]"
|
||||
:index="inst.id + db.Name"
|
||||
:key="inst.id + db.Name"
|
||||
:class="state.nowSchema === (inst.id+db.Name) && 'checked'"
|
||||
@click.prevent="changeSchema(inst, db.Name)"
|
||||
>
|
||||
<template #title>
|
||||
<el-icon><Coin color="#67c23a"/></el-icon>
|
||||
<span class="checked-schema">
|
||||
{{ db.Name }}
|
||||
<span style="color: #8492a6;font-size: 13px">[{{formatByteSize(db.SizeOnDisk)}}]</span>
|
||||
</span>
|
||||
</template>
|
||||
<!-- 第四级 01:表 -->
|
||||
<el-sub-menu :index="inst.id + db.Name + '-table'" >
|
||||
<template #title>
|
||||
<div style="width: 100%" @click="loadTableNames(inst, db.Name)">
|
||||
<el-icon><Calendar color="#409eff"/></el-icon>
|
||||
<span>集合</span>
|
||||
<el-icon v-show="state.loading[inst.id + db.Name]" class="is-loading"><Loading /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
<el-menu-item :index="inst.id + db.Name + '-tableSearch'"
|
||||
:key="inst.id + db.Name + '-tableSearch'">
|
||||
<template #title>
|
||||
|
||||
<el-input size="small" placeholder="过滤" clearable
|
||||
@change="filterTableName(inst.id, db.Name)"
|
||||
@keyup="e => filterTableName(inst.id, db.Name, e)"
|
||||
v-model="state.filterParam[inst.id+db.Name]"/>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
|
||||
<template v-for="tb in instances.tables[inst.id+db.Name]" >
|
||||
<el-menu-item :index="inst.id + db.Name + tb.tableName"
|
||||
:key="inst.id + db.Name + tb.tableName"
|
||||
v-if="tb.show"
|
||||
@click="loadTableData(inst, db.Name, tb.tableName)"
|
||||
>
|
||||
<template #title>
|
||||
<div style="width: 100%" >
|
||||
<el-icon><Calendar color="#409eff"/></el-icon>
|
||||
<span :title="tb.tableComment||''">{{tb.tableName}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-sub-menu>
|
||||
</el-sub-menu>
|
||||
</el-sub-menu>
|
||||
</el-sub-menu>
|
||||
</el-menu>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {onBeforeMount, reactive} from 'vue';
|
||||
import {formatByteSize} from '@/common/utils/format';
|
||||
|
||||
const props = defineProps({
|
||||
instances: {
|
||||
type: Object, required: true
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits(['initLoadInstances','changeInstance','loadTableNames','loadTableData','changeSchema'])
|
||||
|
||||
onBeforeMount(async ()=>{
|
||||
await initLoadInstances()
|
||||
setHeight()
|
||||
})
|
||||
|
||||
const setHeight = () => {
|
||||
state.instanceMenuMaxHeight = window.innerHeight - 140 + 'px';
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
instanceMenuMaxHeight: '800px',
|
||||
nowSchema: '',
|
||||
filterParam: {},
|
||||
loading: {},
|
||||
|
||||
})
|
||||
|
||||
/**
|
||||
* 初始化加载实例数据
|
||||
*/
|
||||
const initLoadInstances = () => {
|
||||
emits('initLoadInstances')
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变选中的数据库实例
|
||||
* @param inst 选中的实例对象
|
||||
*/
|
||||
const changeInstance = (inst : any) => {
|
||||
emits('changeInstance', inst)
|
||||
}
|
||||
/**
|
||||
* 改变选中的数据库schema
|
||||
* @param inst 选中的实例对象
|
||||
* @param schema 选中的数据库schema
|
||||
*/
|
||||
const changeSchema = (inst : any, schema: string) => {
|
||||
state.nowSchema = inst.id + schema
|
||||
emits('changeSchema', inst, schema)
|
||||
}
|
||||
/**
|
||||
* 加载schema下所有表
|
||||
* @param inst 数据库实例
|
||||
* @param schema database名
|
||||
*/
|
||||
const loadTableNames = async (inst: any, schema: string) => {
|
||||
state.loading[inst.id+schema] = true
|
||||
await emits('loadTableNames', inst, schema, ()=>{
|
||||
state.loading[inst.id+schema] = false
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 加载选中表数据
|
||||
* @param inst 数据库实例
|
||||
* @param schema database名
|
||||
* @param tableName 表名
|
||||
*/
|
||||
const loadTableData = (inst: any, schema: string, tableName: string) => {
|
||||
emits('loadTableData', inst, schema, tableName)
|
||||
}
|
||||
|
||||
const filterTableName = (instId: number, schema: string, event?: any) => {
|
||||
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
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.instances-box {
|
||||
.el-menu{
|
||||
width: 275px;
|
||||
}
|
||||
.el-sub-menu{
|
||||
.checked{
|
||||
.checked-schema{
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
.el-sub-menu__title{
|
||||
padding-left: 0 !important;
|
||||
height: 30px !important;
|
||||
line-height: 30px !important;
|
||||
}
|
||||
.el-menu--vertical:not(.el-menu--collapse):not(.el-menu--popup-container) .el-sub-menu__title{
|
||||
padding-right: 10px;
|
||||
}
|
||||
.el-menu-item{
|
||||
padding-left: 0 !important;
|
||||
height: 20px !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
.el-icon{
|
||||
margin: 0;
|
||||
}
|
||||
.el-sub-menu__icon-arrow{
|
||||
top:inherit;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
.instances-pop-form{
|
||||
.el-form-item{
|
||||
margin-bottom: unset;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -408,8 +408,6 @@ const valChange = () => {
|
||||
|
||||
const openDataOps = (row: any) => {
|
||||
state.dbOps.db = row.Name
|
||||
|
||||
debugger
|
||||
let data = {
|
||||
tagPath: state.currentData.tagPath,
|
||||
dbId: state.dbOps.dbId,
|
||||
|
||||
Reference in New Issue
Block a user