fix: key 类型为 none 时显示过期提示并自动移除失效 key
- KeyDetail: 新增 'none' 类型专用视图,显示过期提示 + 刷新按钮 - key store: TYPE 返回 none 时自动从列表移除失效 key 并重建 tree - 新增 i18n keyExpired 多语言 (zh-CN/en/ja/ko/de)
This commit is contained in:
@@ -164,7 +164,12 @@ async function refreshKey() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="detail-content">
|
<div class="detail-content">
|
||||||
<StringEditor v-if="keyStore.selectedType === 'string'" />
|
<div v-if="keyStore.selectedType === 'none'" class="key-expired">
|
||||||
|
<el-icon size="48" color="var(--text-muted)"><Warning /></el-icon>
|
||||||
|
<p>{{ t('key.keyExpired') }}</p>
|
||||||
|
<el-button type="primary" @click="refreshKey">{{ t('common.refresh') }}</el-button>
|
||||||
|
</div>
|
||||||
|
<StringEditor v-else-if="keyStore.selectedType === 'string'" />
|
||||||
<HashEditor v-else-if="keyStore.selectedType === 'hash'" />
|
<HashEditor v-else-if="keyStore.selectedType === 'hash'" />
|
||||||
<ListEditor v-else-if="keyStore.selectedType === 'list'" />
|
<ListEditor v-else-if="keyStore.selectedType === 'list'" />
|
||||||
<SetEditor v-else-if="keyStore.selectedType === 'set'" />
|
<SetEditor v-else-if="keyStore.selectedType === 'set'" />
|
||||||
@@ -303,4 +308,18 @@ async function refreshKey() {
|
|||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.key-expired {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.key-expired p {
|
||||||
|
margin: 12px 0 16px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export default {
|
|||||||
andMore: '...und {n} weitere',
|
andMore: '...und {n} weitere',
|
||||||
selected: '{n} ausgewählt',
|
selected: '{n} ausgewählt',
|
||||||
selectKey: 'Wählen Sie einen Schlüssel für Details',
|
selectKey: 'Wählen Sie einen Schlüssel für Details',
|
||||||
|
keyExpired: 'Dieser Schlüssel existiert nicht mehr (möglicherweise abgelaufen oder gelöscht)',
|
||||||
unsupported: 'Typ "{type}"-Anzeige noch nicht implementiert',
|
unsupported: 'Typ "{type}"-Anzeige noch nicht implementiert',
|
||||||
patternPlaceholder: 'Schlüssel scannen (z.B. user:*, * ? unterstützt)',
|
patternPlaceholder: 'Schlüssel scannen (z.B. user:*, * ? unterstützt)',
|
||||||
scanHint: 'Schlüssel auf dem Redis-Server scannen. * passt zu beliebigen Zeichen, ? zu einem einzelnen Zeichen. Enter zum Scannen.',
|
scanHint: 'Schlüssel auf dem Redis-Server scannen. * passt zu beliebigen Zeichen, ? zu einem einzelnen Zeichen. Enter zum Scannen.',
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export default {
|
|||||||
andMore: '...and {n} more',
|
andMore: '...and {n} more',
|
||||||
selected: '{n} selected',
|
selected: '{n} selected',
|
||||||
selectKey: 'Select a key to view details',
|
selectKey: 'Select a key to view details',
|
||||||
|
keyExpired: 'This key no longer exists (may have expired or been deleted)',
|
||||||
unsupported: 'Type "{type}" viewer not yet implemented',
|
unsupported: 'Type "{type}" viewer not yet implemented',
|
||||||
patternPlaceholder: 'Scan keys (e.g. user:*, supports * ?)',
|
patternPlaceholder: 'Scan keys (e.g. user:*, supports * ?)',
|
||||||
scanHint: 'Scan keys on Redis server. * matches any characters, ? matches a single character. Press Enter to scan.',
|
scanHint: 'Scan keys on Redis server. * matches any characters, ? matches a single character. Press Enter to scan.',
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export default {
|
|||||||
andMore: '...他 {n} 個',
|
andMore: '...他 {n} 個',
|
||||||
selected: '{n} 個選択済み',
|
selected: '{n} 個選択済み',
|
||||||
selectKey: 'キーを選択して詳細を表示',
|
selectKey: 'キーを選択して詳細を表示',
|
||||||
|
keyExpired: 'このキーは存在しません(期限切れまたは削除された可能性があります)',
|
||||||
unsupported: 'タイプ "{type}" のビューアーは未実装です',
|
unsupported: 'タイプ "{type}" のビューアーは未実装です',
|
||||||
patternPlaceholder: 'キーをスキャン (例: user:*, * ? 対応)',
|
patternPlaceholder: 'キーをスキャン (例: user:*, * ? 対応)',
|
||||||
scanHint: 'Redisサーバーでキーをスキャン。* は任意の文字列、? は1文字に一致。Enterでスキャン。',
|
scanHint: 'Redisサーバーでキーをスキャン。* は任意の文字列、? は1文字に一致。Enterでスキャン。',
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export default {
|
|||||||
andMore: '...그 외 {n}개',
|
andMore: '...그 외 {n}개',
|
||||||
selected: '{n}개 선택됨',
|
selected: '{n}개 선택됨',
|
||||||
selectKey: '키를 선택하여 세부 정보 보기',
|
selectKey: '키를 선택하여 세부 정보 보기',
|
||||||
|
keyExpired: '이 키는 더 이상 존재하지 않습니다(만료되었거나 삭제되었을 수 있음)',
|
||||||
unsupported: '"{type}" 유형 뷰어가 아직 구현되지 않았습니다',
|
unsupported: '"{type}" 유형 뷰어가 아직 구현되지 않았습니다',
|
||||||
patternPlaceholder: '키 스캔 (예: user:*, * ? 지원)',
|
patternPlaceholder: '키 스캔 (예: user:*, * ? 지원)',
|
||||||
scanHint: 'Redis 서버에서 키를 스캔합니다. * 는 임의의 문자, ? 는 단일 문자와 일치. Enter로 스캔.',
|
scanHint: 'Redis 서버에서 키를 스캔합니다. * 는 임의의 문자, ? 는 단일 문자와 일치. Enter로 스캔.',
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export default {
|
|||||||
andMore: '...以及其他 {n} 个',
|
andMore: '...以及其他 {n} 个',
|
||||||
selected: '已选 {n} 项',
|
selected: '已选 {n} 项',
|
||||||
selectKey: '选择一个键查看详情',
|
selectKey: '选择一个键查看详情',
|
||||||
|
keyExpired: '该键已不存在(可能已过期或被删除)',
|
||||||
unsupported: '类型 "{type}" 查看器尚未实现',
|
unsupported: '类型 "{type}" 查看器尚未实现',
|
||||||
patternPlaceholder: '扫描 Key (如 user:*, 支持 * ?)',
|
patternPlaceholder: '扫描 Key (如 user:*, 支持 * ?)',
|
||||||
scanHint: '在 Redis 服务端按模式扫描 Key。* 匹配任意字符, ? 匹配单个字符。回车扫描。',
|
scanHint: '在 Redis 服务端按模式扫描 Key。* 匹配任意字符, ? 匹配单个字符。回车扫描。',
|
||||||
|
|||||||
@@ -138,6 +138,21 @@ export const useKeyStore = defineStore('key', () => {
|
|||||||
await loadKeyTypeAndTTL(connId, key)
|
await loadKeyTypeAndTTL(connId, key)
|
||||||
selectedKey.value = key
|
selectedKey.value = key
|
||||||
|
|
||||||
|
// Key no longer exists — show expired state and refresh list
|
||||||
|
if (selectedType.value === 'none') {
|
||||||
|
keyData.value = null
|
||||||
|
// Remove the stale key from the list
|
||||||
|
keys.value = keys.value.filter(k => k.name !== key)
|
||||||
|
// Rebuild tree if needed
|
||||||
|
if (useTree.value) {
|
||||||
|
const conn = (await window.electronAPI.storage.getConnections())
|
||||||
|
.find((c: any) => c.id === connId)
|
||||||
|
const sep = conn?.separator || ':'
|
||||||
|
treeKeys.value = buildTree(keys.value.map(k => k.name), sep)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (selectedType.value) {
|
switch (selectedType.value) {
|
||||||
case 'string':
|
case 'string':
|
||||||
|
|||||||
Reference in New Issue
Block a user