refactor(frontend): 在输入框内嵌 iframe skill 通信逻辑

This commit is contained in:
肖应宇 2026-03-29 01:02:01 +08:00
parent 93b9bc7af5
commit 4afba86bcb
1 changed files with 74 additions and 2 deletions

View File

@ -59,7 +59,6 @@ import {
import { useI18n } from "@/core/i18n/hooks";
import { useModels } from "@/core/models/hooks";
import type { AgentThreadContext } from "@/core/threads";
import { useIframeSkill } from "@/hooks/use-iframe-skill";
import { cn } from "@/lib/utils";
import {
@ -82,6 +81,79 @@ import {
import { ModeHoverGuide } from "./mode-hover-guide";
import { Tooltip } from "./tooltip";
const POST_MESSAGE_TYPES = {
SELECT_SKILL: "selectSkill",
OPEN_SKILL_DIALOG: "openSkillDialog",
} as const;
const RECEIVE_MESSAGE_TYPES = {
SELECTED_SKILL: "selectedSkill",
} as const;
type IframeSelectedSkillMessage = {
type: typeof RECEIVE_MESSAGE_TYPES.SELECTED_SKILL;
id: string | number;
title: string;
};
type IframeSkillData = {
skill_id: string;
title: string;
};
function sendIframeMessageToParent(message: unknown): void {
if (window.parent !== window) {
window.parent.postMessage(message, "*");
}
}
function useEmbeddedIframeSkill() {
const searchParams = useSearchParams();
const skillIdFromQuery = searchParams.get("skill_id");
const titleFromQuery = searchParams.get("title");
const [selectedSkill, setSelectedSkill] = useState<IframeSkillData | null>(
null,
);
useEffect(() => {
if (skillIdFromQuery && titleFromQuery) {
setSelectedSkill({ skill_id: skillIdFromQuery, title: titleFromQuery });
}
}, [skillIdFromQuery, titleFromQuery]);
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
if (event.data?.type === RECEIVE_MESSAGE_TYPES.SELECTED_SKILL) {
const { id, title } = event.data as IframeSelectedSkillMessage;
setSelectedSkill({ skill_id: String(id), title });
}
};
window.addEventListener("message", handleMessage);
return () => window.removeEventListener("message", handleMessage);
}, []);
const sendSelectSkill = useCallback((skill_id: string) => {
sendIframeMessageToParent({ type: POST_MESSAGE_TYPES.SELECT_SKILL, skill_id });
}, []);
const openSkillDialog = useCallback(() => {
sendIframeMessageToParent({
type: POST_MESSAGE_TYPES.OPEN_SKILL_DIALOG,
openSkillDialog: true,
});
}, []);
const clearSkill = useCallback(() => {
setSelectedSkill(null);
sendIframeMessageToParent({
type: POST_MESSAGE_TYPES.SELECT_SKILL,
skill_id: "0",
});
}, []);
return { selectedSkill, sendSelectSkill, openSkillDialog, clearSkill };
}
export function InputBox({
className,
disabled,
@ -125,7 +197,7 @@ export function InputBox({
}) {
const { t } = useI18n();
const searchParams = useSearchParams();
const iframeSkill = useIframeSkill();
const iframeSkill = useEmbeddedIframeSkill();
const params = useParams();
const threadId = threadIdProp ?? params?.thread_id;