chore(frontend): 删除未使用 selected skill 监听 hook
This commit is contained in:
parent
4bd2591a03
commit
105802d6c1
|
|
@ -1,152 +0,0 @@
|
|||
import { useSearchParams } from "next/navigation";
|
||||
import { useEffect, useCallback, useState, useRef } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { bootstrapRemoteSkill } from "@/core/skills/api";
|
||||
|
||||
/** 宿主页发过来的 selectedSkill 消息结构 */
|
||||
interface SelectedSkillMessage {
|
||||
type: "selectedSkill";
|
||||
id: number | string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
/** 技能基础数据 */
|
||||
interface SkillData {
|
||||
skill_id: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
/** 错误信息状态 */
|
||||
interface SkillError {
|
||||
title: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
interface UseSelectedSkillListenerOptions {
|
||||
/** 当前会话 thread_id,用于调用 bootstrapRemoteSkill */
|
||||
threadId: string | null;
|
||||
}
|
||||
|
||||
interface UseSelectedSkillListenerReturn {
|
||||
/** 当前选中的技能数据(用于 UI 展示,如 Badge) */
|
||||
selectedSkill: SkillData | null;
|
||||
/** 当前错误信息,不为 null 时展示 DevDialog */
|
||||
skillError: SkillError | null;
|
||||
/** 清除错误信息(关闭 DevDialog 时调用) */
|
||||
clearSkillError: () => void;
|
||||
/** 是否正在加载(处理 skill 中) */
|
||||
isBootstrapping: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听宿主页通过 postMessage 发送的 selectedSkill 消息或 URL 中的 skill 参数,
|
||||
* 收到后自动调用 bootstrapRemoteSkill 接口:
|
||||
* - 成功:使用 toast 提示
|
||||
* - 失败:返回 skillError 供 DevDialog 显示
|
||||
*/
|
||||
export function useSelectedSkillListener({
|
||||
threadId,
|
||||
}: UseSelectedSkillListenerOptions): UseSelectedSkillListenerReturn {
|
||||
const searchParams = useSearchParams();
|
||||
const [selectedSkill, setSelectedSkill] = useState<SkillData | null>(null);
|
||||
const [skillError, setSkillError] = useState<SkillError | null>(null);
|
||||
const [isBootstrapping, setIsBootstrapping] = useState(false);
|
||||
|
||||
const isFirstLoadRef = useRef(false);
|
||||
const skillBootstrappedKeyRef = useRef<string | null>(null);
|
||||
|
||||
const performBootstrap = useCallback(
|
||||
async (id: number | string, title: string) => {
|
||||
if (!threadId) return;
|
||||
|
||||
const languageTypeRaw =
|
||||
searchParams.get("languageType")?.trim() ??
|
||||
searchParams.get("language_type")?.trim();
|
||||
const languageType = languageTypeRaw ? Number(languageTypeRaw) : 0;
|
||||
|
||||
const initKey = `${threadId}:${id}:${languageType}`;
|
||||
if (skillBootstrappedKeyRef.current === initKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[useSelectedSkillListener] 开始初始化技能: ${title} (${id})`,
|
||||
);
|
||||
setIsBootstrapping(true);
|
||||
toast.loading(`正在加载技能「${title}」...`, { id: "skill-bootstrap" });
|
||||
|
||||
try {
|
||||
const result = await bootstrapRemoteSkill({
|
||||
thread_id: threadId,
|
||||
content_id: Number(id),
|
||||
language_type: languageType,
|
||||
target_dir: "/mnt/user-data/uploads/skill",
|
||||
clear_target: true,
|
||||
});
|
||||
|
||||
toast.dismiss("skill-bootstrap");
|
||||
|
||||
if (result.success) {
|
||||
skillBootstrappedKeyRef.current = initKey;
|
||||
toast.success(`技能「${title}」加载成功`, {
|
||||
description:
|
||||
result.message || `已创建 ${result.created_files} 个文件`,
|
||||
duration: 4000,
|
||||
});
|
||||
} else {
|
||||
setSkillError({
|
||||
title: `技能「${title}」加载失败`,
|
||||
message: result.message || "未知错误",
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
toast.dismiss("skill-bootstrap");
|
||||
const message = err instanceof Error ? err.message : "网络请求失败";
|
||||
setSkillError({ title: `技能「${title}」加载出错`, message });
|
||||
} finally {
|
||||
setIsBootstrapping(false);
|
||||
}
|
||||
},
|
||||
[threadId, searchParams],
|
||||
);
|
||||
|
||||
// 1. URL 初始化集成
|
||||
useEffect(() => {
|
||||
if (!threadId || isFirstLoadRef.current) return;
|
||||
|
||||
const skillIdFromQuery = searchParams.get("skill_id");
|
||||
const titleFromQuery = searchParams.get("title");
|
||||
if (skillIdFromQuery && titleFromQuery) {
|
||||
isFirstLoadRef.current = true;
|
||||
setSelectedSkill({ skill_id: skillIdFromQuery, title: titleFromQuery });
|
||||
void performBootstrap(skillIdFromQuery, titleFromQuery);
|
||||
}
|
||||
}, [threadId, searchParams, performBootstrap]);
|
||||
|
||||
const handleMessage = useCallback(
|
||||
(event: MessageEvent) => {
|
||||
const data = event.data as SelectedSkillMessage;
|
||||
if (data?.type !== "selectedSkill") return;
|
||||
|
||||
const { id, title } = data;
|
||||
console.log(
|
||||
"[useSelectedSkillListener] 收到 postMessage selectedSkill:",
|
||||
data,
|
||||
);
|
||||
|
||||
setSelectedSkill({ skill_id: String(id), title });
|
||||
void performBootstrap(id, title);
|
||||
},
|
||||
[performBootstrap],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("message", handleMessage);
|
||||
return () => window.removeEventListener("message", handleMessage);
|
||||
}, [handleMessage]);
|
||||
|
||||
const clearSkillError = useCallback(() => setSkillError(null), []);
|
||||
|
||||
return { selectedSkill, skillError, clearSkillError, isBootstrapping };
|
||||
}
|
||||
Loading…
Reference in New Issue