agent-Specialization/static/src/composables/useEasterEgg.ts

163 lines
4.2 KiB
TypeScript

import { useUiStore } from '@/stores/ui';
let overlayRoot: HTMLElement | null = null;
export function useEasterEgg() {
const uiStore = useUiStore();
const registerOverlayRoot = (el: HTMLElement | null) => {
overlayRoot = el;
if (!el) {
finishCleanup();
}
};
const finishCleanup = () => {
const state = uiStore.easterEgg;
if (state.cleanupTimer) {
clearTimeout(state.cleanupTimer);
}
const root = overlayRoot;
if (root) {
root.innerHTML = '';
}
uiStore.clearEasterEgg();
};
const destroyEffect = (forceImmediate = false) => {
const state = uiStore.easterEgg;
if (state.cleanupTimer) {
clearTimeout(state.cleanupTimer);
uiStore.setEasterEggState({ cleanupTimer: null });
}
const instance = state.instance;
if (!instance) {
finishCleanup();
return Promise.resolve();
}
if (state.destroying) {
return state.destroyPromise || Promise.resolve();
}
uiStore.setEasterEggState({ destroying: true });
let result: unknown;
try {
result = instance.destroy({
immediate: forceImmediate,
payload: state.payload,
root: overlayRoot
});
} catch (error) {
console.warn('销毁彩蛋时发生错误:', error);
uiStore.setEasterEggState({ destroying: false });
finishCleanup();
return Promise.resolve();
}
const finalize = () => {
uiStore.setEasterEggState({ destroyPromise: null, destroying: false });
finishCleanup();
};
if (result && typeof (result as Promise<void>).then === 'function') {
const promise = (result as Promise<void>)
.then(() => {
finalize();
})
.catch((error) => {
console.warn('彩蛋清理失败:', error);
finalize();
});
uiStore.setEasterEggState({ destroyPromise: promise });
return promise;
}
finalize();
return Promise.resolve();
};
const startEffect = async (effectName: string, payload: any = {}, app?: any) => {
const registry = (window as any).EasterEggRegistry;
if (!registry) {
console.warn('EasterEggRegistry 尚未加载,无法播放彩蛋');
return;
}
if (!registry.has(effectName)) {
console.warn('未注册的彩蛋 effect:', effectName);
await destroyEffect(true);
return;
}
const root = overlayRoot;
if (!root) {
console.warn('未找到彩蛋根节点');
return;
}
await destroyEffect(true);
uiStore.setEasterEggState({
active: true,
effect: effectName,
payload
});
const instance = registry.start(effectName, {
root,
payload,
app
});
if (!instance) {
finishCleanup();
return;
}
uiStore.setEasterEggState({
instance,
destroyPromise: null,
destroying: false
});
if (uiStore.easterEgg.cleanupTimer) {
clearTimeout(uiStore.easterEgg.cleanupTimer);
}
const durationSeconds = Math.max(8, Number(payload?.duration_seconds) || 45);
const timer = setTimeout(() => {
const cleanup = destroyEffect(false);
if (cleanup && typeof cleanup.catch === 'function') {
cleanup.catch(() => {});
}
}, durationSeconds * 1000);
uiStore.setEasterEggState({ cleanupTimer: timer });
if (payload?.message) {
console.info(`[彩蛋] ${payload.display_name || effectName}: ${payload.message}`);
}
};
const handlePayload = async (payload: any, app?: any) => {
let parsed = payload;
if (typeof payload === 'string') {
try {
parsed = JSON.parse(payload);
} catch (error) {
console.warn('无法解析彩蛋结果:', payload);
return;
}
}
if (!parsed || typeof parsed !== 'object') {
return;
}
if (!parsed.success) {
if (parsed.error) {
console.warn('彩蛋触发失败:', parsed.error);
}
await destroyEffect(true);
return;
}
const effectName = (parsed.effect || '').toLowerCase();
if (!effectName) {
console.warn('彩蛋结果缺少 effect 字段');
return;
}
await startEffect(effectName, parsed, app);
};
return {
registerOverlayRoot,
handlePayload,
startEffect,
destroyEffect,
finishCleanup
};
}