refactor: move type-badge from KeyDetail header to editors with colored border style

This commit is contained in:
2026-07-12 11:25:13 +08:00
parent 9848d97b4c
commit 775b66054a
8 changed files with 102 additions and 42 deletions
@@ -6,6 +6,17 @@ import { useI18n } from '@renderer/i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const { t } = useI18n()
@@ -126,7 +137,7 @@ async function addField() {
<template>
<div class="hash-editor">
<div class="editor-toolbar">
<span class="type-badge">HASH</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">HASH</span>
<span class="item-count">{{ t('editor.fieldCount', { n: fields.length }) }}</span>
<el-input v-model="filterText" :placeholder="t('editor.filter')" size="small" clearable style="width: 150px" />
<el-button size="small" type="primary" @click="showAddDialog = true">{{ t('editor.addField') }}</el-button>
@@ -198,9 +209,8 @@ async function addField() {
.type-badge {
font-size: 10px;
font-weight: 700;
color: var(--accent-light);
background: var(--accent-bg);
padding: 2px 8px;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
@@ -1,11 +1,22 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { useKeyStore } from '@renderer/stores/key'
import { useConnectionStore } from '@renderer/stores/connection'
import { useI18n } from '@renderer/i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const { t } = useI18n()
@@ -98,7 +109,7 @@ function nextPage() {
<template>
<div class="list-editor">
<div class="editor-toolbar">
<span class="type-badge">LIST</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">LIST</span>
<span class="item-count">{{ t('editor.elements', { n: totalCount }) }}</span>
<el-button size="small" type="primary" @click="showAddDialog = true">{{ t('editor.push') }}</el-button>
<el-button size="small" @click="loadList" :loading="loading">{{ t('common.refresh') }}</el-button>
@@ -160,9 +171,8 @@ function nextPage() {
.type-badge {
font-size: 10px;
font-weight: 700;
color: var(--accent-light);
background: var(--accent-bg);
padding: 2px 8px;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
@@ -8,6 +8,18 @@ import { useI18n } from '@renderer/i18n'
import { ElMessage } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
json: 'var(--color-blue)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const appStore = useAppStore()
const { t } = useI18n()
@@ -62,7 +74,7 @@ async function save() {
<template>
<div class="rejson-editor">
<div class="editor-toolbar">
<span class="type-badge">ReJSON</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">ReJSON</span>
<span class="spacer" />
<el-button v-if="!isEditing" size="small" type="primary" @click="isEditing = true">{{ t('editor.edit') }}</el-button>
<template v-else>
@@ -85,7 +97,7 @@ async function save() {
<style scoped>
.rejson-editor { height: 100%; display: flex; flex-direction: column; }
.editor-toolbar { padding: 12px; display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--border-color); flex-shrink: 0; }
.type-badge { font-size: 10px; font-weight: 700; color: var(--accent-light); background: var(--accent-bg); padding: 2px 8px; border-radius: 4px; }
.type-badge { font-size: 10px; font-weight: 700; border: 1px solid; padding: 1px 6px; border-radius: 4px; letter-spacing: 0.05em; }
.spacer { flex: 1; }
.editor-content { flex: 1; overflow: hidden; }
</style>
@@ -1,11 +1,22 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { useKeyStore } from '@renderer/stores/key'
import { useConnectionStore } from '@renderer/stores/connection'
import { useI18n } from '@renderer/i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const { t } = useI18n()
@@ -71,7 +82,7 @@ watch([members, filterText], () => {
<template>
<div class="set-editor">
<div class="editor-toolbar">
<span class="type-badge">SET</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">SET</span>
<span class="item-count">{{ t('editor.members', { n: members.length }) }}</span>
<el-input v-model="filterText" :placeholder="t('editor.filter')" size="small" clearable style="width: 150px" />
<el-button size="small" type="primary" @click="showAddDialog = true">{{ t('common.add') }}</el-button>
@@ -117,9 +128,8 @@ watch([members, filterText], () => {
.type-badge {
font-size: 10px;
font-weight: 700;
color: var(--accent-light);
background: var(--accent-bg);
padding: 2px 8px;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
@@ -1,11 +1,22 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { useKeyStore } from '@renderer/stores/key'
import { useConnectionStore } from '@renderer/stores/connection'
import { useI18n } from '@renderer/i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const { t } = useI18n()
@@ -246,7 +257,7 @@ async function trimStream() {
<template>
<div class="stream-editor">
<div class="editor-toolbar">
<span class="type-badge">STREAM</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">STREAM</span>
<span class="item-count">{{ t('editor.entries', { n: entries.length }) }}</span>
<el-button size="small" type="primary" @click="showAddDialog = true">{{ t('common.add') }}</el-button>
<el-popconfirm :title="t('editor.trimConfirm')">
@@ -370,9 +381,8 @@ async function trimStream() {
.type-badge {
font-size: 10px;
font-weight: 700;
color: var(--accent-light);
background: var(--accent-bg);
padding: 2px 8px;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
@@ -8,6 +8,17 @@ import { useI18n } from '@renderer/i18n'
import { ElMessage } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const appStore = useAppStore()
const { t } = useI18n()
@@ -160,7 +171,7 @@ onUnmounted(() => {
<template>
<div class="string-editor">
<div class="editor-toolbar">
<span class="type-badge">STRING</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">STRING</span>
<el-select v-model="selectedFormat" size="small" style="width:140px">
<el-option
v-for="opt in formatOptions"
@@ -222,9 +233,8 @@ onUnmounted(() => {
.type-badge {
font-size: 10px;
font-weight: 700;
color: var(--accent-light);
background: var(--accent-bg);
padding: 2px 8px;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
@@ -1,11 +1,22 @@
<script setup lang="ts">
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { useKeyStore } from '@renderer/stores/key'
import { useConnectionStore } from '@renderer/stores/connection'
import { useI18n } from '@renderer/i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
const keyStore = useKeyStore()
const typeColor = computed(() => {
const colors: Record<string, string> = {
string: 'var(--color-green)',
hash: 'var(--color-yellow)',
list: 'var(--color-cyan)',
set: 'var(--color-purple)',
zset: 'var(--color-red)',
stream: 'var(--color-orange)',
}
return colors[keyStore.selectedType || ''] || 'var(--text-muted)'
})
const connStore = useConnectionStore()
const { t } = useI18n()
@@ -89,7 +100,7 @@ watch([items, filterText, sortOrder], () => {
<template>
<div class="zset-editor">
<div class="editor-toolbar">
<span class="type-badge">ZSET</span>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">ZSET</span>
<span class="item-count">{{ t('editor.members', { n: items.length }) }}</span>
<el-input v-model="filterText" :placeholder="t('editor.filter')" size="small" clearable style="width: 150px" />
<el-radio-group v-model="sortOrder" size="small">
@@ -145,9 +156,8 @@ watch([items, filterText, sortOrder], () => {
.type-badge {
font-size: 10px;
font-weight: 700;
color: var(--accent-light);
background: var(--accent-bg);
padding: 2px 8px;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
@@ -149,9 +149,6 @@ async function refreshKey() {
<el-icon><CopyDocument /></el-icon>
<span class="copy-hex-label">{{ t('key.copyHex') }}</span>
</el-button>
<span class="type-badge" :style="{ color: typeColor, borderColor: typeColor }">
{{ keyStore.selectedType?.toUpperCase() }}
</span>
<el-button size="small" text class="ttl-btn" @click="openTtlDialog">
{{ ttlDisplay }}
</el-button>
@@ -256,15 +253,6 @@ async function refreshKey() {
padding: 2px 4px;
}
.type-badge {
font-size: 10px;
font-weight: 700;
border: 1px solid;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.05em;
}
.ttl-btn {
font-size: 11px;
color: var(--text-muted);