feat: support database alias
This commit is contained in:
parent
42fa24debd
commit
6d3526c765
|
@ -179,8 +179,13 @@ func (b *browserService) OpenConnection(name string) (resp types.JSResp) {
|
||||||
dbInfoStr := info["Keyspace"][dbName]
|
dbInfoStr := info["Keyspace"][dbName]
|
||||||
if len(dbInfoStr) > 0 {
|
if len(dbInfoStr) > 0 {
|
||||||
dbInfo := b.parseDBItemInfo(dbInfoStr)
|
dbInfo := b.parseDBItemInfo(dbInfoStr)
|
||||||
|
var alias string
|
||||||
|
if selConn.Alias != nil {
|
||||||
|
alias = selConn.Alias[idx]
|
||||||
|
}
|
||||||
return types.ConnectionDB{
|
return types.ConnectionDB{
|
||||||
Name: dbName,
|
Name: dbName,
|
||||||
|
Alias: alias,
|
||||||
Index: idx,
|
Index: idx,
|
||||||
MaxKeys: dbInfo["keys"],
|
MaxKeys: dbInfo["keys"],
|
||||||
Expires: dbInfo["expires"],
|
Expires: dbInfo["expires"],
|
||||||
|
|
|
@ -20,6 +20,7 @@ type ConnectionConfig struct {
|
||||||
LoadSize int `json:"loadSize,omitempty" yaml:"load_size,omitempty"`
|
LoadSize int `json:"loadSize,omitempty" yaml:"load_size,omitempty"`
|
||||||
MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"`
|
MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"`
|
||||||
RefreshInterval int `json:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty"`
|
RefreshInterval int `json:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty"`
|
||||||
|
Alias map[int]string `json:"alias,omitempty" yaml:"alias,omitempty"`
|
||||||
SSL ConnectionSSL `json:"ssl,omitempty" yaml:"ssl,omitempty"`
|
SSL ConnectionSSL `json:"ssl,omitempty" yaml:"ssl,omitempty"`
|
||||||
SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"`
|
SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"`
|
||||||
Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"`
|
Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"`
|
||||||
|
@ -36,6 +37,7 @@ type Connections []Connection
|
||||||
|
|
||||||
type ConnectionDB struct {
|
type ConnectionDB struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Alias string `json:"alias,omitempty"`
|
||||||
Index int `json:"index"`
|
Index int `json:"index"`
|
||||||
MaxKeys int `json:"maxKeys"`
|
MaxKeys int `json:"maxKeys"`
|
||||||
Expires int `json:"expires,omitempty"`
|
Expires int `json:"expires,omitempty"`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { every, get, includes, isEmpty, map, sortBy, toNumber } from 'lodash'
|
import { every, get, includes, isEmpty, map, reject, sortBy, toNumber } from 'lodash'
|
||||||
import { computed, nextTick, ref, watch } from 'vue'
|
import { computed, nextTick, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { ListSentinelMasters, TestConnection } from 'wailsjs/go/services/connectionService.js'
|
import { ListSentinelMasters, TestConnection } from 'wailsjs/go/services/connectionService.js'
|
||||||
|
@ -10,6 +10,9 @@ import FileOpenInput from '@/components/common/FileOpenInput.vue'
|
||||||
import { KeyViewType } from '@/consts/key_view_type.js'
|
import { KeyViewType } from '@/consts/key_view_type.js'
|
||||||
import { useThemeVars } from 'naive-ui'
|
import { useThemeVars } from 'naive-ui'
|
||||||
import useBrowserStore from 'stores/browser.js'
|
import useBrowserStore from 'stores/browser.js'
|
||||||
|
import Delete from '@/components/icons/Delete.vue'
|
||||||
|
import Add from '@/components/icons/Add.vue'
|
||||||
|
import IconButton from '@/components/common/IconButton.vue'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog for new or edit connection
|
* Dialog for new or edit connection
|
||||||
|
@ -72,6 +75,24 @@ const onUpdateDBFilterType = (t) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const aliasPair = ref([
|
||||||
|
/*{ db: 0, alias: '' }*/
|
||||||
|
])
|
||||||
|
const onCreateAlias = () => {
|
||||||
|
return {
|
||||||
|
db: 0,
|
||||||
|
alias: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const onUpdateAlias = () => {
|
||||||
|
const val = reject(aliasPair.value, (v) => v == null || isEmpty(v.alias))
|
||||||
|
const result = {}
|
||||||
|
for (const elem of val) {
|
||||||
|
result[elem.db] = elem.alias
|
||||||
|
}
|
||||||
|
generalForm.value.alias = result
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => dbFilterList.value,
|
() => dbFilterList.value,
|
||||||
(list) => {
|
(list) => {
|
||||||
|
@ -210,6 +231,13 @@ watch(
|
||||||
generalForm.value = dialogStore.connParam || connectionStore.newDefaultConnection()
|
generalForm.value = dialogStore.connParam || connectionStore.newDefaultConnection()
|
||||||
dbFilterList.value = map(generalForm.value.dbFilterList, (item) => item + '')
|
dbFilterList.value = map(generalForm.value.dbFilterList, (item) => item + '')
|
||||||
generalForm.value.ssh.loginType = generalForm.value.ssh.loginType || 'pwd'
|
generalForm.value.ssh.loginType = generalForm.value.ssh.loginType || 'pwd'
|
||||||
|
// update alias display
|
||||||
|
const alias = get(generalForm.value, 'alias', {})
|
||||||
|
const pairs = []
|
||||||
|
for (const db in alias) {
|
||||||
|
pairs.push({ db: parseInt(db), alias: alias[db] })
|
||||||
|
}
|
||||||
|
aliasPair.value = pairs
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -254,9 +282,15 @@ const onClose = () => {
|
||||||
style="width: 600px"
|
style="width: 600px"
|
||||||
transform-origin="center">
|
transform-origin="center">
|
||||||
<n-spin :show="closingConnection">
|
<n-spin :show="closingConnection">
|
||||||
<n-tabs v-model:value="tab" animated type="line">
|
<n-tabs
|
||||||
|
v-model:value="tab"
|
||||||
|
animated
|
||||||
|
pane-style="min-height: 50vh;"
|
||||||
|
placement="left"
|
||||||
|
tab-style="justify-content: right;"
|
||||||
|
type="line">
|
||||||
<!-- General pane -->
|
<!-- General pane -->
|
||||||
<n-tab-pane :tab="$t('dialogue.connection.general')" display-directive="show" name="general">
|
<n-tab-pane :tab="$t('dialogue.connection.general')" display-directive="show:lazy" name="general">
|
||||||
<n-form
|
<n-form
|
||||||
ref="generalFormRef"
|
ref="generalFormRef"
|
||||||
:model="generalForm"
|
:model="generalForm"
|
||||||
|
@ -434,8 +468,42 @@ const onClose = () => {
|
||||||
</n-form>
|
</n-form>
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
|
||||||
|
<n-tab-pane :tab="$t('dialogue.connection.alias.title')" display-directive="show:lazy" name="alias">
|
||||||
|
<n-form
|
||||||
|
:model="generalForm.alias"
|
||||||
|
:show-label="false"
|
||||||
|
:show-require-mark="false"
|
||||||
|
label-placement="top">
|
||||||
|
<n-form-item required>
|
||||||
|
<n-dynamic-input
|
||||||
|
v-model:value="aliasPair"
|
||||||
|
@create="onCreateAlias"
|
||||||
|
@update:value="onUpdateAlias">
|
||||||
|
<template #default="{ value }">
|
||||||
|
<n-input-number
|
||||||
|
v-model:value="value.db"
|
||||||
|
:min="0"
|
||||||
|
:placeholder="$t('dialogue.connection.alias.db')"
|
||||||
|
:show-button="false"
|
||||||
|
@update:value="onUpdateAlias" />
|
||||||
|
<n-text>:</n-text>
|
||||||
|
<n-input
|
||||||
|
v-model:value="value.alias"
|
||||||
|
:placeholder="$t('dialogue.connection.alias.value')"
|
||||||
|
type="text"
|
||||||
|
@update:value="onUpdateAlias" />
|
||||||
|
</template>
|
||||||
|
<template #action="{ index, create, remove, move }">
|
||||||
|
<icon-button :icon="Delete" size="18" @click="() => remove(index)" />
|
||||||
|
<icon-button :icon="Add" size="18" @click="() => create(index)" />
|
||||||
|
</template>
|
||||||
|
</n-dynamic-input>
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
</n-tab-pane>
|
||||||
|
|
||||||
<!-- SSL pane -->
|
<!-- SSL pane -->
|
||||||
<n-tab-pane :tab="$t('dialogue.connection.ssl.title')" display-directive="show" name="ssl">
|
<n-tab-pane :tab="$t('dialogue.connection.ssl.title')" display-directive="show:lazy" name="ssl">
|
||||||
<n-form-item label-placement="left">
|
<n-form-item label-placement="left">
|
||||||
<n-checkbox v-model:checked="generalForm.ssl.enable" size="medium">
|
<n-checkbox v-model:checked="generalForm.ssl.enable" size="medium">
|
||||||
{{ $t('dialogue.connection.ssl.enable') }}
|
{{ $t('dialogue.connection.ssl.enable') }}
|
||||||
|
@ -478,7 +546,7 @@ const onClose = () => {
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
|
||||||
<!-- SSH pane -->
|
<!-- SSH pane -->
|
||||||
<n-tab-pane :tab="$t('dialogue.connection.ssh.title')" display-directive="show" name="ssh">
|
<n-tab-pane :tab="$t('dialogue.connection.ssh.title')" display-directive="show:lazy" name="ssh">
|
||||||
<n-form-item label-placement="left">
|
<n-form-item label-placement="left">
|
||||||
<n-checkbox v-model:checked="generalForm.ssh.enable" size="medium">
|
<n-checkbox v-model:checked="generalForm.ssh.enable" size="medium">
|
||||||
{{ $t('dialogue.connection.ssh.enable') }}
|
{{ $t('dialogue.connection.ssh.enable') }}
|
||||||
|
@ -538,7 +606,10 @@ const onClose = () => {
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
|
||||||
<!-- Sentinel pane -->
|
<!-- Sentinel pane -->
|
||||||
<n-tab-pane :tab="$t('dialogue.connection.sentinel.title')" display-directive="show" name="sentinel">
|
<n-tab-pane
|
||||||
|
:tab="$t('dialogue.connection.sentinel.title')"
|
||||||
|
display-directive="show:lazy"
|
||||||
|
name="sentinel">
|
||||||
<n-form-item label-placement="left">
|
<n-form-item label-placement="left">
|
||||||
<n-checkbox v-model:checked="generalForm.sentinel.enable" size="medium">
|
<n-checkbox v-model:checked="generalForm.sentinel.enable" size="medium">
|
||||||
{{ $t('dialogue.connection.sentinel.enable') }}
|
{{ $t('dialogue.connection.sentinel.enable') }}
|
||||||
|
@ -580,7 +651,7 @@ const onClose = () => {
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
|
||||||
<!-- Cluster pane -->
|
<!-- Cluster pane -->
|
||||||
<n-tab-pane :tab="$t('dialogue.connection.cluster.title')" display-directive="show" name="cluster">
|
<n-tab-pane :tab="$t('dialogue.connection.cluster.title')" display-directive="show:lazy" name="cluster">
|
||||||
<n-form-item label-placement="left">
|
<n-form-item label-placement="left">
|
||||||
<n-checkbox v-model:checked="generalForm.cluster.enable" size="medium">
|
<n-checkbox v-model:checked="generalForm.cluster.enable" size="medium">
|
||||||
{{ $t('dialogue.connection.cluster.enable') }}
|
{{ $t('dialogue.connection.cluster.enable') }}
|
||||||
|
|
|
@ -25,11 +25,6 @@ const updateOption = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef ZSetItem
|
|
||||||
* @property {string} value
|
|
||||||
* @property {string} score
|
|
||||||
*/
|
|
||||||
const zset = ref([{ value: '', score: 0 }])
|
const zset = ref([{ value: '', score: 0 }])
|
||||||
const onCreate = () => {
|
const onCreate = () => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import BrowserTree from './BrowserTree.vue'
|
||||||
import IconButton from '@/components/common/IconButton.vue'
|
import IconButton from '@/components/common/IconButton.vue'
|
||||||
import useTabStore from 'stores/tab.js'
|
import useTabStore from 'stores/tab.js'
|
||||||
import { computed, nextTick, onMounted, reactive, ref, unref, watch } from 'vue'
|
import { computed, nextTick, onMounted, reactive, ref, unref, watch } from 'vue'
|
||||||
import { find, get, map, size } from 'lodash'
|
import { find, get, isEmpty, map, size } from 'lodash'
|
||||||
import Refresh from '@/components/icons/Refresh.vue'
|
import Refresh from '@/components/icons/Refresh.vue'
|
||||||
import useDialogStore from 'stores/dialog.js'
|
import useDialogStore from 'stores/dialog.js'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
@ -50,16 +50,22 @@ const inCheckState = ref(false)
|
||||||
|
|
||||||
const dbSelectOptions = computed(() => {
|
const dbSelectOptions = computed(() => {
|
||||||
const dblist = browserStore.getDBList(props.server)
|
const dblist = browserStore.getDBList(props.server)
|
||||||
return map(dblist, (db) => {
|
return map(dblist, ({ db, alias, keyCount, maxKeys }) => {
|
||||||
if (props.db === db.db) {
|
let label
|
||||||
return {
|
if (!isEmpty(alias)) {
|
||||||
value: db.db,
|
// has alias
|
||||||
label: `db${db.db} (${db.keyCount}/${db.maxKeys})`,
|
label = `${alias}[${db}]`
|
||||||
|
} else {
|
||||||
|
label = `db${db}`
|
||||||
}
|
}
|
||||||
|
if (props.db === db) {
|
||||||
|
label += ` (${keyCount}/${maxKeys})`
|
||||||
|
} else {
|
||||||
|
label += ` (${maxKeys})`
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
value: db.db,
|
value: db,
|
||||||
label: `db${db.db} (${db.maxKeys})`,
|
label: label,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -201,6 +201,11 @@
|
||||||
"load_size": "Size of Keys Per Load",
|
"load_size": "Size of Keys Per Load",
|
||||||
"mark_color": "Mark Color"
|
"mark_color": "Mark Color"
|
||||||
},
|
},
|
||||||
|
"alias": {
|
||||||
|
"title": "Database Alias",
|
||||||
|
"db": "Input Database Index",
|
||||||
|
"value": "Input Database Alias"
|
||||||
|
},
|
||||||
"ssl": {
|
"ssl": {
|
||||||
"title": "SSL/TLS",
|
"title": "SSL/TLS",
|
||||||
"enable": "Enable SSL/TLS",
|
"enable": "Enable SSL/TLS",
|
||||||
|
|
|
@ -201,6 +201,11 @@
|
||||||
"load_size": "单次加载键数量",
|
"load_size": "单次加载键数量",
|
||||||
"mark_color": "标记颜色"
|
"mark_color": "标记颜色"
|
||||||
},
|
},
|
||||||
|
"alias": {
|
||||||
|
"title": "数据库别名",
|
||||||
|
"db": "输入数据库索引",
|
||||||
|
"value": "输入别名"
|
||||||
|
},
|
||||||
"ssl": {
|
"ssl": {
|
||||||
"title": "SSL/TLS",
|
"title": "SSL/TLS",
|
||||||
"enable": "启用SSL",
|
"enable": "启用SSL",
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
* redis database item
|
* redis database item
|
||||||
*/
|
*/
|
||||||
export class RedisDatabaseItem {
|
export class RedisDatabaseItem {
|
||||||
constructor({ db = 0, keyCount = 0, maxKeys = 0 }) {
|
constructor({ db = 0, alias = '', keyCount = 0, maxKeys = 0 }) {
|
||||||
this.db = db
|
this.db = db
|
||||||
|
this.alias = alias
|
||||||
this.keyCount = keyCount
|
this.keyCount = keyCount
|
||||||
this.maxKeys = maxKeys
|
this.maxKeys = maxKeys
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,6 +252,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
for (const dbItem of db) {
|
for (const dbItem of db) {
|
||||||
databases[dbItem.index] = new RedisDatabaseItem({
|
databases[dbItem.index] = new RedisDatabaseItem({
|
||||||
db: dbItem.index,
|
db: dbItem.index,
|
||||||
|
alias: dbItem.alias,
|
||||||
maxKeys: dbItem.maxKeys,
|
maxKeys: dbItem.maxKeys,
|
||||||
})
|
})
|
||||||
if (dbItem.index === lastDB) {
|
if (dbItem.index === lastDB) {
|
||||||
|
|
|
@ -164,6 +164,7 @@ const useConnectionStore = defineStore('connections', {
|
||||||
keyView: KeyViewType.Tree,
|
keyView: KeyViewType.Tree,
|
||||||
loadSize: 10000,
|
loadSize: 10000,
|
||||||
markColor: '',
|
markColor: '',
|
||||||
|
alias: {},
|
||||||
ssl: {
|
ssl: {
|
||||||
enable: false,
|
enable: false,
|
||||||
allowInsecure: true,
|
allowInsecure: true,
|
||||||
|
|
Loading…
Reference in New Issue