From 4259deb19122a4807d50c99ed4a95405ebe4a47c Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期五, 10 四月 2026 08:40:18 +0800
Subject: [PATCH] #
---
rsf-design/src/utils/ui/iconify-loader.js | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 163 insertions(+), 0 deletions(-)
diff --git a/rsf-design/src/utils/ui/iconify-loader.js b/rsf-design/src/utils/ui/iconify-loader.js
index e69de29..f62f06e 100644
--- a/rsf-design/src/utils/ui/iconify-loader.js
+++ b/rsf-design/src/utils/ui/iconify-loader.js
@@ -0,0 +1,163 @@
+import { addCollection } from '@iconify/vue/offline'
+import { LOCAL_ICON_COLLECTIONS } from '../../plugins/iconify.collections.js'
+
+const FULL_ICON_COLLECTION_LOADERS = Object.freeze({
+ fluent: () => import('@iconify-json/fluent').then((module) => module.icons),
+ 'icon-park-outline': () =>
+ import('@iconify-json/icon-park-outline').then((module) => module.icons),
+ iconamoon: () => import('@iconify-json/iconamoon').then((module) => module.icons),
+ ix: () => import('@iconify-json/ix').then((module) => module.icons),
+ 'line-md': () => import('@iconify-json/line-md').then((module) => module.icons),
+ ri: () => import('@iconify-json/ri').then((module) => module.icons),
+ solar: () => import('@iconify-json/solar').then((module) => module.icons),
+ 'svg-spinners': () => import('@iconify-json/svg-spinners').then((module) => module.icons),
+ 'system-uicons': () => import('@iconify-json/system-uicons').then((module) => module.icons),
+ vaadin: () => import('@iconify-json/vaadin').then((module) => module.icons)
+})
+
+const fullyRegisteredPrefixes = new Set()
+const pendingPrefixLoads = new Map()
+
+function parseIconName(icon) {
+ if (typeof icon !== 'string') {
+ return null
+ }
+
+ const normalizedIcon = icon.trim()
+ if (!normalizedIcon) {
+ return null
+ }
+
+ const separatorIndex = normalizedIcon.indexOf(':')
+ if (separatorIndex <= 0 || separatorIndex >= normalizedIcon.length - 1) {
+ return null
+ }
+
+ return {
+ prefix: normalizedIcon.slice(0, separatorIndex),
+ name: normalizedIcon.slice(separatorIndex + 1)
+ }
+}
+
+function hasBundledIcon(icon) {
+ const parsedIcon = parseIconName(icon)
+ if (!parsedIcon) {
+ return false
+ }
+
+ const collection = LOCAL_ICON_COLLECTIONS[parsedIcon.prefix]
+ if (!collection) {
+ return false
+ }
+
+ return Boolean(collection.icons?.[parsedIcon.name] || collection.aliases?.[parsedIcon.name])
+}
+
+function loadFullIconCollection(prefix) {
+ if (fullyRegisteredPrefixes.has(prefix)) {
+ return Promise.resolve(true)
+ }
+
+ const currentTask = pendingPrefixLoads.get(prefix)
+ if (currentTask) {
+ return currentTask
+ }
+
+ const loader = FULL_ICON_COLLECTION_LOADERS[prefix]
+ if (!loader) {
+ return Promise.resolve(false)
+ }
+
+ const loadTask = loader()
+ .then((collection) => {
+ addCollection(collection)
+ fullyRegisteredPrefixes.add(prefix)
+ pendingPrefixLoads.delete(prefix)
+ return true
+ })
+ .catch((error) => {
+ pendingPrefixLoads.delete(prefix)
+ throw error
+ })
+
+ pendingPrefixLoads.set(prefix, loadTask)
+ return loadTask
+}
+
+function collectRuntimeIcons(source, iconNames = new Set()) {
+ if (!Array.isArray(source)) {
+ return iconNames
+ }
+
+ source.forEach((item) => {
+ if (!item || typeof item !== 'object') {
+ return
+ }
+
+ const icon = item.meta?.icon || item.icon
+ if (typeof icon === 'string' && icon.includes(':') && !hasBundledIcon(icon)) {
+ iconNames.add(icon)
+ }
+
+ if (Array.isArray(item.children) && item.children.length > 0) {
+ collectRuntimeIcons(item.children, iconNames)
+ }
+ })
+
+ return iconNames
+}
+
+function scheduleIdleTask(task, delay = 0) {
+ const invoke = () => {
+ if (globalThis.requestIdleCallback) {
+ globalThis.requestIdleCallback(task, { timeout: 1000 })
+ return
+ }
+ setTimeout(task, 0)
+ }
+
+ if (delay > 0) {
+ setTimeout(invoke, delay)
+ return
+ }
+
+ invoke()
+}
+
+async function ensureIconRegistered(icon) {
+ const parsedIcon = parseIconName(icon)
+ if (!parsedIcon) {
+ return false
+ }
+
+ if (hasBundledIcon(icon) || fullyRegisteredPrefixes.has(parsedIcon.prefix)) {
+ return true
+ }
+
+ return loadFullIconCollection(parsedIcon.prefix)
+}
+
+function warmRuntimeIcons(iconNames, delay = 120) {
+ const icons = [...new Set(Array.isArray(iconNames) ? iconNames : [])].filter(Boolean)
+ if (icons.length === 0) {
+ return
+ }
+
+ scheduleIdleTask(() => {
+ icons.forEach((icon) => {
+ void ensureIconRegistered(icon)
+ })
+ }, delay)
+}
+
+function warmMenuIcons(menuList, delay = 120) {
+ warmRuntimeIcons([...collectRuntimeIcons(menuList)], delay)
+}
+
+export {
+ collectRuntimeIcons,
+ ensureIconRegistered,
+ hasBundledIcon,
+ warmMenuIcons,
+ warmRuntimeIcons
+}
--
Gitblit v1.9.1