diff --git a/frontend-web/src/core/page-layout/chats-iframe-route.test.mjs b/frontend-web/src/core/page-layout/chats-iframe-route.test.mjs index 4d237adb..246c2d70 100644 --- a/frontend-web/src/core/page-layout/chats-iframe-route.test.mjs +++ b/frontend-web/src/core/page-layout/chats-iframe-route.test.mjs @@ -45,14 +45,37 @@ test("requires an explicit chatMode=iframe opt-in for the Brainy page", () => { assert.equal(isExplicitBrainyIframeMode("chatMode=IFRAME"), true); }); -test("redirects accidental chats_iframe routes to standard full chat", () => { +test("upgrades legacy iframe-source routes to the iframe protocol", () => { assert.equal( resolveStandardChatFallback( "/page/workspace/chats_iframe/new", "?from=iframe&hideChrome=1", ), - "/page/workspace/chats/new?hideChrome=1&chatMode=full", + "/page/workspace/chats_iframe/new?from=iframe&hideChrome=1&chatMode=iframe", ); +}); + +test("honors an explicit chat mode over the legacy iframe source", () => { + assert.equal( + resolveStandardChatFallback( + "/page/workspace/chats_iframe/new", + "?from=iframe&chatMode=full", + ), + "/page/workspace/chats/new?chatMode=full", + ); +}); + +test("treats a blank chat mode as absent for the legacy iframe source", () => { + assert.equal( + resolveStandardChatFallback( + "/page/workspace/chats_iframe/new", + "?from=iframe&chatMode=%20%20", + ), + "/page/workspace/chats_iframe/new?from=iframe&chatMode=iframe", + ); +}); + +test("redirects chats_iframe routes without the iframe source to standard full chat", () => { assert.equal( resolveStandardChatFallback( "/page/workspace/chats_iframe/thread-123", @@ -121,17 +144,17 @@ test("forces the iframe theme on the login route without changing normal login", test("preserves the iframe theme in the post-login redirect", () => { assert.equal( buildChatsIframeRedirectPath("?from=iframe&theme=dark-blue"), - "/page/workspace/chats_iframe/new?from=iframe&theme=dark-blue", + "/page/workspace/chats_iframe/new?from=iframe&chatMode=iframe&theme=dark-blue", ); assert.equal( buildChatsIframeRedirectPath("?from=iframe"), - "/page/workspace/chats_iframe/new?from=iframe", + "/page/workspace/chats_iframe/new?from=iframe&chatMode=iframe", ); assert.equal( buildChatsIframeRedirectPath( "?from=iframe&theme=dark-blue&ticket=secret&authToken=secret", ), - "/page/workspace/chats_iframe/new?from=iframe&theme=dark-blue", + "/page/workspace/chats_iframe/new?from=iframe&chatMode=iframe&theme=dark-blue", ); }); @@ -141,7 +164,7 @@ test("keeps the iframe redirect ahead of login-method fallbacks", () => { "?from=iframe&theme=dark-blue&yUserId=user-1", "/page/workspace/chats/new", ), - "/page/workspace/chats_iframe/new?from=iframe&theme=dark-blue", + "/page/workspace/chats_iframe/new?from=iframe&chatMode=iframe&theme=dark-blue", ); assert.equal( resolvePostLoginRedirectPath("?yUserId=user-1", "/page/workspace/chats/new"), @@ -156,7 +179,7 @@ test("preserves iframe theme when a new chat becomes a thread", () => { "thread-123", "?from=iframe&theme=dark-blue&ticket=secret", ), - "/page/workspace/chats_iframe/thread-123?from=iframe&theme=dark-blue", + "/page/workspace/chats_iframe/thread-123?from=iframe&chatMode=iframe&theme=dark-blue", ); }); diff --git a/frontend-web/src/core/page-layout/chats-iframe-route.ts b/frontend-web/src/core/page-layout/chats-iframe-route.ts index 2868b00d..aadfb64d 100644 --- a/frontend-web/src/core/page-layout/chats-iframe-route.ts +++ b/frontend-web/src/core/page-layout/chats-iframe-route.ts @@ -23,7 +23,13 @@ export function buildChatsIframeRedirectPath(search: string): string { target.set("from", IFRAME_LOGIN_SOURCE); } - if (isExplicitBrainyIframeMode(search)) { + const requestedMode = source.get("chatMode")?.trim(); + if (requestedMode) { + target.set("chatMode", requestedMode); + } else if (isChatsIframeLogin(search)) { + // Plugin links historically identify this protocol with `from=iframe`. + // Normalize that legacy marker into the explicit mode before handing the + // URL to the workspace route, so it does not fall back to the full chat. target.set("chatMode", "iframe"); } @@ -89,21 +95,25 @@ export function resolveStandardChatFallback( pathname: string, search: string, ): string | null { - if ( - !isChatsIframeWorkspacePath(pathname) || - isExplicitBrainyIframeMode(search) - ) { + if (!isChatsIframeWorkspacePath(pathname) || isExplicitBrainyIframeMode(search)) { return null; } + const normalizedSearch = search.startsWith("?") ? search.slice(1) : search; + const params = new URLSearchParams(normalizedSearch); + const requestedMode = params.get("chatMode")?.trim(); + if (isChatsIframeLogin(search) && !requestedMode) { + params.set("chatMode", "iframe"); + const targetSearch = params.toString(); + return targetSearch ? `${pathname}?${targetSearch}` : pathname; + } + const routePrefix = "/page/workspace/chats_iframe/"; const routeSuffix = pathname.slice(routePrefix.length); const targetPath = routeSuffix && routeSuffix !== "new" ? `/page/workspace/chats/${routeSuffix}` : "/page/workspace/chats/new"; - const normalizedSearch = search.startsWith("?") ? search.slice(1) : search; - const params = new URLSearchParams(normalizedSearch); params.delete("from"); params.set("chatMode", "full"); const targetSearch = params.toString(); diff --git a/frontend-web/src/pages/IframeChatPage.tsx b/frontend-web/src/pages/IframeChatPage.tsx index ca66cb18..4bf84389 100644 --- a/frontend-web/src/pages/IframeChatPage.tsx +++ b/frontend-web/src/pages/IframeChatPage.tsx @@ -1,7 +1,6 @@ "use client"; import { - ArrowRightIcon, BookMarkedIcon, BotIcon, BrainCircuitIcon, @@ -709,7 +708,7 @@ export default function IframeChatPage() {
你好
- 选择智能体进入问答,或直接使用通用问答 + 选择智能体进入问答
-
{!selectorLoading && fallbackAgents.length === 0 && (
- 暂无可选智能体,仍可直接进入通用问答 + 暂无可选智能体
)}
diff --git a/frontend-web/src/pages/LoginPage.tsx b/frontend-web/src/pages/LoginPage.tsx index 7262ce3d..5acae55c 100644 --- a/frontend-web/src/pages/LoginPage.tsx +++ b/frontend-web/src/pages/LoginPage.tsx @@ -76,7 +76,6 @@ function summarizeStoredUserInfo(): Record | null { } const DEFAULT_USERNAME = 'guest'; -const IFRAME_LOGIN_SOURCE = 'iframe'; const IFRAME_CHAT_MODE = 'iframe'; const DEFAULT_REDIRECT_PATH = '/page/workspace/chats/new'; const FULL_CHAT_MODE = 'full'; @@ -104,15 +103,13 @@ export default function LoginPage() { searchParams.get('chatMode')?.trim().toLowerCase() ?? ''; const brainyIframeRequested = requestedChatMode === IFRAME_CHAT_MODE; // Wujie is an application container, not the Brainy iframe protocol. It - // must therefore land on the regular full ChatPage. Legacy `from=iframe` - // links now do the same; only the explicit `chatMode=iframe` protocol opt-in - // is allowed to open IframeChatPage. + // must therefore land on the regular full ChatPage. Plugin links with + // `from=iframe` are normalized into the explicit iframe protocol mode. const fullChatRequested = useMemo( () => !brainyIframeRequested && (isWujieEnv() || - requestedChatMode === FULL_CHAT_MODE || - searchParams.get('from') === IFRAME_LOGIN_SOURCE), + requestedChatMode === FULL_CHAT_MODE), [brainyIframeRequested, requestedChatMode, searchParams], ); const isIframeLogin = useMemo(