From 58df004d02511d7c16900cd2a974bb1b4c1d0fac Mon Sep 17 00:00:00 2001 From: Pine Date: Sun, 13 Sep 2026 17:31:54 +0800 Subject: [PATCH] =?UTF-8?q?fix(console):=20=E6=B8=85=E7=90=86=E6=A1=8C?= =?UTF-8?q?=E9=9D=A2=E7=AB=AF=E6=8E=A7=E5=88=B6=E5=8F=B0=20React/antd=20?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E6=9C=9F=E8=AD=A6=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - mermaidComponents 增加安全 渲染器:解构掉 XMarkdown 注入的 domNode/streamStatus,避免透传到 DOM 触发 React warning,并改为 外链在系统浏览器/新标签打开(防止 Tauri WebView 内跳转丢失应用) - 6 处独立 Spin+tip 改为嵌套模式(antd 要求 nest/fullscreen 才显示 tip), 消除 'tip only work in nest or fullscreen' 警告:MainLayout Suspense fallback、DefaultRedirect、Network Chat、政策/服务详情页 说明:Chat 页正文的 domNode/streamStatus、Input key、flushSync、 findDOMNode 警告来自 @agentscope-ai/chat 三方库内部硬编码,开发期 显示、不影响功能,生产构建无。 --- .../MermaidCodeBlock/mermaidComponents.tsx | 39 +++++++++++++++++-- console/src/layouts/MainLayout/index.tsx | 4 +- .../src/layouts/registry/builtinRoutes.tsx | 4 +- console/src/pages/Agent/Network/Chat.tsx | 8 +++- console/src/pages/portal/Opc/PolicyDetail.tsx | 4 +- .../src/pages/portal/Opc/ServiceDetail.tsx | 4 +- 6 files changed, 50 insertions(+), 13 deletions(-) diff --git a/console/src/components/MermaidCodeBlock/mermaidComponents.tsx b/console/src/components/MermaidCodeBlock/mermaidComponents.tsx index d04affe..589e5c6 100644 --- a/console/src/components/MermaidCodeBlock/mermaidComponents.tsx +++ b/console/src/components/MermaidCodeBlock/mermaidComponents.tsx @@ -1,8 +1,9 @@ -import type { ReactNode } from "react"; +import type { CSSProperties, ComponentType, ReactNode } from "react"; import type { ComponentProps } from "@ant-design/x-markdown"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"; import { MermaidCodeBlock } from "./MermaidCodeBlock"; +import { openExternalLink } from "@/utils/openExternalLink"; /** * Extracts plain text from React children recursively. @@ -66,6 +67,37 @@ function CodeWithMermaid({ ); } +/** + * Safe markdown renderer for XMarkdown. + * + * XMarkdown injects `domNode` / `streamStatus` into every custom component; + * if passed through to the DOM element they trigger React warnings. The two + * props are destructured off, and clicks open the link in the system browser + * / new tab instead of navigating the Tauri WebView window away from the app. + */ +function SafeMarkdownAnchor({ + domNode: _domNode, + streamStatus: _streamStatus, + href, + children, + ...rest +}: ComponentProps) { + const linkHref = typeof href === "string" ? href : undefined; + return ( + { + event.preventDefault(); + if (linkHref) openExternalLink(linkHref); + }} + style={{ cursor: "pointer", ...(rest as { style?: CSSProperties }).style }} + > + {children} + + ); +} + /** * XMarkdown components mapping that enables Mermaid diagram rendering. * @@ -76,7 +108,8 @@ function CodeWithMermaid({ */ export const mermaidComponents: Record< string, - React.ComponentType + ComponentType > = { code: CodeWithMermaid, -}; + a: SafeMarkdownAnchor, +}; \ No newline at end of file diff --git a/console/src/layouts/MainLayout/index.tsx b/console/src/layouts/MainLayout/index.tsx index b2450a2..077df4e 100644 --- a/console/src/layouts/MainLayout/index.tsx +++ b/console/src/layouts/MainLayout/index.tsx @@ -1,7 +1,6 @@ import { Suspense, useMemo } from "react"; import { Layout, Spin } from "antd"; import { Routes, Route, useLocation, matchPath } from "react-router-dom"; -import { useTranslation } from "react-i18next"; import Sidebar from "../Sidebar"; import Header from "../Header"; import ConsolePollService from "../../components/ConsolePollService"; @@ -40,7 +39,6 @@ function pickSelectedKey( } export default function MainLayout() { - const { t } = useTranslation(); const location = useLocation(); const currentPath = location.pathname; const routes = useRoutes(); @@ -81,7 +79,7 @@ export default function MainLayout() { } diff --git a/console/src/layouts/registry/builtinRoutes.tsx b/console/src/layouts/registry/builtinRoutes.tsx index bbc1cda..66baa23 100644 --- a/console/src/layouts/registry/builtinRoutes.tsx +++ b/console/src/layouts/registry/builtinRoutes.tsx @@ -18,7 +18,6 @@ import { Suspense } from "react"; import { Navigate } from "react-router-dom"; import { Spin } from "antd"; -import { useTranslation } from "react-i18next"; import { lazyImportWithRetry } from "../../utils/lazyWithRetry"; import { useCodingMode } from "../../stores/codingModeStore"; import { routeRegistry } from "../../plugins/registry/store"; @@ -140,12 +139,11 @@ const AppCenterPage = lazyImportWithRetry("../../pages/AppCenter"); * deciding between /coding and /chat — see MainLayout.tsx history for why. */ function DefaultRedirect() { - const { t } = useTranslation(); const { codingMode, initialized } = useCodingMode(); if (!initialized) { return ( ); diff --git a/console/src/pages/Agent/Network/Chat.tsx b/console/src/pages/Agent/Network/Chat.tsx index 66edfb0..5b9326f 100644 --- a/console/src/pages/Agent/Network/Chat.tsx +++ b/console/src/pages/Agent/Network/Chat.tsx @@ -79,7 +79,9 @@ export default function AgentNetworkChatPage() { if (loading) { return (
- + +
+
); } @@ -123,7 +125,9 @@ export default function AgentNetworkChatPage() { {conversation ? ( ) : ( - + +
+ )}
diff --git a/console/src/pages/portal/Opc/PolicyDetail.tsx b/console/src/pages/portal/Opc/PolicyDetail.tsx index faba3e4..81c6e54 100644 --- a/console/src/pages/portal/Opc/PolicyDetail.tsx +++ b/console/src/pages/portal/Opc/PolicyDetail.tsx @@ -38,7 +38,9 @@ export default function OpcPolicyDetail() { return (
- + +
+
); diff --git a/console/src/pages/portal/Opc/ServiceDetail.tsx b/console/src/pages/portal/Opc/ServiceDetail.tsx index 70440db..7e734f9 100644 --- a/console/src/pages/portal/Opc/ServiceDetail.tsx +++ b/console/src/pages/portal/Opc/ServiceDetail.tsx @@ -114,7 +114,9 @@ export default function ServiceDetailPage() { if (loading) { return (
- + +
+
); }