feat(skill): 新增 postMessage 方式获取 skill 初始化参数

This commit is contained in:
肖应宇 2026-03-18 11:52:01 +08:00
parent 83511dee5f
commit b5b1cd6ad8
1 changed files with 66 additions and 7 deletions

View File

@ -1,7 +1,7 @@
"use client"; "use client";
import { useParams, usePathname, useSearchParams } from "next/navigation"; import { useParams, usePathname, useSearchParams } from "next/navigation";
import { useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { uuid } from "@/core/utils/uuid"; import { uuid } from "@/core/utils/uuid";
@ -22,6 +22,22 @@ export interface ThreadChatResult {
}; };
} }
// postMessage 消息类型定义
interface SelectedSkillMessage {
type: "selectedSkill";
id: number;
title: string;
}
function isSelectedSkillMessage(data: unknown): data is SelectedSkillMessage {
return (
typeof data === "object" &&
data !== null &&
(data as SelectedSkillMessage).type === "selectedSkill" &&
typeof (data as SelectedSkillMessage).id === "number"
);
}
export function useThreadChat(): ThreadChatResult { export function useThreadChat(): ThreadChatResult {
console.log("[useThreadChat] ========== HOOK CALLED =========="); console.log("[useThreadChat] ========== HOOK CALLED ==========");
@ -72,14 +88,14 @@ export function useThreadChat(): ThreadChatResult {
return result; return result;
}, [searchParams]); }, [searchParams]);
// [移植自 main 分支 ef9a071] 获取 skill 初始化参数 // [移植自 main 分支 ef9a071] 获取 skill 初始化参数 (从 URL)
const skillBootstrap = useMemo(() => { const skillBootstrapFromUrl = useMemo(() => {
console.log("[useThreadChat] --- Parsing skillBootstrap params ---"); console.log("[useThreadChat] --- Parsing skillBootstrap params from URL ---");
const skillIdRaw = searchParams.get("skill_id")?.trim(); const skillIdRaw = searchParams.get("skill_id")?.trim();
console.log("[useThreadChat] skill_id raw:", skillIdRaw); console.log("[useThreadChat] skill_id raw:", skillIdRaw);
if (!skillIdRaw) { if (!skillIdRaw) {
console.log("[useThreadChat] skillBootstrap: undefined (no skill_id)"); console.log("[useThreadChat] skillBootstrapFromUrl: undefined (no skill_id)");
return undefined; return undefined;
} }
@ -87,7 +103,7 @@ export function useThreadChat(): ThreadChatResult {
console.log("[useThreadChat] contentId parsed:", contentId, "isFinite:", Number.isFinite(contentId)); console.log("[useThreadChat] contentId parsed:", contentId, "isFinite:", Number.isFinite(contentId));
if (!Number.isFinite(contentId)) { if (!Number.isFinite(contentId)) {
console.log("[useThreadChat] skillBootstrap: undefined (invalid contentId)"); console.log("[useThreadChat] skillBootstrapFromUrl: undefined (invalid contentId)");
return undefined; return undefined;
} }
@ -104,10 +120,53 @@ export function useThreadChat(): ThreadChatResult {
contentId, contentId,
languageType: Number.isFinite(languageType) ? languageType : 0, languageType: Number.isFinite(languageType) ? languageType : 0,
}; };
console.log("[useThreadChat] skillBootstrap result:", result); console.log("[useThreadChat] skillBootstrapFromUrl result:", result);
return result; return result;
}, [searchParams]); }, [searchParams]);
// [新增] postMessage 方式获取 skill 初始化参数
const [skillBootstrapFromPostMessage, setSkillBootstrapFromPostMessage] = useState<{
contentId: number;
languageType: number;
} | undefined>(undefined);
// [新增] 监听 postMessage 消息
useEffect(() => {
console.log("[useThreadChat] Setting up postMessage listener");
const handleMessage = (event: MessageEvent) => {
console.log("[useThreadChat] postMessage received:", event.data);
// 检查消息类型
if (!isSelectedSkillMessage(event.data)) {
console.log("[useThreadChat] postMessage ignored: not a selectedSkill message");
return;
}
const { id, title } = event.data;
console.log("[useThreadChat] selectedSkill message - id:", id, "title:", title);
// 设置 skillBootstrap
const newSkillBootstrap = {
contentId: id,
languageType: 0, // 默认语言类型
};
console.log("[useThreadChat] Setting skillBootstrap from postMessage:", newSkillBootstrap);
setSkillBootstrapFromPostMessage(newSkillBootstrap);
};
window.addEventListener("message", handleMessage);
return () => {
console.log("[useThreadChat] Cleaning up postMessage listener");
window.removeEventListener("message", handleMessage);
};
}, []);
// [新增] 合并 URL 和 postMessage 的 skillBootstrap (postMessage 优先)
const skillBootstrap = skillBootstrapFromPostMessage ?? skillBootstrapFromUrl;
console.log("[useThreadChat] skillBootstrap final:", skillBootstrap ? JSON.stringify(skillBootstrap) : undefined);
// [修复] 使用 useRef 缓存生成的 threadId避免 React StrictMode 下重复生成 // [修复] 使用 useRef 缓存生成的 threadId避免 React StrictMode 下重复生成
const threadIdRef = useRef<string | null>(null); const threadIdRef = useRef<string | null>(null);
const isNewThreadRef = useRef<boolean | null>(null); const isNewThreadRef = useRef<boolean | null>(null);