feat(redis): 优化数据库别名与计数展示

- Redis DB 标题不再重复拼接 key 数量
- 将别名单独渲染为浅色文本并支持设置后即时刷新

Fixes #593
This commit is contained in:
Syngnat
2026-06-27 10:58:24 +08:00
parent 23d7511f55
commit bfb61c8449
7 changed files with 74 additions and 23 deletions

View File

@@ -1034,6 +1034,8 @@ describe('Sidebar locate toolbar', () => {
expect(css).toMatch(/\.gn-v2-tree-title \{[^}]*font-size: var\(--gn-sidebar-tree-font-size, var\(--gn-font-size-sm, 12px\)\);/s);
expect(css).toMatch(/\.gn-v2-tree-title\.is-mono \.gn-v2-tree-label \{[^}]*font-size: inherit;[^}]*font-weight: 400 !important;/s);
expect(css).toMatch(/\.gn-v2-tree-count \{[^}]*font-size: clamp\(10px, calc\(var\(--gn-sidebar-tree-font-size, var\(--gn-font-size-sm, 12px\)\) - 1px\), 16px\);/s);
expect(css).toMatch(/\.gn-v2-tree-title\.is-redis-db \.gn-v2-tree-label \{[^}]*display: inline-flex;[^}]*gap: 6px;/s);
expect(css).toMatch(/\.gn-v2-redis-db-alias \{[^}]*color: var\(--gn-fg-5\);[^}]*opacity: 0\.78;/s);
expect(css).toMatch(/\.gn-v2-connection-rail \{[^}]*width: calc\(38px \* var\(--gn-ui-scale, 1\)\);[^}]*flex: 0 0 calc\(38px \* var\(--gn-ui-scale, 1\)\);/s);
expect(css).toMatch(/\.gn-v2-rail-item,\s*body\[data-ui-version="v2"\] \.gn-v2-rail-tool \{[^}]*width: calc\(36px \* var\(--gn-ui-scale, 1\)\);[^}]*height: calc\(38px \* var\(--gn-ui-scale, 1\)\);[^}]*font-size: var\(--gn-font-size-sm, 12px\);/s);
expect(css).toMatch(/\.gn-v2-rail-tool \{[^}]*height: calc\(32px \* var\(--gn-ui-scale, 1\)\);/s);
@@ -2543,6 +2545,25 @@ describe('Sidebar locate toolbar', () => {
expect(source).toContain("title: buildConnectionRootRedisMonitorTabTitle(`db${redisDB}`)");
});
it('keeps redis db key counts in v2 meta and renders aliases separately from the db title', () => {
const loaderSource = readSourceFile('./sidebar/useSidebarTreeLoaders.tsx');
const redisLoadStart = loaderSource.indexOf("if (conn.config.type === 'redis') {");
const redisLoadEnd = loaderSource.indexOf('const res = await DBGetDatabases', redisLoadStart);
expect(redisLoadStart).toBeGreaterThanOrEqual(0);
expect(redisLoadEnd).toBeGreaterThan(redisLoadStart);
const redisLoadSource = loaderSource.slice(redisLoadStart, redisLoadEnd);
expect(redisLoadSource).toContain('const alias = getRedisDbAlias(redisDbAliases, conn.id, db.index);');
expect(redisLoadSource).toContain('title: buildRedisDbNodeLabel(');
expect(redisLoadSource).toContain('dataRef: { ...conn, redisDB: db.index, redisKeyCount: keyCount, redisDbAlias: alias }');
expect(redisLoadSource).not.toContain("keyCount > 0 ? ` (${keyCount})` : ''");
const titleSource = readSourceFile('./sidebar/SidebarTreeTitle.tsx');
expect(titleSource).toContain("node.type === 'redis-db' ? 'is-redis-db' : ''");
expect(titleSource).toContain("const redisDbAlias = node.type === 'redis-db'");
expect(titleSource).toContain('className="gn-v2-redis-db-alias"');
});
it('localizes sidebar JVM probe and resource failure prompts', () => {
const source = readSidebarSource();

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { StarFilled, StarOutlined } from '@ant-design/icons';
import { t } from '../../i18n';
import { SIDEBAR_SQL_EDITOR_DRAG_MIME, encodeSidebarSqlEditorDragPayload } from '../../utils/sidebarSqlDrag';
import { sanitizeRedisDbAlias } from '../../utils/redisDbAlias';
import { resolveSidebarObjectDragText } from '../sidebarCoreUtils';
import { resolveV2ObjectGroupTitle } from './sidebarHelpers';
@@ -52,6 +53,11 @@ export const renderSidebarV2TreeTitle = ({
return rawTitle;
})();
const metaText = getV2TreeMetaText(node);
const redisDbAlias = node.type === 'redis-db'
? sanitizeRedisDbAlias(node?.dataRef?.redisDbAlias)
: '';
const redisDbIndex = Number(node?.dataRef?.redisDB);
const redisDbBaseTitle = Number.isFinite(redisDbIndex) ? `db${redisDbIndex}` : displayTitle;
const isMono = node.type === 'table'
|| node.type === 'view'
|| node.type === 'materialized-view'
@@ -66,6 +72,7 @@ export const renderSidebarV2TreeTitle = ({
'gn-v2-tree-title',
isMono ? 'is-mono' : '',
node.type === 'object-group' ? 'is-group' : '',
node.type === 'redis-db' ? 'is-redis-db' : '',
node.type === 'table' && node?.dataRef?.pinnedSidebarTable ? 'is-pinned-table' : '',
].filter(Boolean).join(' ');
const tablePinAction = node.type === 'table' ? (
@@ -145,7 +152,14 @@ export const renderSidebarV2TreeTitle = ({
} : undefined}
>
{statusBadge}
<span className="gn-v2-tree-label">{displayTitle}</span>
<span className="gn-v2-tree-label">
{redisDbAlias ? (
<>
<span className="gn-v2-redis-db-name">{redisDbBaseTitle}</span>
<span className="gn-v2-redis-db-alias">{redisDbAlias}</span>
</>
) : displayTitle}
</span>
{metaText && <span className="gn-v2-tree-count">{metaText}</span>}
</span>
{tablePinAction}

View File

@@ -38,17 +38,25 @@ import {
} from '../../utils/redisDbAlias';
import { supportsTableTruncateAction } from '../tableDataDangerActions';
const updateTreeNodeTitle = (
const updateRedisDbNodeAlias = (
nodes: any[],
targetKey: string,
title: string,
alias: string,
): any[] =>
nodes.map((node) => {
if (node.key === targetKey) {
return { ...node, title };
return {
...node,
title,
dataRef: {
...(node.dataRef || {}),
redisDbAlias: alias,
},
};
}
if (Array.isArray(node.children)) {
return { ...node, children: updateTreeNodeTitle(node.children, targetKey, title) };
return { ...node, children: updateRedisDbNodeAlias(node.children, targetKey, title, alias) };
}
return node;
});
@@ -57,7 +65,7 @@ const openRedisDbAliasModal = (
node: any,
context: SidebarLegacyNodeMenuContext,
): void => {
const { id, redisDB, redisKeyCount } = node.dataRef;
const { id, redisDB } = node.dataRef;
const { treeDataRef, setTreeData } = context;
const currentAlias = getRedisDbAlias(
useStore.getState().appearance.redisDbAliases,
@@ -91,10 +99,8 @@ const openRedisDbAliasModal = (
id,
redisDB,
);
const keyCount = Number(redisKeyCount);
const suffix = Number.isFinite(keyCount) && keyCount > 0 ? ` (${keyCount})` : '';
const nextTitle = buildRedisDbNodeLabel(redisDB, nextAlias, suffix);
const nextTree = updateTreeNodeTitle(treeDataRef.current, node.key, nextTitle);
const nextTitle = buildRedisDbNodeLabel(redisDB, nextAlias);
const nextTree = updateRedisDbNodeAlias(treeDataRef.current, node.key, nextTitle, nextAlias);
treeDataRef.current = nextTree;
setTreeData(nextTree);
}

View File

@@ -314,16 +314,16 @@ export const useSidebarTreeLoaders = ({
const redisDbAliases = useStore.getState().appearance.redisDbAliases;
let dbs = redisRows.map((db: any) => {
const keyCount = Number(db.keys) > 0 ? Number(db.keys) : 0;
const alias = getRedisDbAlias(redisDbAliases, conn.id, db.index);
return {
title: buildRedisDbNodeLabel(
db.index,
getRedisDbAlias(redisDbAliases, conn.id, db.index),
keyCount > 0 ? ` (${keyCount})` : '',
alias,
),
key: `${conn.id}-db${db.index}`,
icon: <DatabaseOutlined style={{ color: '#DC382D' }} />,
type: 'redis-db' as const,
dataRef: { ...conn, redisDB: db.index, redisKeyCount: keyCount },
dataRef: { ...conn, redisDB: db.index, redisKeyCount: keyCount, redisDbAlias: alias },
isLeaf: true,
dbIndex: db.index,
};