diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx index 7d5d4cb52d..9670c54c6d 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout-main.tsx @@ -32,6 +32,35 @@ export type IAppDetailLayoutProps = { appId: string } + +const useIframeHeader = () => { + const [show, setShow] = useState(true); + + useEffect(() => { + // 监听父级指定操作 + const handler = (event: MessageEvent) => { + // if (event.origin !== "https://gcgj.ngsk.tech:7001") return; + if (event.data.type === "HIDDEN") setShow(() => false); + }; + + // 初始化完成后提示iframe操作 + window.parent.postMessage( + { + type: "SIDEBA", + }, + "*" + ); + + window.addEventListener("message", handler); + return () => window.removeEventListener("message", handler); + }, []); + + return { + show, + }; +}; + + const AppDetailLayout: FC = (props) => { const { children, @@ -56,6 +85,7 @@ const AppDetailLayout: FC = (props) => { icon: NavIcon selectedIcon: NavIcon }>>([]) + const { show } = useIframeHeader() const getNavigations = useCallback((appId: string, isCurrentWorkspaceEditor: boolean, mode: string) => { const navs = [ @@ -160,9 +190,9 @@ const AppDetailLayout: FC = (props) => { return (
- {appDetail && ( + {show ? appDetail && ( - )} + ): ''}
{children}
diff --git a/web/app/components/header/header-wrapper.tsx b/web/app/components/header/header-wrapper.tsx index 6486e3707a..afd4f71044 100644 --- a/web/app/components/header/header-wrapper.tsx +++ b/web/app/components/header/header-wrapper.tsx @@ -1,5 +1,5 @@ 'use client' -import React, { useState } from 'react' +import React, { useState, useEffect } from "react"; import { usePathname } from 'next/navigation' import s from './index.module.css' import { useEventEmitterContextContext } from '@/context/event-emitter' @@ -9,6 +9,33 @@ type HeaderWrapperProps = { children: React.ReactNode } +const useIframeHeader = () => { + const [show, setShow] = useState(true); + + useEffect(() => { + // 监听父级指定操作 + const handler = (event: MessageEvent) => { + // if (event.origin !== "https://gcgj.ngsk.tech:7001") return; + if (event.data.type === "HIDDEN") setShow(() => false); + }; + + // 初始化完成后提示iframe操作 + window.parent.postMessage( + { + type: "HEADER", + }, + "*" + ); + + window.addEventListener("message", handler); + return () => window.removeEventListener("message", handler); + }, []); + + return { + show, + }; +}; + const HeaderWrapper = ({ children, }: HeaderWrapperProps) => { @@ -19,6 +46,7 @@ const HeaderWrapper = ({ const workflowCanvasMaximize = localStorage.getItem('workflow-canvas-maximize') === 'true' const [hideHeader, setHideHeader] = useState(workflowCanvasMaximize) const { eventEmitter } = useEventEmitterContextContext() + const { show } = useIframeHeader(); eventEmitter?.useSubscription((v: any) => { if (v?.type === 'workflow-canvas-maximize') @@ -26,15 +54,22 @@ const HeaderWrapper = ({ }) return ( -
- {children} -
- ) + <> + {show ? ( +
+ {children} +
+ ) : ( + "" + )} + + ); } export default HeaderWrapper diff --git a/web/app/signin/normalForm.tsx b/web/app/signin/normalForm.tsx index f8c973a13f..b54e303ee4 100644 --- a/web/app/signin/normalForm.tsx +++ b/web/app/signin/normalForm.tsx @@ -15,6 +15,37 @@ import Toast from '@/app/components/base/toast' import { IS_CE_EDITION } from '@/config' import { useGlobalPublicStore } from '@/context/global-public-context' +const useIframeToken = () => { + const router = useRouter(); + + useEffect(() => { + // 监听父级指定操作 + const handler = (event: MessageEvent) => { + // if (event.origin !== "https://gcgj.ngsk.tech:7001") return; + if ( + event.data.type === "LOGIN_AND_WORKFLOW_INTO" && + event.data.tokens && + event.data.workflowUrl + ) { + localStorage.setItem("console_token", event.data.tokens.console_token); + localStorage.setItem("refresh_token", event.data.tokens.refresh_token); + router.replace(event.data.workflowUrl); + } + }; + + // 首页初始化完成后提示iframe操作 + window.parent.postMessage( + { + type: "LOGIN_AND_WORKFLOW", + }, + "*" + ); + + window.addEventListener("message", handler); + return () => window.removeEventListener("message", handler); + }, []); +}; + const NormalForm = () => { const { t } = useTranslation() const router = useRouter() @@ -29,6 +60,7 @@ const NormalForm = () => { const [showORLine, setShowORLine] = useState(false) const [allMethodsAreDisabled, setAllMethodsAreDisabled] = useState(false) const [workspaceName, setWorkSpaceName] = useState('') + useIframeToken(); const isInviteLink = Boolean(invite_token && invite_token !== 'null') diff --git a/web/next.config.js b/web/next.config.js index 00793bf26a..847a5f6b32 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -27,30 +27,41 @@ const nextConfig = { basePath, assetPrefix, webpack: (config, { dev, isServer }) => { - config.plugins.push(codeInspectorPlugin({ bundler: 'webpack' })) - return config + config.plugins.push(codeInspectorPlugin({ bundler: "webpack" })); + return config; }, productionBrowserSourceMaps: false, // enable browser source map generation during the production build // Configure pageExtensions to include md and mdx - pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'], + pageExtensions: ["ts", "tsx", "js", "jsx", "md", "mdx"], // https://nextjs.org/docs/messages/next-image-unconfigured-host images: { - remotePatterns: remoteImageURLs.map(remoteImageURL => ({ - protocol: remoteImageURL.protocol.replace(':', ''), + remotePatterns: remoteImageURLs.map((remoteImageURL) => ({ + protocol: remoteImageURL.protocol.replace(":", ""), hostname: remoteImageURL.hostname, port: remoteImageURL.port, pathname: remoteImageURL.pathname, - search: '', + search: "", })), }, - experimental: { - }, + experimental: {}, // fix all before production. Now it slow the develop speed. eslint: { // Warning: This allows production builds to successfully complete even if // your project has ESLint errors. ignoreDuringBuilds: true, - dirs: ['app', 'bin', 'config', 'context', 'hooks', 'i18n', 'models', 'service', 'test', 'types', 'utils'], + dirs: [ + "app", + "bin", + "config", + "context", + "hooks", + "i18n", + "models", + "service", + "test", + "types", + "utils", + ], }, typescript: { // https://nextjs.org/docs/api-reference/next.config.js/ignoring-typescript-errors @@ -60,13 +71,30 @@ const nextConfig = { async redirects() { return [ { - source: '/', - destination: '/apps', + source: "/", + destination: "/apps", permanent: false, }, - ] + ]; + }, + output: "standalone", + async headers() { + return [ + { + source: "/(.*)", // 匹配所有路由 + headers: [ + { + key: "X-Frame-Options", + value: "ALLOWALL", // 或 ALLOWALL(更宽松) + }, + { + key: "Content-Security-Policy", + value: `default-src 'none'`, //允许所有 + }, + ], + }, + ]; }, - output: 'standalone', -} +}; module.exports = withBundleAnalyzer(withMDX(nextConfig))