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

This commit is contained in:
肖应宇 2026-04-09 10:23:27 +08:00 committed by Titan
parent c1ab79e2cb
commit f2921ae3df
3 changed files with 82 additions and 19 deletions

View File

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

View File

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