Files
JRedisDesktop/src/components/Sidebar.vue
T
Jokul d2fd07161c fix: UI improvements
- Remove auto-open devtools
- Settings as right drawer
- DB selector in title bar
- Sidebar expand/collapse
- Fix dark mode colors for key detail
2026-07-04 23:38:09 +08:00

131 lines
3.2 KiB
Vue

<script setup lang="ts">
// src/components/Sidebar.vue
import { ref } from 'vue'
import ConnectionList from './ConnectionList.vue'
import NewConnectionDialog from './NewConnectionDialog.vue'
import { useConnectionStore } from '@renderer/stores/connection'
import { useKeyStore } from '@renderer/stores/key'
import { useI18n } from '@renderer/i18n'
import type { ConnectionConfig } from '@renderer/stores/connection'
import { useKeyboard } from '@renderer/composables/useKeyboard'
import { ElMessage, ElMessageBox } from 'element-plus'
const connStore = useConnectionStore()
const keyStore = useKeyStore()
const { t } = useI18n()
const dialogVisible = ref(false)
const editingConnection = ref<ConnectionConfig | null>(null)
const collapsed = ref(false)
function handleEdit(conn: ConnectionConfig | null) {
editingConnection.value = conn
dialogVisible.value = true
}
function handleNew() {
editingConnection.value = null
dialogVisible.value = true
}
async function deleteSelectedKey() {
if (!connStore.activeId || !keyStore.selectedKey) return
try {
await ElMessageBox.confirm(t('key.deleteConfirm', { key: keyStore.selectedKey }), t('common.confirm'))
await window.electronAPI.redis.deleteKey(connStore.activeId, keyStore.selectedKey)
ElMessage.success(t('key.deleted'))
keyStore.selectedKey = null
keyStore.keyData = null
await keyStore.scanKeys(connStore.activeId, '0', true)
} catch { /* cancelled */ }
}
function deselectKey() {
keyStore.selectedKey = null
keyStore.keyData = null
}
function refreshAll() {
if (connStore.activeId) {
keyStore.scanKeys(connStore.activeId, '0', true)
}
}
useKeyboard({
'ctrl+n': handleNew,
'ctrl+r': refreshAll,
'f5': refreshAll,
'delete': deleteSelectedKey,
'escape': deselectKey,
})
</script>
<template>
<aside class="sidebar" :class="{ collapsed }">
<div class="sidebar-header" v-if="!collapsed">
<ConnectionList @edit="handleEdit" />
</div>
<button class="collapse-btn" @click="collapsed = !collapsed" :title="collapsed ? '展开' : '收缩'">
<el-icon>
<component :is="collapsed ? 'ArrowRight' : 'ArrowLeft'" />
</el-icon>
</button>
<NewConnectionDialog
v-model:visible="dialogVisible"
:connection="editingConnection"
/>
</aside>
</template>
<style scoped>
.sidebar {
width: 260px;
flex-shrink: 0;
background: var(--bg-secondary);
border-right: 1px solid var(--border-color);
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
transition: width 0.2s ease;
}
.sidebar.collapsed {
width: 36px;
}
.sidebar-header {
flex: 1;
overflow: hidden;
}
.collapse-btn {
position: absolute;
top: 50%;
right: -12px;
transform: translateY(-50%);
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--bg-secondary);
border: 1px solid var(--border-color);
color: var(--text-muted);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
z-index: 10;
transition: all 0.2s;
}
.collapse-btn:hover {
background: var(--bg-card-hover);
color: var(--text-primary);
border-color: var(--border-accent);
}
.sidebar.collapsed .collapse-btn {
right: -12px;
}
</style>