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
commit 62a2684f929f74092cb3b52cd9dbe599328d2ad4 Author: aias00 <[email protected]> AuthorDate: Fri Aug 7 01:37:10 2026 -0700 fix: do not present simulated Ops settings as live state (#1182) --- .../java/org/apache/rocketmq/studio/ops/OpsHomeVO.java | 2 ++ .../org/apache/rocketmq/studio/ops/OpsService.java | 18 ++++++------------ .../org/apache/rocketmq/studio/ops/OpsServiceTest.java | 15 ++++++++------- web/src/api/ops.ts | 2 ++ web/src/pages/studio/Ops.tsx | 17 +++++++++++++++-- web/src/pages/studio/__tests__/Ops.test.tsx | 1 + 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/server/src/main/java/org/apache/rocketmq/studio/ops/OpsHomeVO.java b/server/src/main/java/org/apache/rocketmq/studio/ops/OpsHomeVO.java index 6949ed26..8a989ad8 100644 --- a/server/src/main/java/org/apache/rocketmq/studio/ops/OpsHomeVO.java +++ b/server/src/main/java/org/apache/rocketmq/studio/ops/OpsHomeVO.java @@ -25,6 +25,8 @@ import java.util.List; @Data @Builder public class OpsHomeVO { + private boolean configurationAvailable; + private String unavailableReason; private List<String> namesvrAddrList; private boolean useVIPChannel; private boolean useTLS; diff --git a/server/src/main/java/org/apache/rocketmq/studio/ops/OpsService.java b/server/src/main/java/org/apache/rocketmq/studio/ops/OpsService.java index e21408d3..6b77074f 100644 --- a/server/src/main/java/org/apache/rocketmq/studio/ops/OpsService.java +++ b/server/src/main/java/org/apache/rocketmq/studio/ops/OpsService.java @@ -21,10 +21,7 @@ import org.apache.rocketmq.studio.common.exception.BusinessException; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; @Slf4j @Service @@ -33,17 +30,14 @@ public class OpsService { private static final String OPS_SETTINGS_UNAVAILABLE = "Ops settings are not connected to the cluster admin configuration"; - private final Set<String> namesrvAddrs = new LinkedHashSet<>(List.of("127.0.0.1:9876")); - private String currentNamesrv = "127.0.0.1:9876"; - private boolean useVIPChannel = true; - private boolean useTLS; - public synchronized OpsHomeVO getHomePage() { return OpsHomeVO.builder() - .namesvrAddrList(new ArrayList<>(namesrvAddrs)) - .currentNamesrv(currentNamesrv) - .useVIPChannel(useVIPChannel) - .useTLS(useTLS) + .configurationAvailable(false) + .unavailableReason(OPS_SETTINGS_UNAVAILABLE) + .namesvrAddrList(List.of()) + .currentNamesrv("") + .useVIPChannel(false) + .useTLS(false) .build(); } diff --git a/server/src/test/java/org/apache/rocketmq/studio/ops/OpsServiceTest.java b/server/src/test/java/org/apache/rocketmq/studio/ops/OpsServiceTest.java index 1035a8e7..33536bf3 100644 --- a/server/src/test/java/org/apache/rocketmq/studio/ops/OpsServiceTest.java +++ b/server/src/test/java/org/apache/rocketmq/studio/ops/OpsServiceTest.java @@ -28,12 +28,13 @@ class OpsServiceTest { private final OpsService opsService = new OpsService(); @Test - void getHomePageShouldReturnDefaultSettings() { + void getHomePageShouldReportUnavailableConfiguration() { OpsHomeVO home = opsService.getHomePage(); - assertThat(home.getNamesvrAddrList()).containsExactly("127.0.0.1:9876"); - assertThat(home.getCurrentNamesrv()).isEqualTo("127.0.0.1:9876"); - assertThat(home.isUseVIPChannel()).isTrue(); + assertThat(home.isConfigurationAvailable()).isFalse(); + assertThat(home.getNamesvrAddrList()).isEmpty(); + assertThat(home.getCurrentNamesrv()).isEmpty(); + assertThat(home.isUseVIPChannel()).isFalse(); assertThat(home.isUseTLS()).isFalse(); } @@ -53,8 +54,8 @@ class OpsServiceTest { .satisfies(ex -> assertThat(((BusinessException) ex).getCode()).isEqualTo(501)); OpsHomeVO home = opsService.getHomePage(); - assertThat(home.getNamesvrAddrList()).containsExactly("127.0.0.1:9876"); - assertThat(home.getCurrentNamesrv()).isEqualTo("127.0.0.1:9876"); + assertThat(home.getNamesvrAddrList()).isEmpty(); + assertThat(home.getCurrentNamesrv()).isEmpty(); } @Test @@ -69,7 +70,7 @@ class OpsServiceTest { .satisfies(ex -> assertThat(((BusinessException) ex).getCode()).isEqualTo(501)); OpsHomeVO home = opsService.getHomePage(); - assertThat(home.isUseVIPChannel()).isTrue(); + assertThat(home.isUseVIPChannel()).isFalse(); assertThat(home.isUseTLS()).isFalse(); } diff --git a/web/src/api/ops.ts b/web/src/api/ops.ts index e35ce9a0..039ecbfb 100644 --- a/web/src/api/ops.ts +++ b/web/src/api/ops.ts @@ -113,6 +113,8 @@ export async function cleanupAuditLogs(beforeDays: number) { // ─── NameServer Operations ────────────────────────────────────── export interface OpsHomeData { + configurationAvailable: boolean; + unavailableReason?: string; namesvrAddrList: string[]; useVIPChannel: boolean; useTLS: boolean; diff --git a/web/src/pages/studio/Ops.tsx b/web/src/pages/studio/Ops.tsx index b55ce118..f5320c5d 100644 --- a/web/src/pages/studio/Ops.tsx +++ b/web/src/pages/studio/Ops.tsx @@ -16,7 +16,7 @@ */ import React, { useEffect, useState } from 'react'; -import { App, Button, Input, Popconfirm, Select, Space, Switch, Tooltip, Typography } from 'antd'; +import { Alert, App, Button, Input, Popconfirm, Select, Space, Switch, Tooltip, Typography } from 'antd'; import { FloppyDisk, Plus, Trash } from '@phosphor-icons/react'; import { useLang } from '../../i18n/LangContext'; import useAuthStore from '../../stores/authStore'; @@ -42,7 +42,9 @@ const OpsPage: React.FC = () => { const [newNamesrvAddr, setNewNamesrvAddr] = useState(''); const [useVIPChannel, setUseVIPChannel] = useState(false); const [useTLS, setUseTLS] = useState(false); - const writeOperationEnabled = !token || admin === true; + const [configurationAvailable, setConfigurationAvailable] = useState(false); + const [unavailableReason, setUnavailableReason] = useState(''); + const writeOperationEnabled = configurationAvailable && (!token || admin === true); const deleteNameServerDisabled = !selectedNamesrv || selectedNamesrv === currentNamesrv || namesrvAddrList.length <= 1; @@ -58,6 +60,8 @@ const OpsPage: React.FC = () => { setUseTLS(data.useTLS); setSelectedNamesrv(data.currentNamesrv); setCurrentNamesrv(data.currentNamesrv); + setConfigurationAvailable(data.configurationAvailable); + setUnavailableReason(data.unavailableReason || ''); } } catch { if (!cancelled) { @@ -140,6 +144,15 @@ const OpsPage: React.FC = () => { return ( <div style={{ padding: 24 }}> + {!configurationAvailable && ( + <Alert + type="info" + showIcon + message="运行时配置不可用" + description={unavailableReason || '当前集群不支持读取或更新 Ops 配置。'} + style={{ marginBottom: 24 }} + /> + )} {/* NameServer Address List */} <div style={{ marginBottom: 24 }}> <Typography.Title level={4}>{t('ops.nameServerAddressList')}</Typography.Title> diff --git a/web/src/pages/studio/__tests__/Ops.test.tsx b/web/src/pages/studio/__tests__/Ops.test.tsx index 30388b91..beb12a8b 100644 --- a/web/src/pages/studio/__tests__/Ops.test.tsx +++ b/web/src/pages/studio/__tests__/Ops.test.tsx @@ -66,6 +66,7 @@ describe('OpsPage', () => { useAuthStore.setState({ token: null, user: null, admin: null }); vi.mocked(queryOpsHomePage).mockResolvedValue({ namesvrAddrList: ['127.0.0.1:9876', '127.0.0.2:9876'], + configurationAvailable: true, useVIPChannel: true, useTLS: false, currentNamesrv: '127.0.0.1:9876',
