From 427d22d9e700e4e9c17ec3835e1d934e9a6ea5ad Mon Sep 17 00:00:00 2001 From: AutumnNazi <104422820+AutumnNazi@users.noreply.github.com> Date: Fri, 24 Jul 2026 11:19:17 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20style(redis):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20Key=20=E8=AF=A6=E6=83=85=E6=93=8D=E4=BD=9C=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 Key 名称、类型与 TTL/长度、操作按钮拆分为独立行 - 移除操作按钮组外层灰色容器并保留窄宽度换行 - 增加 Key 详情布局交互回归测试 --- .../RedisViewer.interaction.test.tsx | 38 +++++++++++++++++++ frontend/src/components/RedisViewer.tsx | 28 +++++++------- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/RedisViewer.interaction.test.tsx b/frontend/src/components/RedisViewer.interaction.test.tsx index e8050ec9..005c2d4e 100644 --- a/frontend/src/components/RedisViewer.interaction.test.tsx +++ b/frontend/src/components/RedisViewer.interaction.test.tsx @@ -321,6 +321,44 @@ describe('RedisViewer tree interactions', () => { renderer!.unmount(); }); + it('renders key detail actions on a separate row below the metadata', async () => { + let renderer: ReactTestRenderer; + await act(async () => { + renderer = create(); + }); + await flushEffects(); + + const leafNode = findFirstLeafNode(antdState.treeProps.treeData); + await act(async () => { + antdState.treeProps.onSelect?.([leafNode.key]); + }); + await flushEffects(); + + const header = renderer!.root.findByProps({ className: 'redis-key-detail-header' }); + const summary = renderer!.root.findByProps({ className: 'redis-key-detail-summary' }); + const identity = renderer!.root.findByProps({ className: 'redis-key-detail-identity' }); + const metadata = renderer!.root.findByProps({ className: 'redis-key-detail-metadata' }); + const actions = renderer!.root.findByProps({ className: 'redis-key-detail-actions' }); + + expect(header.props.style).toMatchObject({ flexDirection: 'column' }); + expect(summary.props.style).toMatchObject({ minWidth: 0, width: '100%' }); + expect(identity.parent).toBe(summary); + expect(metadata.parent).toBe(summary); + expect(actions.parent).toBe(summary); + expect(summary.children.indexOf(identity)).toBeLessThan(summary.children.indexOf(metadata)); + expect(summary.children.indexOf(metadata)).toBeLessThan(summary.children.indexOf(actions)); + expect(actions.props.style).toMatchObject({ + alignSelf: 'flex-start', + flexWrap: 'wrap', + maxWidth: '100%', + }); + expect(findButtonByText(renderer!, 'Set TTL')).toBeTruthy(); + expect(findButtonByText(renderer!, 'Refresh')).toBeTruthy(); + expect(findButtonByText(renderer!, 'Delete Key')).toBeTruthy(); + + renderer!.unmount(); + }); + it('loads every key page when the load-all action is clicked', async () => { redisBackend.RedisScanKeys.mockReset(); redisBackend.RedisScanKeys diff --git a/frontend/src/components/RedisViewer.tsx b/frontend/src/components/RedisViewer.tsx index 8649414f..44acc043 100644 --- a/frontend/src/components/RedisViewer.tsx +++ b/frontend/src/components/RedisViewer.tsx @@ -2017,12 +2017,12 @@ const RedisViewer: React.FC = ({ connectionId, redisDB }) => { return (
-
-
+
+
{tr('redis_viewer.title.active_key')} -
+
{selectedKey} @@ -2043,20 +2043,22 @@ const RedisViewer: React.FC = ({ connectionId, redisDB }) => { }} /> +
+
{keyValue.type} } style={mutedPillTagStyle}>{formatTTL(keyValue.ttl)} {keyValue.length > 0 && {tr('redis_viewer.label.length', { count: keyValue.length })}}
-
-
- - - - - +
+ + + + + +