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";
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";
@ -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 {
console.log("[useThreadChat] ========== HOOK CALLED ==========");
@ -72,14 +88,14 @@ export function useThreadChat(): ThreadChatResult {
return result;
}, [searchParams]);
// [移植自 main 分支 ef9a071] 获取 skill 初始化参数
const skillBootstrap = useMemo(() => {
console.log("[useThreadChat] --- Parsing skillBootstrap params ---");
// [移植自 main 分支 ef9a071] 获取 skill 初始化参数 (从 URL)
const skillBootstrapFromUrl = useMemo(() => {
console.log("[useThreadChat] --- Parsing skillBootstrap params from URL ---");
const skillIdRaw = searchParams.get("skill_id")?.trim();
console.log("[useThreadChat] skill_id raw:", skillIdRaw);
if (!skillIdRaw) {
console.log("[useThreadChat] skillBootstrap: undefined (no skill_id)");
console.log("[useThreadChat] skillBootstrapFromUrl: undefined (no skill_id)");
return undefined;
}
@ -87,7 +103,7 @@ export function useThreadChat(): ThreadChatResult {
console.log("[useThreadChat] contentId parsed:", contentId, "isFinite:", Number.isFinite(contentId));
if (!Number.isFinite(contentId)) {
console.log("[useThreadChat] skillBootstrap: undefined (invalid contentId)");
console.log("[useThreadChat] skillBootstrapFromUrl: undefined (invalid contentId)");
return undefined;
}
@ -104,10 +120,53 @@ export function useThreadChat(): ThreadChatResult {
contentId,
languageType: Number.isFinite(languageType) ? languageType : 0,
};
console.log("[useThreadChat] skillBootstrap result:", result);
console.log("[useThreadChat] skillBootstrapFromUrl result:", result);
return result;
}, [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 下重复生成
const threadIdRef = useRef<string | null>(null);
const isNewThreadRef = useRef<boolean | null>(null);