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 0e5d2ca5a fix(web): guard topic consumer pagination race and stale 
metrics datasource, wire dead buttons (#1992)
0e5d2ca5a is described below

commit 0e5d2ca5a3e083214443636ac2c02137050324e8
Author: btlqql <[email protected]>
AuthorDate: Tue Aug 18 17:04:59 2026 +0800

    fix(web): guard topic consumer pagination race and stale metrics 
datasource, wire dead buttons (#1992)
    
    Co-authored-by: yyqdbngt <[email protected]>
---
 web/src/components/MetricsExplorer.tsx |  3 +++
 web/src/pages/ai/index.tsx             | 13 +++++++++++--
 web/src/pages/instance/consumer.tsx    |  2 ++
 web/src/pages/instance/topic.tsx       |  7 ++++++-
 4 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/web/src/components/MetricsExplorer.tsx 
b/web/src/components/MetricsExplorer.tsx
index 627dac61e..b9207c2cf 100644
--- a/web/src/components/MetricsExplorer.tsx
+++ b/web/src/components/MetricsExplorer.tsx
@@ -490,6 +490,9 @@ const MetricsExplorer = ({ instanceId }: 
MetricsExplorerProps) => {
   useEffect(() => {
     if (dataSourceKey && !availableDataSources.some((source) => source.key === 
dataSourceKey)) {
       window.setTimeout(() => {
+        // Keep the ref in sync with the state; queries read the ref, so a 
stale key would
+        // keep hitting the de-registered data source while the UI shows the 
default.
+        dataSourceKeyRef.current = '';
         setDataSourceKey('');
         setData(null);
       }, 0);
diff --git a/web/src/pages/ai/index.tsx b/web/src/pages/ai/index.tsx
index 6b0041c0f..8f02ccbd3 100644
--- a/web/src/pages/ai/index.tsx
+++ b/web/src/pages/ai/index.tsx
@@ -390,6 +390,7 @@ const AiPage = () => {
   const [modelsLoading, setModelsLoading] = useState(false);
   const [selectedModel, setSelectedModel] = useState('');
   const [toolModalOpen, setToolModalOpen] = useState(false);
+  const [enhance, setEnhance] = useState(false);
   const [tools, setTools] = useState<McpTool[]>([]);
   const [toolsLoading, setToolsLoading] = useState(false);
   const [clusterOptions, setClusterOptions] = useState<{ value: string; label: 
string }[]>([]);
@@ -850,7 +851,15 @@ const AiPage = () => {
                       <SlidersHorizontal size={17} />
                       <span>工具</span>
                     </button>
-                    <button className="tool-btn">
+                    <button
+                      className="tool-btn"
+                      onClick={() => setEnhance((value) => !value)}
+                      style={{
+                        borderColor: enhance ? '#1677ff' : undefined,
+                        color: enhance ? '#1677ff' : undefined,
+                      }}
+                      title="发送前增强 Prompt"
+                    >
                       <Sparkle size={17} />
                       <span>Prompt 增强</span>
                     </button>
@@ -859,7 +868,7 @@ const AiPage = () => {
                 <div className="shrink-0 flex items-center gap-1">
                   <button
                     className="flex items-center justify-center w-9 h-9 
rounded-full bg-gradient-to-r from-purple-500 to-violet-600 text-white 
shadow-lg hover:shadow-xl transition-all hover:scale-105"
-                    onClick={() => void handleSend()}
+                    onClick={() => void handleSend(undefined, undefined, 
enhance)}
                     disabled={loading || !inputValue.trim() || !llmReady}
                     style={{
                       opacity: loading || !inputValue.trim() || !llmReady ? 
0.5 : 1,
diff --git a/web/src/pages/instance/consumer.tsx 
b/web/src/pages/instance/consumer.tsx
index 095400877..d37625c20 100644
--- a/web/src/pages/instance/consumer.tsx
+++ b/web/src/pages/instance/consumer.tsx
@@ -685,6 +685,8 @@ const ConsumerPageContent = ({
         <Button
           size="small"
           icon={<Eye size={14} />}
+          disabled
+          title="队列分布暂未支持"
           style={{ borderColor: '#1677ff', color: '#1677ff' }}
         >
           查看分布
diff --git a/web/src/pages/instance/topic.tsx b/web/src/pages/instance/topic.tsx
index 09313851e..83be3de7c 100644
--- a/web/src/pages/instance/topic.tsx
+++ b/web/src/pages/instance/topic.tsx
@@ -335,6 +335,7 @@ const TopicPage = () => {
 
   const topicRequestIdRef = useRef(0);
   const detailRequestIdRef = useRef(0);
+  const consumersRequestIdRef = useRef(0);
   const createInFlightRef = useRef(false);
 
   useEffect(() => {
@@ -392,13 +393,17 @@ const TopicPage = () => {
   };
 
   const loadTopicConsumers = async (topic: Topic, page = 1, pageSize = 20) => {
+    const requestId = ++consumersRequestIdRef.current;
     const consumers = await getTopicConsumerPage(
       topic.name,
       selectedInstanceId || undefined,
       page,
       pageSize,
     );
-    setConsumersByTopic((previous) => ({ ...previous, [topic.name]: consumers 
}));
+    // Guard against a slower earlier page overwriting a newer one when the 
user pages quickly.
+    if (requestId === consumersRequestIdRef.current) {
+      setConsumersByTopic((previous) => ({ ...previous, [topic.name]: 
consumers }));
+    }
   };
 
   // ─── Open detail modal ────────────────────────────────────────

Reply via email to