This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 2002d3d6 fix: normalize service search filters (#635)
2002d3d6 is described below

commit 2002d3d6683f8f5fc567193cdae465cab07bf805
Author: aias00 <[email protected]>
AuthorDate: Tue Jul 28 07:10:24 2026 -0700

    fix: normalize service search filters (#635)
    
    * [Studio] Normalize service search filters
    
    * fix: make group search case insensitive
---
 .../studio/cluster/client/ClientService.java       |  6 +-
 .../cluster/client/ProducerConnectionService.java  |  8 ++-
 .../rocketmq/studio/instance/InstanceService.java  |  9 +--
 .../instance/group/ConsumerDiagnosticsService.java | 15 ++--
 .../studio/instance/topic/MetadataService.java     | 11 ++-
 .../studio/ops/audit/InMemoryAuditRepository.java  | 20 ++++--
 .../studio/cluster/client/ClientServiceTest.java   | 63 ++++++++++++++++
 .../client/ProducerConnectionServiceTest.java      | 19 +++++
 .../studio/instance/InstanceServiceTest.java       | 26 +++++++
 .../group/ConsumerDiagnosticsServiceTest.java      | 18 +++++
 .../studio/instance/topic/MetadataServiceTest.java | 34 +++++++++
 .../ops/audit/InMemoryAuditRepositoryTest.java     | 83 ++++++++++++++++++++++
 web/src/pages/studio/GroupManagement.tsx           |  7 +-
 .../studio/__tests__/GroupManagement.test.tsx      |  2 +-
 14 files changed, 301 insertions(+), 20 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
index 60469a0d..7f39325a 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ClientService.java
@@ -31,6 +31,10 @@ public class ClientService {
 
     public List<ClientConnectionVO> listConnections(String clusterId, String 
type) {
         log.info("Listing client connections, clusterId={}, type={}", 
clusterId, type);
-        return clientProvider.findConnections(clusterId, type);
+        return clientProvider.findConnections(normalizeFilter(clusterId), 
normalizeFilter(type));
+    }
+
+    private String normalizeFilter(String value) {
+        return value == null || value.isBlank() ? null : value.trim();
     }
 }
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
index 9709db00..bce19e91 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionService.java
@@ -32,8 +32,10 @@ public class ProducerConnectionService {
 
     public List<ProducerConnectionVO> listConnections(String topic, String 
producerGroup) {
         log.info("Listing producer connections, topic={}, producerGroup={}", 
topic, producerGroup);
+        String normalizedTopic = normalizeFilter(topic);
+        String normalizedProducerGroup = normalizeFilter(producerGroup);
         return clientService.listConnections(null, 
ClientType.Producer.name()).stream()
-                .filter(connection -> matchesFilter(connection, topic, 
producerGroup))
+                .filter(connection -> matchesFilter(connection, 
normalizedTopic, normalizedProducerGroup))
                 .map(this::toProducerConnection)
                 .toList();
     }
@@ -60,4 +62,8 @@ public class ProducerConnectionService {
     private boolean hasText(String value) {
         return value != null && !value.trim().isEmpty();
     }
+
+    private String normalizeFilter(String value) {
+        return hasText(value) ? value.trim() : null;
+    }
 }
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java 
b/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
index f9abb650..eb4c5aec 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/instance/InstanceService.java
@@ -36,13 +36,14 @@ public class InstanceService {
 
     public List<InstanceVO> listInstances(InstanceType type, String search) {
         log.debug("Listing instances, type={}, search={}", type, search);
+        String normalizedSearch = search == null || search.isBlank() ? null : 
search.trim();
 
-        if (type != null && search != null && !search.isBlank()) {
-            return instanceRepository.findByTypeAndSearch(type, search);
+        if (type != null && normalizedSearch != null) {
+            return instanceRepository.findByTypeAndSearch(type, 
normalizedSearch);
         } else if (type != null) {
             return instanceRepository.findByType(type);
-        } else if (search != null && !search.isBlank()) {
-            return instanceRepository.search(search);
+        } else if (normalizedSearch != null) {
+            return instanceRepository.search(normalizedSearch);
         }
         return instanceRepository.findAll();
     }
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
index 4c4def1f..87e8f1db 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsService.java
@@ -30,12 +30,15 @@ public class ConsumerDiagnosticsService {
     private final ConsumerDiagnosticsProvider diagnosticsProvider;
 
     public ConsumerStackTraceVO getConsumerStack(String groupName, String 
clientId) {
-        if (!StringUtils.hasText(groupName)) {
-            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), 
"groupName is required");
-        }
-        if (!StringUtils.hasText(clientId)) {
-            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), 
"clientId is required");
+        String normalizedGroupName = normalizeRequired(groupName, "groupName");
+        String normalizedClientId = normalizeRequired(clientId, "clientId");
+        return diagnosticsProvider.getConsumerStack(normalizedGroupName, 
normalizedClientId);
+    }
+
+    private String normalizeRequired(String value, String fieldName) {
+        if (!StringUtils.hasText(value)) {
+            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), 
fieldName + " is required");
         }
-        return diagnosticsProvider.getConsumerStack(groupName, clientId);
+        return value.trim();
     }
 }
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
index 33f53642..f2c4e541 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/instance/topic/MetadataService.java
@@ -38,7 +38,10 @@ public class MetadataService {
 
 
     public List<TopicVO> listTopics(String clusterId, String type, String 
search) {
-        return metadataProvider.listTopics(clusterId, type, search);
+        return metadataProvider.listTopics(
+                normalizeFilter(clusterId),
+                normalizeFilter(type),
+                normalizeFilter(search));
     }
 
 
@@ -75,7 +78,7 @@ public class MetadataService {
 
 
     public List<ConsumerGroupVO> listConsumerGroups(String clusterId, String 
search) {
-        return metadataProvider.listConsumerGroups(clusterId, search);
+        return metadataProvider.listConsumerGroups(normalizeFilter(clusterId), 
normalizeFilter(search));
     }
 
 
@@ -114,4 +117,8 @@ public class MetadataService {
     public List<NamespaceVO> listNamespaces() {
         throw new UnsupportedOperationException("Not implemented");
     }
+
+    private String normalizeFilter(String value) {
+        return value == null || value.isBlank() ? null : value.trim();
+    }
 }
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
index 37b430c9..02740375 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepository.java
@@ -35,11 +35,12 @@ public class InMemoryAuditRepository implements 
AuditRepository {
     public List<AuditRecordVO> findAll(String search, String operationType,
                                      LocalDateTime startDate, LocalDateTime 
endDate,
                                      String result) {
+        String normalizedSearch = normalize(search);
         return records.values().stream()
-                .filter(r -> search == null || search.isEmpty()
-                        || 
r.getDetail().toLowerCase().contains(search.toLowerCase())
-                        || 
r.getOperator().toLowerCase().contains(search.toLowerCase())
-                        || 
r.getTarget().toLowerCase().contains(search.toLowerCase()))
+                .filter(r -> normalizedSearch == null
+                        || containsIgnoreCase(r.getDetail(), normalizedSearch)
+                        || containsIgnoreCase(r.getOperator(), 
normalizedSearch)
+                        || containsIgnoreCase(r.getTarget(), normalizedSearch))
                 .filter(r -> operationType == null || operationType.isEmpty()
                         || operationType.equals(r.getOperationType()))
                 .filter(r -> startDate == null || r.getTimestamp() != null && 
!r.getTimestamp().isBefore(startDate))
@@ -54,6 +55,17 @@ public class InMemoryAuditRepository implements 
AuditRepository {
                 .collect(Collectors.toList());
     }
 
+    private String normalize(String value) {
+        if (value == null || value.isBlank()) {
+            return null;
+        }
+        return value.toLowerCase();
+    }
+
+    private boolean containsIgnoreCase(String value, String normalizedSearch) {
+        return value != null && value.toLowerCase().contains(normalizedSearch);
+    }
+
     @Override
     public int deleteBefore(LocalDateTime cutoff) {
         List<String> toRemove = records.values().stream()
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ClientServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ClientServiceTest.java
new file mode 100644
index 00000000..6825cbf1
--- /dev/null
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ClientServiceTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.cluster.client;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class ClientServiceTest {
+
+    @Mock
+    private ClientProvider clientProvider;
+
+    @InjectMocks
+    private ClientService clientService;
+
+    @Test
+    void listConnectionsShouldTrimFiltersBeforeQueryingProvider() {
+        ClientConnectionVO connection = ClientConnectionVO.builder()
+                .clientId("client-1")
+                .clusterName("production-cluster")
+                .build();
+        when(clientProvider.findConnections("production-cluster", 
"Producer")).thenReturn(List.of(connection));
+
+        List<ClientConnectionVO> result = clientService.listConnections(" 
production-cluster ", " Producer ");
+
+        assertThat(result).containsExactly(connection);
+        verify(clientProvider).findConnections("production-cluster", 
"Producer");
+    }
+
+    @Test
+    void listConnectionsShouldTreatBlankFiltersAsUnspecified() {
+        when(clientProvider.findConnections(null, null)).thenReturn(List.of());
+
+        List<ClientConnectionVO> result = clientService.listConnections(" ", 
"\t");
+
+        assertThat(result).isEmpty();
+        verify(clientProvider).findConnections(null, null);
+    }
+}
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
index 5bce6134..489f43cc 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/client/ProducerConnectionServiceTest.java
@@ -91,6 +91,25 @@ class ProducerConnectionServiceTest {
         assertThat(result.get(0).getClientId()).isEqualTo("producer-1");
     }
 
+    @Test
+    void listConnectionsShouldTrimFilterValues() {
+        ClientConnectionVO producer = ClientConnectionVO.builder()
+                .clientId("producer-1")
+                .type(ClientType.Producer)
+                .groupOrTopic("order-topic")
+                .producerGroup("pg-order")
+                .address("10.0.0.1:38888")
+                .language(ClientLanguage.Java)
+                .version("5.1.0")
+                .build();
+        when(clientService.listConnections(null, 
ClientType.Producer.name())).thenReturn(List.of(producer));
+
+        List<ProducerConnectionVO> result = 
producerConnectionService.listConnections(" order-topic ", " pg-order ");
+
+        assertThat(result).hasSize(1);
+        assertThat(result.get(0).getClientId()).isEqualTo("producer-1");
+    }
+
     @Test
     void listConnectionsShouldRequireProducerGroupWhenBothFiltersAreProvided() 
{
         ClientConnectionVO producer = ClientConnectionVO.builder()
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
index 9fab45f6..c59644fd 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/instance/InstanceServiceTest.java
@@ -83,6 +83,19 @@ class InstanceServiceTest {
         verify(instanceRepository).search("prod");
     }
 
+    @Test
+    void listInstancesShouldTrimSearchKeyword() {
+        List<InstanceVO> instances = List.of(
+                InstanceVO.builder().name("production").build()
+        );
+        when(instanceRepository.search("prod")).thenReturn(instances);
+
+        List<InstanceVO> result = instanceService.listInstances(null, " prod 
");
+
+        assertThat(result).hasSize(1);
+        verify(instanceRepository).search("prod");
+    }
+
     @Test
     void listInstancesShouldFilterByTypeAndSearch() {
         List<InstanceVO> instances = List.of(
@@ -96,6 +109,19 @@ class InstanceServiceTest {
         verify(instanceRepository).findByTypeAndSearch(InstanceType.PROXY, 
"prod");
     }
 
+    @Test
+    void listInstancesShouldTrimSearchKeywordWhenFilteringByType() {
+        List<InstanceVO> instances = List.of(
+                
InstanceVO.builder().name("production-proxy").type(InstanceType.PROXY).build()
+        );
+        when(instanceRepository.findByTypeAndSearch(InstanceType.PROXY, 
"prod")).thenReturn(instances);
+
+        List<InstanceVO> result = 
instanceService.listInstances(InstanceType.PROXY, " prod ");
+
+        assertThat(result).hasSize(1);
+        verify(instanceRepository).findByTypeAndSearch(InstanceType.PROXY, 
"prod");
+    }
+
     @Test
     void listInstancesShouldIgnoreBlankSearch() {
         List<InstanceVO> instances = 
List.of(InstanceVO.builder().name("inst").build());
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
index 034c1acd..6867871b 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/instance/group/ConsumerDiagnosticsServiceTest.java
@@ -60,6 +60,24 @@ class ConsumerDiagnosticsServiceTest {
         verify(diagnosticsProvider).getConsumerStack("cg-orders", "client-1");
     }
 
+    @Test
+    void getConsumerStackShouldTrimInputsBeforeDelegatingToProvider() {
+        ConsumerStackTraceVO stackTrace = ConsumerStackTraceVO.builder()
+                .groupName("cg-orders")
+                .clientId("client-1")
+                .capturedAt(LocalDateTime.now())
+                .threadCount(0)
+                .threads(List.of())
+                .build();
+        when(diagnosticsProvider.getConsumerStack("cg-orders", 
"client-1")).thenReturn(stackTrace);
+
+        ConsumerStackTraceVO result = diagnosticsService.getConsumerStack(" 
cg-orders ", " client-1 ");
+
+        assertThat(result.getGroupName()).isEqualTo("cg-orders");
+        assertThat(result.getClientId()).isEqualTo("client-1");
+        verify(diagnosticsProvider).getConsumerStack("cg-orders", "client-1");
+    }
+
     @Test
     void getConsumerStackShouldRejectBlankGroupName() {
         assertThatThrownBy(() -> diagnosticsService.getConsumerStack(" ", 
"client-1"))
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
index 21d30799..554335b7 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/instance/topic/MetadataServiceTest.java
@@ -68,6 +68,28 @@ class MetadataServiceTest {
         assertThat(result).isEmpty();
     }
 
+    @Test
+    void listTopicsShouldNormalizeFiltersBeforeQueryingProvider() {
+        TopicVO topic = new TopicVO();
+        topic.setName("order-topic");
+        when(metadataProvider.listTopics("cluster-1", "FIFO", 
"order")).thenReturn(List.of(topic));
+
+        List<TopicVO> result = metadataService.listTopics(" cluster-1 ", " 
FIFO ", " order ");
+
+        assertThat(result).containsExactly(topic);
+        verify(metadataProvider).listTopics("cluster-1", "FIFO", "order");
+    }
+
+    @Test
+    void listTopicsShouldTreatBlankFiltersAsUnspecified() {
+        when(metadataProvider.listTopics(null, null, 
null)).thenReturn(List.of());
+
+        List<TopicVO> result = metadataService.listTopics(" ", "\t", "");
+
+        assertThat(result).isEmpty();
+        verify(metadataProvider).listTopics(null, null, null);
+    }
+
     @Test
     void createTopicShouldDelegateToAdminClient() {
         TopicVO input = new TopicVO();
@@ -141,4 +163,16 @@ class MetadataServiceTest {
         assertThat(result).isEmpty();
         verify(metadataProvider).listConsumerGroups(null, "order");
     }
+
+    @Test
+    void listConsumerGroupsShouldNormalizeFiltersBeforeQueryingProvider() {
+        ConsumerGroupVO group = new ConsumerGroupVO();
+        group.setName("cg-order");
+        when(metadataProvider.listConsumerGroups("cluster-1", 
"order")).thenReturn(List.of(group));
+
+        List<ConsumerGroupVO> result = metadataService.listConsumerGroups(" 
cluster-1 ", " order ");
+
+        assertThat(result).containsExactly(group);
+        verify(metadataProvider).listConsumerGroups("cluster-1", "order");
+    }
 }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepositoryTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepositoryTest.java
new file mode 100644
index 00000000..25516302
--- /dev/null
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/audit/InMemoryAuditRepositoryTest.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.audit;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.time.LocalDateTime;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class InMemoryAuditRepositoryTest {
+
+    private final InMemoryAuditRepository repository = new 
InMemoryAuditRepository();
+
+    @Test
+    void findAllShouldSearchAcrossNullableFields() {
+        AuditRecordVO missingTextFields = AuditRecordVO.builder()
+                .timestamp(LocalDateTime.now())
+                .operationType("CREATE")
+                .result("SUCCESS")
+                .build();
+        missingTextFields.setId("record-null-fields");
+        AuditRecordVO targetMatch = AuditRecordVO.builder()
+                .timestamp(LocalDateTime.now().minusMinutes(1))
+                .operator("admin")
+                .operationType("UPDATE")
+                .target("Topic-Order")
+                .detail(null)
+                .result("SUCCESS")
+                .build();
+        targetMatch.setId("record-target-match");
+
+        putRecords(missingTextFields, targetMatch);
+
+        assertThat(repository.findAll("order", null, null, null, null))
+                .extracting(AuditRecordVO::getId)
+                .containsExactly("record-target-match");
+    }
+
+    @Test
+    void findAllShouldTreatBlankSearchAsNoSearchFilter() {
+        AuditRecordVO record = AuditRecordVO.builder()
+                .timestamp(LocalDateTime.now())
+                .operationType("DELETE")
+                .result("FAILURE")
+                .build();
+        record.setId("record-blank-search");
+
+        putRecords(record);
+
+        assertThat(repository.findAll("   ", null, null, null, null))
+                .extracting(AuditRecordVO::getId)
+                .containsExactly("record-blank-search");
+    }
+
+    @SafeVarargs
+    @SuppressWarnings("unchecked")
+    private final void putRecords(AuditRecordVO... records) {
+        Map<String, AuditRecordVO> store =
+                (Map<String, AuditRecordVO>) 
ReflectionTestUtils.getField(repository, "records");
+        assertThat(store).isNotNull();
+        store.clear();
+        for (AuditRecordVO record : records) {
+            store.put(record.getId(), record);
+        }
+    }
+}
diff --git a/web/src/pages/studio/GroupManagement.tsx 
b/web/src/pages/studio/GroupManagement.tsx
index 4c4976af..47102e16 100644
--- a/web/src/pages/studio/GroupManagement.tsx
+++ b/web/src/pages/studio/GroupManagement.tsx
@@ -227,6 +227,11 @@ const GroupManagementPage = () => {
     setModalVisible(true);
   };
 
+  const normalizedSearchText = searchText.trim().toLowerCase();
+  const filteredGroupData = groupData.filter(
+    (record) => !normalizedSearchText || 
record.group.toLowerCase().includes(normalizedSearchText),
+  );
+
   const columns = [
     {
       title: t('groupMgmt.groupName'),
@@ -390,7 +395,7 @@ const GroupManagementPage = () => {
       <Card bordered={false} style={{ borderRadius: 8, boxShadow: '0 1px 6px 
rgba(0,0,0,0.04)' }}>
         <Table
           columns={columns}
-          dataSource={groupData.filter((d) => !searchText || 
d.group.includes(searchText))}
+          dataSource={filteredGroupData}
           pagination={{
             pageSize: 10,
             showTotal: (total) => `${t('common.total')} ${total} Group`,
diff --git a/web/src/pages/studio/__tests__/GroupManagement.test.tsx 
b/web/src/pages/studio/__tests__/GroupManagement.test.tsx
index 3ac9fbbe..3b93a966 100644
--- a/web/src/pages/studio/__tests__/GroupManagement.test.tsx
+++ b/web/src/pages/studio/__tests__/GroupManagement.test.tsx
@@ -90,7 +90,7 @@ describe('GroupManagement Page', () => {
     const user = userEvent.setup();
     renderWithProviders(<GroupManagement />);
     const searchInput = screen.getByPlaceholderText('搜索消费组');
-    await user.type(searchInput, 'order');
+    await user.type(searchInput, 'ORDER');
     expect(screen.getByText('order-consumer-group')).toBeInTheDocument();
     
expect(screen.queryByText('payment-consumer-group')).not.toBeInTheDocument();
   });

Reply via email to