feat(skill): 新增 postMessage 方式获取 skill 初始化参数
This commit is contained in:
parent
83511dee5f
commit
b5b1cd6ad8
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue