Files
deerflow-code/frontend-web/src/pages/LightAppIframeView.tsx
T
2026-07-24 14:12:42 +08:00

60 lines
2.1 KiB
TypeScript

/**
* 轻应用 iframe 宿主页 —— 渲染某个已注册 iframe 类型应用。
*
* 路由:/page/strategy/light-app/view/:appId。侧边栏动态注入的 iframe 应用子项指向此页。
* 用 buildLightAppUrl 构造带路由参数(登录态 / 主题)的 src。
*/
import { useMemo } from "react";
import { useParams } from "react-router-dom";
import { useTheme } from "@/contexts/ThemeContext";
import { useLightApp } from "@/strategy-components/api/light-apps";
import { buildLightAppUrl, type AppThemeColor } from "@/strategy-components/lib/light-app";
export default function LightAppIframeView() {
const { appId } = useParams<{ appId: string }>();
const { theme } = useTheme();
const isDark = theme === "dark";
const { data: app, isLoading, error } = useLightApp(appId);
// 由 useTheme 的 theme 直接换算主题色并显式传入,切主题时 src 立即重建、
// 把新主题色传给被嵌套应用(不依赖 <html> 的 dark class,避免时序读旧值)。
// 深色=dark-blue,浅蓝=blue,其余(红白)=red。
const themeColor: AppThemeColor =
theme === "dark"
? "dark-blue"
: theme === "lightgreen"
? "green"
: theme === "lightblue"
? "blue"
: theme === "iceblue"
? "iceblue"
: theme === "lightyellow"
? "lightyellow"
: "red";
const src = useMemo(
() => (app ? buildLightAppUrl(app, undefined, themeColor) : ""),
[app, themeColor],
);
const centerClass = `flex h-full w-full items-center justify-center text-sm ${
isDark ? "text-slate-400" : "text-slate-500"
}`;
if (isLoading) {
return <div className={centerClass}>加载中…</div>;
}
if (error || !app) {
return <div className={centerClass}>应用不存在或已被删除</div>;
}
if (app.appType !== "iframe") {
return <div className={centerClass}>该应用不是 iframe 嵌套类型</div>;
}
return (
<div className="flex h-full w-full flex-col">
<iframe src={src} title={app.name} className="w-full flex-1 border-0" />
</div>
);
}