feat: Sentinel mode support

- NewConnectionDialog: sentinel toggle + host/port/masterName/nodePassword form
- connection.ts: use ioredis sentinels config when sentinelEnabled
- Add sentinelEnabled/sentinelHost/sentinelPort/sentinelNodePassword to all types
- i18n keys for all sentinel fields (zh-CN + en)
This commit is contained in:
2026-07-05 16:43:52 +08:00
parent 1686af1a79
commit e46d6a80be
8 changed files with 133 additions and 2 deletions
+50
View File
@@ -22,6 +22,11 @@ const form = reactive({
tlsCertPath: '',
tlsKeyPath: '',
tlsRejectUnauthorized: false,
sentinelEnabled: false,
sentinelHost: '',
sentinelPort: 26379,
sentinelMasterName: '',
sentinelNodePassword: '',
separator: ':',
sshEnabled: false,
sshHost: '',
@@ -51,6 +56,12 @@ watch(() => props.visible, async (v) => {
tlsCaPath: props.connection.tlsCaPath || '',
tlsCertPath: props.connection.tlsCertPath || '',
tlsKeyPath: props.connection.tlsKeyPath || '',
tlsRejectUnauthorized: props.connection.tlsRejectUnauthorized || false,
sentinelEnabled: props.connection.sentinelEnabled || false,
sentinelHost: props.connection.sentinelHost || '',
sentinelPort: props.connection.sentinelPort || 26379,
sentinelMasterName: props.connection.sentinelMasterName || '',
sentinelNodePassword: props.connection.sentinelNodePassword || '',
separator: props.connection.separator,
sshEnabled: props.connection.sshEnabled || false,
sshHost: props.connection.sshHost || '',
@@ -65,6 +76,9 @@ watch(() => props.visible, async (v) => {
Object.assign(form, {
name: '', host: '127.0.0.1', port: 6379,
auth: '', username: '', tls: false, tlsCaPath: '', tlsCertPath: '', tlsKeyPath: '',
tlsRejectUnauthorized: false,
sentinelEnabled: false, sentinelHost: '', sentinelPort: 26379,
sentinelMasterName: '', sentinelNodePassword: '',
separator: ':',
sshEnabled: false, sshHost: '', sshPort: 22,
sshUsername: '', sshPassword: '', sshPrivateKeyPath: '', sshPassphrase: '',
@@ -128,6 +142,11 @@ async function handleTest() {
tlsCertPath: form.tlsCertPath,
tlsKeyPath: form.tlsKeyPath,
tlsRejectUnauthorized: form.tlsRejectUnauthorized,
sentinelEnabled: form.sentinelEnabled,
sentinelHost: form.sentinelHost.trim(),
sentinelPort: Number(form.sentinelPort) || 26379,
sentinelMasterName: form.sentinelMasterName.trim(),
sentinelNodePassword: form.sentinelNodePassword,
sshEnabled: form.sshEnabled,
sshHost: form.sshHost.trim(),
sshPort: Number(form.sshPort) || 22,
@@ -165,6 +184,11 @@ async function handleSave() {
tlsCertPath: form.tlsCertPath,
tlsKeyPath: form.tlsKeyPath,
tlsRejectUnauthorized: form.tlsRejectUnauthorized,
sentinelEnabled: form.sentinelEnabled,
sentinelHost: form.sentinelHost.trim(),
sentinelPort: Number(form.sentinelPort) || 26379,
sentinelMasterName: form.sentinelMasterName.trim(),
sentinelNodePassword: form.sentinelNodePassword,
sshEnabled: form.sshEnabled,
sshHost: form.sshHost.trim(),
sshPort: Number(form.sshPort) || 22,
@@ -249,6 +273,32 @@ async function handleSave() {
</el-form-item>
</template>
<!-- Sentinel -->
<el-divider />
<el-form-item>
<el-checkbox v-model="form.sentinelEnabled">{{ t('connection.sentinel') }}</el-checkbox>
</el-form-item>
<template v-if="form.sentinelEnabled">
<el-row :gutter="12">
<el-col :span="16">
<el-form-item :label="t('connection.sentinelHost')">
<el-input v-model="form.sentinelHost" placeholder="192.168.1.1" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="t('connection.sentinelPort')">
<el-input-number v-model="form.sentinelPort" :min="1" :max="65535" controls-position="right" style="width:100%" />
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="t('connection.sentinelMasterName')">
<el-input v-model="form.sentinelMasterName" placeholder="mymaster" />
</el-form-item>
<el-form-item :label="t('connection.sentinelNodePassword')">
<el-input v-model="form.sentinelNodePassword" type="password" show-password />
</el-form-item>
</template>
<!-- SSH Tunnel -->
<el-divider />
<el-form-item>
+5
View File
@@ -34,6 +34,11 @@ export default {
tlsCertPath: 'Client Certificate',
tlsKeyPath: 'Client Private Key',
tlsRejectUnauthorized: 'Verify Server Certificate',
sentinel: 'Sentinel Mode',
sentinelHost: 'Sentinel Host',
sentinelPort: 'Sentinel Port',
sentinelMasterName: 'Master Name',
sentinelNodePassword: 'Sentinel Password',
ssh: 'SSH Tunnel',
sshHost: 'SSH Host',
sshPort: 'SSH Port',
+5
View File
@@ -34,6 +34,11 @@ export default {
tlsCertPath: '客户端证书',
tlsKeyPath: '客户端私钥',
tlsRejectUnauthorized: '验证服务器证书',
sentinel: 'Sentinel 哨兵模式',
sentinelHost: '哨兵主机',
sentinelPort: '哨兵端口',
sentinelMasterName: 'Master 名称',
sentinelNodePassword: '哨兵密码',
ssh: 'SSH 隧道',
sshHost: 'SSH 主机',
sshPort: 'SSH 端口',
+17 -1
View File
@@ -22,7 +22,11 @@ export interface ConnectionConfig {
sshPrivateKeyPath: string
sshPassphrase: string
cluster: boolean
sentinelEnabled: boolean
sentinelHost: string
sentinelPort: number
sentinelMasterName: string
sentinelNodePassword: string
separator: string
order: number
createdAt: number
@@ -88,6 +92,11 @@ export const useConnectionStore = defineStore('connection', () => {
tlsCertPath: conn.tlsCertPath,
tlsKeyPath: conn.tlsKeyPath,
tlsRejectUnauthorized: conn.tlsRejectUnauthorized,
sentinelEnabled: conn.sentinelEnabled,
sentinelHost: conn.sentinelHost,
sentinelPort: conn.sentinelPort,
sentinelMasterName: conn.sentinelMasterName,
sentinelNodePassword: conn.sentinelNodePassword,
sshEnabled: conn.sshEnabled,
sshHost: conn.sshHost,
sshPort: conn.sshPort,
@@ -156,7 +165,9 @@ export const useConnectionStore = defineStore('connection', () => {
async function testConnection(opts: {
host: string; port: number; auth?: string; username?: string; tls?: boolean
tlsCaPath?: string; tlsCertPath?: string; tlsKeyPath?: string
tlsCaPath?: string; tlsCertPath?: string; tlsKeyPath?: string; tlsRejectUnauthorized?: boolean
sentinelEnabled?: boolean; sentinelHost?: string; sentinelPort?: number
sentinelMasterName?: string; sentinelNodePassword?: string
sshEnabled?: boolean; sshHost?: string; sshPort?: number; sshUsername?: string
sshPassword?: string; sshPrivateKeyPath?: string; sshPassphrase?: string
}): Promise<{ success: boolean; error?: string }> {
@@ -175,6 +186,11 @@ export const useConnectionStore = defineStore('connection', () => {
tlsCertPath: opts.tlsCertPath,
tlsKeyPath: opts.tlsKeyPath,
tlsRejectUnauthorized: (opts as any).tlsRejectUnauthorized,
sentinelEnabled: opts.sentinelEnabled,
sentinelHost: opts.sentinelHost,
sentinelPort: opts.sentinelPort,
sentinelMasterName: opts.sentinelMasterName,
sentinelNodePassword: opts.sentinelNodePassword,
sshEnabled: opts.sshEnabled,
sshHost: opts.sshHost,
sshPort: opts.sshPort,