const useIconStore = defineStore('icon', { state: () => ({ iconCache: new Map(), addingSet: new Set(), waitingCallbackFunctions: new Map void)[]>(), }), actions: { getIcon(iconName: string): string { if (this.iconCache.has(iconName)) { return this.iconCache.get(iconName) as string; } return ''; }, getColoredIcon(iconName: string, color: string): string { const icon = this.getIcon(iconName); if (icon === '') return ''; return icon.replace('((resolve) => { if (!this.waitingCallbackFunctions.has(iconName)) { this.waitingCallbackFunctions.set(iconName, [resolve]); } else this.waitingCallbackFunctions.get(iconName)!.push(resolve); }); } this.addingSet.add(iconName); if (iconData === undefined || iconData === null || iconData === '') { this.iconCache.set(iconName, await fetchSvg(iconName)); } else this.iconCache.set(iconName, iconData as string); this.addingSet.delete(iconName); this.waitingCallbackFunctions.get(iconName)?.forEach((callback) => callback()); this.waitingCallbackFunctions.delete(iconName); }, }, }); export default useIconStore; export async function fetchSvg(svgName: string, maxRetries = 3) { const iconifyUrl = 'https://api.iconify.design/'; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await (await $fetch(iconifyUrl + svgName + '.svg', { method: 'GET', params: { width: '100%', }, })).text(); } catch (error) { console.warn(`Attempt ${attempt} failed for ${svgName}:`, error); if (attempt === maxRetries) { console.error(`All ${maxRetries} attempts failed for ${svgName}`); } // 等待一段时间后重试(可选) await new Promise((resolve) => setTimeout(resolve, 1000 * attempt)); } } return ''; }