deerflow2/frontend/src/core/iframe-messages.ts

129 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* iframe 与宿主页通信消息类型常量
*
* 消息格式:{ type: MESSAGE_TYPE, ...其他字段 }
* 发送方式window.parent.postMessage(message, "*")
*/
// 发送给宿主页的消息类型
export const POST_MESSAGE_TYPES = {
// 全屏切换
FULLSCREEN: "fullscreen",
// 会话是否处于聊天态
IS_CHATTING: "isChatting",
// 请求宿主页执行复制
COPY_TO_CLIPBOARD: "copyToClipboard",
// 选择预定义 skill
SELECT_SKILLS: "selectedSkills",
// 打开 skill 选择对话框
OPEN_SKILL_DIALOG: "openSkillDialog",
} as const;
// 接收来自宿主页的消息类型
export const RECEIVE_MESSAGE_TYPES = {
// 选中的 skill 数据
SELECTED_SKILL: "selectedSkill",
// 选中的 skills 数据(数组)
SELECTED_SKILLS: "selectedSkills",
} as const;
// 消息类型
export type PostMessageType =
(typeof POST_MESSAGE_TYPES)[keyof typeof POST_MESSAGE_TYPES];
export type ReceiveMessageType =
(typeof RECEIVE_MESSAGE_TYPES)[keyof typeof RECEIVE_MESSAGE_TYPES];
// 消息数据类型
export interface FullscreenMessage {
type: typeof POST_MESSAGE_TYPES.FULLSCREEN;
fullscreen: boolean;
}
export interface IsChattingMessage {
type: typeof POST_MESSAGE_TYPES.IS_CHATTING;
isChatting: boolean;
}
export interface CopyToClipboardMessage {
type: typeof POST_MESSAGE_TYPES.COPY_TO_CLIPBOARD;
text: string;
}
export interface SelectSkillMessage {
type: typeof POST_MESSAGE_TYPES.SELECT_SKILLS;
selectedSkills: SelectedSkillPayloadItem[];
}
export interface OpenSkillDialogMessage {
type: typeof POST_MESSAGE_TYPES.OPEN_SKILL_DIALOG;
openSkillDialog: true;
}
export interface SelectedSkillMessage {
type: typeof RECEIVE_MESSAGE_TYPES.SELECTED_SKILL;
id: string | number;
title: string;
}
export interface SelectedSkillPayloadItem {
id: string | number;
name: string;
}
type UnknownRecord = Record<string, unknown>;
function asRecord(value: unknown): UnknownRecord | null {
if (typeof value !== "object" || value === null) {
return null;
}
return value as UnknownRecord;
}
export function isSelectedSkillMessage(
value: unknown,
): value is SelectedSkillMessage {
const record = asRecord(value);
if (record?.type !== RECEIVE_MESSAGE_TYPES.SELECTED_SKILL) {
return false;
}
const { id, title } = record;
const isValidId = typeof id === "string" || typeof id === "number";
return isValidId && typeof title === "string" && title.trim().length > 0;
}
export function isSelectedSkillsMessage(
value: unknown,
): value is SelectSkillMessage {
const record = asRecord(value);
if (record?.type !== RECEIVE_MESSAGE_TYPES.SELECTED_SKILLS) {
return false;
}
const selectedSkills = record.selectedSkills;
if (!Array.isArray(selectedSkills)) {
return false;
}
return selectedSkills.every((item) => {
const skill = asRecord(item);
if (!skill) return false;
const id = skill.id;
const name = skill.name;
const isValidId = typeof id === "string" || typeof id === "number";
return isValidId && typeof name === "string" && name.trim().length > 0;
});
}
// 发送消息的辅助函数
export function sendToParent(
message:
| FullscreenMessage
| IsChattingMessage
| CopyToClipboardMessage
| SelectSkillMessage
| OpenSkillDialogMessage,
): void {
console.log("[iframe] sendToParent:", message);
if (window.parent !== window) {
window.parent.postMessage(message, "*");
}
}