feat: 新增图标选择器组件及相关功能;更新路由配置和类型定义;修复依赖地址

This commit is contained in:
2025-12-30 17:41:51 +07:00
parent 17f8082240
commit 2eab7c5365
9 changed files with 696 additions and 18 deletions

149
src/utils/icon-loader.ts Normal file
View File

@@ -0,0 +1,149 @@
import type { IconifyJSON } from '@iconify/types';
import materialSymbolsIcons from '@iconify-json/material-symbols/icons.json';
import cryptoCurrencyIcons from '@iconify-json/cryptocurrency-color/icons.json';
/**
* 图标集缓存
*/
interface IconCache {
/** 图标名称列表 */
icons: string[];
/** 图标别名映射 */
aliases: Record<string, string>;
/** 加载时间戳 */
timestamp: number;
}
const iconCacheMap = new Map<string, IconCache>();
/**
* 加载 Material Symbols 图标集
* @returns 图标名称数组
*/
export function loadMaterialSymbolsIcons(): string[] {
const collectionName = 'material-symbols';
// 返回缓存的图标
if (iconCacheMap.has(collectionName)) {
const cache = iconCacheMap.get(collectionName)!;
return cache.icons;
}
try {
const iconSet = materialSymbolsIcons as unknown as IconifyJSON;
// 获取所有图标名称
const icons = Object.keys(iconSet.icons || {});
// 处理别名
const aliases: Record<string, string> = {};
if (iconSet.aliases) {
Object.entries(iconSet.aliases).forEach(([alias, config]) => {
if (typeof config === 'object' && 'parent' in config) {
aliases[alias] = config.parent;
}
});
}
// 缓存结果
iconCacheMap.set(collectionName, {
icons,
aliases,
timestamp: Date.now()
});
return icons;
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to load material symbols icons:', error);
return [];
}
}
/**
* 加载 cryptocurrency-color 图标集
* @returns 图标名称数组
*/
export function loadCryptoCurrencyIcons(): string[] {
const collectionName = 'cryptocurrency-color';
// 返回缓存的图标
if (iconCacheMap.has(collectionName)) {
const cache = iconCacheMap.get(collectionName)!;
return cache.icons;
}
try {
const iconSet = cryptoCurrencyIcons as IconifyJSON;
// 获取所有图标名称
const icons = Object.keys(iconSet.icons || {});
// 缓存结果
iconCacheMap.set(collectionName, {
icons,
aliases: {},
timestamp: Date.now()
});
return icons;
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to load material icon theme icons:', error);
return [];
}
}
/**
* 通用图标集加载器
* @param collectionName 图标集名称,如 'material-symbols'
* @returns 图标名称数组
*/
export function loadIconCollection(collectionName: string): string[] {
// 根据图标集名称调用对应的加载函数
switch (collectionName) {
case 'material-symbols':
return loadMaterialSymbolsIcons();
case 'cryptocurrency-color':
return loadCryptoCurrencyIcons();
default:
// eslint-disable-next-line no-console
console.error(`Unknown icon collection: ${collectionName}`);
return [];
}
}
/**
* 搜索图标
* @param icons 图标列表
* @param keyword 搜索关键词
* @returns 匹配的图标列表
*/
export function searchIcons(icons: string[], keyword: string): string[] {
if (!keyword.trim()) return icons;
const lowerKeyword = keyword.toLowerCase();
return icons.filter(icon => icon.toLowerCase().includes(lowerKeyword));
}
/**
* 清除图标缓存
* @param collectionName 可选,指定清除的图标集,不传则清除所有
*/
export function clearIconCache(collectionName?: string): void {
if (collectionName) {
iconCacheMap.delete(collectionName);
} else {
iconCacheMap.clear();
}
}
/**
* 获取图标完整路径
* @param collection 图标集名称
* @param iconName 图标名称
* @returns 完整图标路径,如 'material-symbols:home'
*/
export function getIconPath(collection: string, iconName: string): string {
return `${collection}:${iconName}`;
}