feat: skill清空逻辑。因为后端接口不支持取消选择skill,所以暂时禁用取消选择按钮

This commit is contained in:
肖应宇 2026-04-09 10:23:27 +08:00
parent f68c09f90a
commit 25c444e83d
3 changed files with 82 additions and 19 deletions

View File

@ -313,6 +313,23 @@ export function IframeTestPanel() {
>
📦 selectedSkills message
</Button>
<Button
size="sm"
className="w-full bg-slate-50 text-xs text-slate-700 hover:bg-slate-100"
variant="ghost"
onClick={() => {
window.postMessage(
{
type: POST_MESSAGE_TYPES.SELECT_SKILLS,
selectedSkills: [],
},
"*",
);
addLog("模拟宿主页 → selectedSkills []");
}}
>
🧹 selectedSkills
</Button>
<Button
size="sm"
className="w-full bg-orange-50 text-xs text-orange-700 hover:bg-orange-100"

View File

@ -648,7 +648,7 @@ function IframeSkillDialogButton({
selectedSkills: Array<{ skill_id: string; title: string }>;
isBootstrapping: boolean;
openSkillDialog: () => void;
clearSkill: () => void;
clearSkill: (skillId?: string) => void;
}) {
const { t } = useI18n();
@ -683,13 +683,14 @@ function IframeSkillDialogButton({
{selectedSkills.map((skill, index) => (
<Tag key={`${skill.skill_id}-${skill.title}-${index}`}>
{skill.title}
<button
onClick={clearSkill}
{/* TODO: 因为后端接口不支持取消选择skill所以暂时禁用取消选择按钮 */}
{/* <button
onClick={() => clearSkill(skill.skill_id)}
className="hover:bg-muted-foreground/20 ml-1 rounded-full"
type="button"
>
<XIcon className="size-3" />
</button>
</button> */}
</Tag>
))}
</div>

View File

@ -60,7 +60,7 @@ interface UseIframeSkillReturn {
title: string;
}) => Promise<boolean>;
openSkillDialog: () => void;
clearSkill: () => void;
clearSkill: (skillId?: string) => void;
}
interface UseIframeSkillOptions {
@ -149,12 +149,18 @@ export function useIframeSkill(
// 4. 选择变化时同步到 localStorage
useEffect(() => {
const threadKey = getThreadStorageKey(threadId);
if (selectedSkills.length === 0) {
// 空数组也要同步到存储,避免 UI 状态与缓存不一致
window.localStorage.removeItem(STORAGE_KEYS.latest);
if (threadKey) {
window.localStorage.removeItem(threadKey);
}
return;
}
const payload = JSON.stringify(selectedSkills);
window.localStorage.setItem(STORAGE_KEYS.latest, payload);
const threadKey = getThreadStorageKey(threadId);
if (threadKey) {
window.localStorage.setItem(threadKey, payload);
}
@ -262,19 +268,58 @@ export function useIframeSkill(
}, []);
// 清除选中并发送空 selectedSkills 数组给主页
const clearSkill = useCallback(() => {
setSelectedSkill(null);
setSelectedSkills([]);
window.localStorage.removeItem(STORAGE_KEYS.latest);
const threadKey = getThreadStorageKey(threadId);
if (threadKey) {
window.localStorage.removeItem(threadKey);
}
// 发送空数组给主页,通知取消选择
const message = { type: POST_MESSAGE_TYPES.SELECT_SKILLS, selectedSkills: [] };
console.log("[useIframeSkill] clearSkill, sending selectedSkills=[]:", message);
sendToParent(message);
}, [threadId]);
const clearSkill = useCallback(
(skillId?: string) => {
const removeAll = !skillId;
const nextSelectedSkills = removeAll
? []
: selectedSkills.filter((skill) => skill.skill_id !== String(skillId));
setSelectedSkills(nextSelectedSkills);
setSelectedSkill(nextSelectedSkills[0] ?? null);
// 同步 latest 缓存:仅删除对应 skill或全部清空
const latestSkills = parseStoredSkills(
window.localStorage.getItem(STORAGE_KEYS.latest),
);
const nextLatestSkills = removeAll
? []
: latestSkills.filter((skill) => skill.skill_id !== String(skillId));
if (nextLatestSkills.length > 0) {
window.localStorage.setItem(
STORAGE_KEYS.latest,
JSON.stringify(nextLatestSkills),
);
} else {
window.localStorage.removeItem(STORAGE_KEYS.latest);
}
// 同步线程缓存:保存剩余数组,空则删除 key
const threadKey = getThreadStorageKey(threadId);
if (threadKey) {
if (nextSelectedSkills.length > 0) {
window.localStorage.setItem(
threadKey,
JSON.stringify(nextSelectedSkills),
);
} else {
window.localStorage.removeItem(threadKey);
}
}
// 通知宿主页当前剩余技能
const message = {
type: POST_MESSAGE_TYPES.SELECT_SKILLS,
selectedSkills: nextSelectedSkills.map((skill) => ({
id: skill.skill_id,
name: skill.title,
})),
} as const;
console.log("[useIframeSkill] clearSkill:", message);
sendToParent(message);
},
[selectedSkills, threadId],
);
return {
selectedSkill,