mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-07 18:00:25 +08:00
feat: 代码小调整
This commit is contained in:
106
mayfly_go_web/src/views/ops/component/TagMenu.vue
Normal file
106
mayfly_go_web/src/views/ops/component/TagMenu.vue
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
<template>
|
||||||
|
<div class="instances-box layout-aside">
|
||||||
|
<el-row type="flex" justify="space-between">
|
||||||
|
<el-col :span="24"
|
||||||
|
:style="{ maxHeight: instanceMenuMaxHeight, height: instanceMenuMaxHeight, overflow: 'auto' }"
|
||||||
|
class="el-scrollbar flex-auto">
|
||||||
|
<el-menu background-color="transparent" :collapse-transition="false">
|
||||||
|
<!-- 第一级:tag -->
|
||||||
|
<el-sub-menu v-for="tag of tags" :index="tag.tagPath" :key="tag.tagPath"
|
||||||
|
@click.stop="clickTag(tag.tagPath)">
|
||||||
|
<template #title>
|
||||||
|
<el-icon>
|
||||||
|
<FolderOpened v-if="opend[tag.tagPath]" color="#e6a23c" />
|
||||||
|
<Folder v-else />
|
||||||
|
</el-icon>
|
||||||
|
<span>{{ tag.tagPath }}</span>
|
||||||
|
</template>
|
||||||
|
<slot :tag="tag" name="submenu"></slot>
|
||||||
|
</el-sub-menu>
|
||||||
|
</el-menu>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, toRefs } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
instanceMenuMaxHeight: {
|
||||||
|
type: [Number, String],
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
type: Object, required: true
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
instanceMenuMaxHeight: props.instanceMenuMaxHeight,
|
||||||
|
tags: props.tags,
|
||||||
|
opend: {},
|
||||||
|
})
|
||||||
|
|
||||||
|
const {
|
||||||
|
opend,
|
||||||
|
} = toRefs(state)
|
||||||
|
|
||||||
|
const clickTag = (tagPath: string) => {
|
||||||
|
if (state.opend[tagPath] === undefined) {
|
||||||
|
state.opend[tagPath] = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const opend = state.opend[tagPath]
|
||||||
|
state.opend[tagPath] = !opend
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.instances-box {
|
||||||
|
.el-menu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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>
|
||||||
@@ -219,7 +219,8 @@
|
|||||||
layout="prev, pager, next, total, jumper" v-model:current-page="dt.pageNum"
|
layout="prev, pager, next, total, jumper" v-model:current-page="dt.pageNum"
|
||||||
:page-size="defalutLimit"></el-pagination>
|
:page-size="defalutLimit"></el-pagination>
|
||||||
</el-row>
|
</el-row>
|
||||||
<div style=" font-size: 12px; padding: 0 10px; color: #606266"><span>{{ dt.sql }}</span></div>
|
<div style=" font-size: 12px; padding: 0 10px; color: #606266"><span>{{ dt.sql }}</span>
|
||||||
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-container>
|
</el-container>
|
||||||
@@ -258,7 +259,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, nextTick, onMounted, reactive, watch } from 'vue';
|
import { computed, nextTick, onMounted, reactive } from 'vue';
|
||||||
import { dbApi } from './api';
|
import { dbApi } from './api';
|
||||||
|
|
||||||
import { format as sqlFormatter } from 'sql-formatter';
|
import { format as sqlFormatter } from 'sql-formatter';
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="instances-box layout-aside">
|
<tag-menu :instanceMenuMaxHeight="instanceMenuMaxHeight" :tags="instances.tags">
|
||||||
<el-row type="flex" justify="space-between">
|
<template #submenu="props">
|
||||||
<el-col :span="24" :style="{maxHeight: instanceMenuMaxHeight,height: instanceMenuMaxHeight, overflow:'auto'}" class="el-scrollbar flex-auto">
|
|
||||||
<el-menu background-color="transparent" ref="menuRef">
|
|
||||||
<!-- 第一级: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="'instance-' + inst.id"
|
<el-sub-menu v-for="inst in instances.tree[props.tag.tagId]" :index="'instance-' + inst.id"
|
||||||
:key="'instance-' + inst.id" @click="changeInstance(inst, ()=>{})">
|
:key="'instance-' + inst.id" @click.stop="changeInstance(inst, () => { })">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-popover placement="right-start" title="数据库实例信息" trigger="hover" :width="210">
|
<el-popover placement="right-start" title="数据库实例信息" trigger="hover" :width="210">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
@@ -34,9 +24,9 @@
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
<!-- 第三级:数据库 -->
|
<!-- 第三级:数据库 -->
|
||||||
<el-sub-menu v-for="schema in instances.dbs[inst.id]" :index="inst.id + schema"
|
<el-sub-menu v-for="schema in instances.dbs[inst.id]" :index="inst.id + schema" :key="inst.id + schema"
|
||||||
:key="inst.id + schema" :class="state.nowSchema === (inst.id + schema) && 'checked'"
|
:class="state.nowSchema === (inst.id + schema) && 'checked'"
|
||||||
@click="changeSchema(inst, schema)">
|
@click.stop="changeSchema(inst, schema)">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Coin color="#67c23a" />
|
<Coin color="#67c23a" />
|
||||||
@@ -96,9 +86,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-for="sql in instances.sqls[inst.id + schema]">
|
<template v-for="sql in instances.sqls[inst.id + schema]">
|
||||||
<el-menu-item :index="inst.id + schema + sql.name"
|
<el-menu-item :index="inst.id + schema + sql.name" :key="inst.id + schema + sql.name"
|
||||||
:key="inst.id + schema + sql.name" v-if="sql.show"
|
v-if="sql.show" @click="loadSql(inst, schema, sql.name)">
|
||||||
@click="loadSql(inst, schema, sql.name)">
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<div style="width: 100%">
|
<div style="width: 100%">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
@@ -112,16 +101,14 @@
|
|||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</template>
|
||||||
</el-menu>
|
</tag-menu>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onBeforeMount, onMounted, reactive, ref, Ref, watch } from 'vue';
|
import { nextTick, onBeforeMount, onMounted, reactive, ref, Ref, watch } from 'vue';
|
||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
|
import TagMenu from '../../component/TagMenu.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
instanceMenuMaxHeight: {
|
instanceMenuMaxHeight: {
|
||||||
@@ -241,46 +228,6 @@ watch(()=>store.state.sqlExecInfo.dbOptInfo, async newValue => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.instances-box {
|
|
||||||
.el-menu {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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 {
|
.instances-pop-form {
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: unset;
|
margin-bottom: unset;
|
||||||
|
|||||||
@@ -1,27 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="instances-box layout-aside">
|
<tag-menu :instanceMenuMaxHeight="state.instanceMenuMaxHeight" :tags="instances.tags">
|
||||||
<el-row type="flex" justify="space-between">
|
<template #submenu="props">
|
||||||
<el-col :span="24" :style="{
|
<el-sub-menu v-for="inst in instances.tree[props.tag.tagId]" :index="'mongo-instance-' + inst.id"
|
||||||
maxHeight: state.instanceMenuMaxHeight,
|
:key="'mongo-instance-' + inst.id" @click.stop="changeInstance(inst, () => { })">
|
||||||
height: state.instanceMenuMaxHeight,
|
|
||||||
overflow: 'auto'
|
|
||||||
}" class="el-scrollbar flex-auto">
|
|
||||||
|
|
||||||
<el-menu background-color="transparent" ref="menuRef">
|
|
||||||
<!-- 第一级: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>
|
<template #title>
|
||||||
<el-popover placement="right-start" title="mongo数据库实例信息" trigger="hover" :width="210">
|
<el-popover placement="right-start" title="mongo数据库实例信息" trigger="hover" :width="210">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
@@ -38,9 +19,9 @@
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
<!-- 第三级:数据库 -->
|
<!-- 第三级:数据库 -->
|
||||||
<el-sub-menu v-for="db in instances.dbs[inst.id]" :index="inst.id + db.Name"
|
<el-sub-menu v-for="db in instances.dbs[inst.id]" :index="inst.id + db.Name" :key="inst.id + db.Name"
|
||||||
:key="inst.id + db.Name" :class="state.nowSchema === (inst.id + db.Name) && 'checked'"
|
:class="state.nowSchema === (inst.id + db.Name) && 'checked'"
|
||||||
@click.prevent="changeSchema(inst, db.Name)">
|
@click.stop="changeSchema(inst, db.Name)">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Coin color="#67c23a" />
|
<Coin color="#67c23a" />
|
||||||
@@ -93,17 +74,15 @@
|
|||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</template>
|
||||||
</el-menu>
|
</tag-menu>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onBeforeMount, onMounted, reactive, ref, Ref, watch } from 'vue';
|
import { nextTick, onBeforeMount, onMounted, reactive, ref, Ref, watch } from 'vue';
|
||||||
import { formatByteSize } from '@/common/utils/format';
|
import { formatByteSize } from '@/common/utils/format';
|
||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
|
import TagMenu from '../component/TagMenu.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
instances: {
|
instances: {
|
||||||
@@ -119,7 +98,7 @@ onBeforeMount(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const setHeight = () => {
|
const setHeight = () => {
|
||||||
state.instanceMenuMaxHeight = window.innerHeight - 140 + 'px';
|
state.instanceMenuMaxHeight = window.innerHeight - 115 + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
const menuRef = ref(null) as Ref
|
const menuRef = ref(null) as Ref
|
||||||
@@ -226,46 +205,6 @@ watch(()=>store.state.mongoDbOptInfo.dbOptInfo, async newValue => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.instances-box {
|
|
||||||
.el-menu {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.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 {
|
.instances-pop-form {
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: unset;
|
margin-bottom: unset;
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-card>
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="3">
|
<el-col :span="4">
|
||||||
<redis-instance-tree
|
<redis-instance-tree @init-load-instances="initLoadInstances" @change-instance="changeInstance"
|
||||||
@init-load-instances="initLoadInstances"
|
@change-schema="loadInitSchema" :instances="state.instances" />
|
||||||
@change-instance="changeInstance"
|
|
||||||
@change-schema="loadInitSchema"
|
|
||||||
:instances="state.instances"
|
|
||||||
/>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="19" style="border-left: 1px solid var(--el-card-border-color)">
|
<el-col :span="20" style="border-left: 1px solid var(--el-card-border-color);">
|
||||||
<el-col class="mt10">
|
<el-col class="mt10">
|
||||||
<el-form class="search-form" label-position="right" :inline="true" label-width="60px">
|
<el-form class="search-form" label-position="right" :inline="true" label-width="60px">
|
||||||
<el-form-item label="key" label-width="40px">
|
<el-form-item label="key" label-width="40px">
|
||||||
@@ -42,7 +37,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-table v-loading="state.loading" :data="state.keys" stripe :highlight-current-row="true" style="cursor: pointer">
|
<el-table v-loading="state.loading" :data="state.keys" stripe :highlight-current-row="true"
|
||||||
|
style="cursor: pointer">
|
||||||
<el-table-column show-overflow-tooltip prop="key" label="key"></el-table-column>
|
<el-table-column show-overflow-tooltip prop="key" label="key"></el-table-column>
|
||||||
<el-table-column prop="type" label="type" width="80">
|
<el-table-column prop="type" label="type" width="80">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -66,8 +62,6 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<div style="text-align: center; margin-top: 10px"></div>
|
<div style="text-align: center; margin-top: 10px"></div>
|
||||||
|
|
||||||
<hash-value v-model:visible="hashValueDialog.visible" :operationType="dataEdit.operationType"
|
<hash-value v-model:visible="hashValueDialog.visible" :operationType="dataEdit.operationType"
|
||||||
@@ -331,19 +325,19 @@ const initLoadInstances = async ()=>{
|
|||||||
// 实例
|
// 实例
|
||||||
arr.push(db)
|
arr.push(db)
|
||||||
state.instances.tree[db.tagId] = arr;
|
state.instances.tree[db.tagId] = arr;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeInstance = async (inst: any, fn: Function) => {
|
const changeInstance = async (inst: any, fn: Function) => {
|
||||||
let dbs = state.instances.dbs[inst.id] || []
|
let dbs = inst.db.split(',').map((x: string) => {
|
||||||
if(dbs.length <=0 ){
|
return { name: `db${x}`, keys: 0 }
|
||||||
const res = await redisApi.redisInfo.request({ id: inst.id, host:inst.host });
|
|
||||||
for (let db in res.Keyspace){
|
|
||||||
dbs.push({
|
|
||||||
name: db,
|
|
||||||
keys: res.Keyspace[db]?.split(',')[0]?.split('=')[1] || 0
|
|
||||||
})
|
})
|
||||||
|
const res = await redisApi.redisInfo.request({ id: inst.id, host: inst.host, section: "Keyspace" });
|
||||||
|
for (let db in res.Keyspace) {
|
||||||
|
for (let d of dbs) {
|
||||||
|
if (db == d.name) {
|
||||||
|
d.keys = res.Keyspace[db]?.split(',')[0]?.split('=')[1] || 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,68 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="instances-box layout-aside">
|
<tag-menu :instanceMenuMaxHeight="state.instanceMenuMaxHeight" :tags="instances.tags">
|
||||||
<el-row type="flex" justify="space-between">
|
<template #submenu="props">
|
||||||
<el-col :span="24" :style="{
|
<el-sub-menu v-for="inst in instances.tree[props.tag.tagId]" :index="'redis-instance-' + inst.id"
|
||||||
maxHeight: state.instanceMenuMaxHeight,
|
:key="'redis-instance-' + inst.id" @click.stop="changeInstance(inst)">
|
||||||
height: state.instanceMenuMaxHeight,
|
|
||||||
overflow:'auto'
|
|
||||||
}" class="el-scrollbar flex-auto">
|
|
||||||
|
|
||||||
<el-menu background-color="transparent" ref="menuRef">
|
|
||||||
<!-- 第一级:tag -->
|
|
||||||
<el-sub-menu v-for="tag of instances.tags" :index="tag.tagPath" :key="tag.tagPath">
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon><FolderOpened color="#e6a23c"/></el-icon>
|
<el-popover placement="right-start" title="redis实例信息" trigger="hover" :width="210">
|
||||||
<span>{{ tag.tagPath }}</span>
|
|
||||||
</template>
|
|
||||||
<!-- 第二级:数据库实例 -->
|
|
||||||
<el-sub-menu v-for="inst in instances.tree[tag.tagId]"
|
|
||||||
:index="'redis-instance-' + inst.id"
|
|
||||||
:key="'redis-instance-' + inst.id"
|
|
||||||
@click.prevent="changeInstance(inst)"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<el-popover
|
|
||||||
placement="right-start"
|
|
||||||
title="mongo数据库实例信息"
|
|
||||||
trigger="hover"
|
|
||||||
:width="210"
|
|
||||||
>
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<span> <el-icon><MostlyCloudy color="#409eff"/></el-icon>{{ inst.name }}</span>
|
<span> <el-icon>
|
||||||
|
<MostlyCloudy color="#409eff" />
|
||||||
|
</el-icon>{{ inst.name }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-form class="instances-pop-form" label-width="55px" :size="'small'">
|
<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.name }}</el-form-item>
|
||||||
<el-form-item label="链接:">{{ inst.host }}</el-form-item>
|
<el-form-item label="链接:">{{ inst.host }}</el-form-item>
|
||||||
|
<el-form-item label="备注:">{{ inst.remark }}</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</template>
|
</template>
|
||||||
<!-- 第三级:数据库 -->
|
<!-- 第三级:数据库 -->
|
||||||
<el-sub-menu v-for="db in instances.dbs[inst.id]"
|
<el-menu-item v-for="db in instances.dbs[inst.id]" :index="inst.id + db.name" :key="inst.id + db.name"
|
||||||
:index="inst.id + db.name"
|
|
||||||
:key="inst.id + db.name"
|
|
||||||
:class="state.nowSchema === (inst.id + db.name) && 'checked'"
|
:class="state.nowSchema === (inst.id + db.name) && 'checked'"
|
||||||
@click.prevent="changeSchema(inst, db.name)"
|
@click="changeSchema(inst, db.name)">
|
||||||
>
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon><Coin color="#67c23a"/></el-icon>
|
<el-icon>
|
||||||
|
<Coin color="#67c23a" />
|
||||||
|
</el-icon>
|
||||||
<span class="checked-schema">
|
<span class="checked-schema">
|
||||||
{{ db.name }} [{{ db.keys }}]
|
{{ db.name }} [{{ db.keys }}]
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
</el-menu-item>
|
||||||
</el-sub-menu>
|
</el-sub-menu>
|
||||||
</el-sub-menu>
|
</template>
|
||||||
</el-sub-menu>
|
</tag-menu>
|
||||||
</el-menu>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onBeforeMount, onMounted, reactive, Ref, ref, watch } from 'vue';
|
import { onBeforeMount, onMounted, reactive, Ref, ref, watch } from 'vue';
|
||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
|
import TagMenu from '../component/TagMenu.vue';
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
instances: {
|
instances: {
|
||||||
@@ -78,7 +56,7 @@ onBeforeMount(async ()=>{
|
|||||||
})
|
})
|
||||||
|
|
||||||
const setHeight = () => {
|
const setHeight = () => {
|
||||||
state.instanceMenuMaxHeight = window.innerHeight - 140 + 'px';
|
state.instanceMenuMaxHeight = window.innerHeight - 115 + 'px';
|
||||||
}
|
}
|
||||||
|
|
||||||
const menuRef = ref(null) as Ref;
|
const menuRef = ref(null) as Ref;
|
||||||
@@ -138,39 +116,6 @@ watch(()=>store.state.redisDbOptInfo.dbOptInfo, async newValue =>{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<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 {
|
.instances-pop-form {
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: unset;
|
margin-bottom: unset;
|
||||||
|
|||||||
@@ -76,36 +76,42 @@ func (r *Redis) RedisInfo(rc *req.Ctx) {
|
|||||||
g := rc.GinCtx
|
g := rc.GinCtx
|
||||||
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
|
ri := r.RedisApp.GetRedisInstance(uint64(ginx.PathParamInt(g, "id")), 0)
|
||||||
|
|
||||||
var res string
|
section := rc.GinCtx.Query("section")
|
||||||
var err error
|
|
||||||
|
|
||||||
mode := ri.Info.Mode
|
mode := ri.Info.Mode
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
var redisCli *redis.Client
|
||||||
|
|
||||||
if mode == "" || mode == entity.RedisModeStandalone || mode == entity.RedisModeSentinel {
|
if mode == "" || mode == entity.RedisModeStandalone || mode == entity.RedisModeSentinel {
|
||||||
res, err = ri.Cli.Info(ctx).Result()
|
redisCli = ri.Cli
|
||||||
} else if mode == entity.RedisModeCluster {
|
} else if mode == entity.RedisModeCluster {
|
||||||
host := rc.GinCtx.Query("host")
|
host := rc.GinCtx.Query("host")
|
||||||
biz.NotEmpty(host, "集群模式host信息不能为空")
|
biz.NotEmpty(host, "集群模式host信息不能为空")
|
||||||
clusterClient := ri.ClusterCli
|
clusterClient := ri.ClusterCli
|
||||||
var redisClient *redis.Client
|
|
||||||
// 遍历集群的master节点找到该redis client
|
// 遍历集群的master节点找到该redis client
|
||||||
clusterClient.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error {
|
clusterClient.ForEachMaster(ctx, func(ctx context.Context, client *redis.Client) error {
|
||||||
if host == client.Options().Addr {
|
if host == client.Options().Addr {
|
||||||
redisClient = client
|
redisCli = client
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if redisClient == nil {
|
if redisCli == nil {
|
||||||
// 遍历集群的slave节点找到该redis client
|
// 遍历集群的slave节点找到该redis client
|
||||||
clusterClient.ForEachSlave(ctx, func(ctx context.Context, client *redis.Client) error {
|
clusterClient.ForEachSlave(ctx, func(ctx context.Context, client *redis.Client) error {
|
||||||
if host == client.Options().Addr {
|
if host == client.Options().Addr {
|
||||||
redisClient = client
|
redisCli = client
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
biz.NotNil(redisClient, "该实例不在该集群中")
|
biz.NotNil(redisCli, "该实例不在该集群中")
|
||||||
res, err = redisClient.Info(ctx).Result()
|
}
|
||||||
|
|
||||||
|
var res string
|
||||||
|
var err error
|
||||||
|
if section == "" {
|
||||||
|
res, err = ri.Cli.Info(ctx).Result()
|
||||||
|
} else {
|
||||||
|
res, err = ri.Cli.Info(ctx, section).Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
biz.ErrIsNilAppendErr(err, "获取redis info失败: %s")
|
biz.ErrIsNilAppendErr(err, "获取redis info失败: %s")
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ type Redis struct {
|
|||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
Host *string `json:"host"`
|
Host *string `json:"host"`
|
||||||
Db string `json:"db"`
|
Db string `json:"db"`
|
||||||
ProjectId *int64 `json:"projectId"`
|
|
||||||
Project *string `json:"project"`
|
|
||||||
Mode *string `json:"mode"`
|
Mode *string `json:"mode"`
|
||||||
EnableSshTunnel *int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
|
EnableSshTunnel *int8 `json:"enableSshTunnel"` // 是否启用ssh隧道
|
||||||
SshTunnelMachineId *uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
|
SshTunnelMachineId *uint64 `json:"sshTunnelMachineId"` // ssh隧道机器id
|
||||||
|
|||||||
Reference in New Issue
Block a user