feat(icons): 添加favicon模式,自动匹配图标

- 新增配置 icons.mode(manual | favicon),默认 favicon,未配置场景下自动生效
- 模板调用 t3.gstatic.com/faviconV2 获取站点图标;加载中显示旋转占位,失败回退至 Font Awesome 图标
- 新增 ifHttpUrl 与 encodeURIComponent,提升模板安全性与可读性
- 搜索索引优先读取 .icon-fallback,保证 favicon 模式下图标类名一致
- 样式新增 .favicon-icon 与 hover 效果,维持卡片观感一致性
This commit is contained in:
coolzr
2025-10-18 22:32:05 +08:00
parent 95398e074a
commit aa264cc727
6 changed files with 109 additions and 14 deletions

View File

@@ -53,7 +53,8 @@ window.MeNav = {
element.setAttribute('data-description', newData.description);
}
if (newData.icon) {
const iconElement = element.querySelector('i');
// 优先更新站点卡片中的回退图标favicon模式下存在
const iconElement = element.querySelector('i.icon-fallback') || element.querySelector('i');
if (iconElement) {
iconElement.className = newData.icon;
}
@@ -178,16 +179,41 @@ window.MeNav = {
newSite.setAttribute('data-icon', data.icon || 'fas fa-link');
newSite.setAttribute('data-description', data.description || '');
// 添加内容
newSite.innerHTML = `
<i class="${data.icon || 'fas fa-link'}"></i>
<h3>${data.name || '未命名站点'}</h3>
<p>${data.description || ''}</p>
`;
// 添加内容(根据图标模式渲染)
try {
const cfg = window.MeNav && typeof window.MeNav.getConfig === 'function' ? window.MeNav.getConfig() : null;
const iconsMode = (cfg && (cfg.data?.icons?.mode || cfg.icons?.mode)) || 'favicon';
if (iconsMode === 'favicon' && data.url && /^https?:\/\//i.test(data.url)) {
const faviconUrl = `https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${encodeURIComponent(data.url)}&size=32`;
newSite.innerHTML = `
<i class="fas fa-circle-notch fa-spin icon-placeholder" aria-hidden="true"></i>
<img class="favicon-icon" src="${faviconUrl}" alt="${(data.name || '站点')} favicon" loading="lazy" style="opacity:0;"
onload="this.style.opacity='1'; this.previousElementSibling.style.display='none';"
onerror="this.style.display='none'; this.previousElementSibling.style.display='none'; this.nextElementSibling.style.display='inline-block';" />
<i class="fas fa-link icon-fallback" aria-hidden="true" style="display:none;"></i>
<h3>${data.name || '未命名站点'}</h3>
<p>${data.description || ''}</p>
`;
} else {
newSite.innerHTML = `
<i class="${data.icon || 'fas fa-link'}"></i>
<h3>${data.name || '未命名站点'}</h3>
<p>${data.description || ''}</p>
`;
}
} catch (e) {
newSite.innerHTML = `
<i class="${data.icon || 'fas fa-link'}"></i>
<h3>${data.name || '未命名站点'}</h3>
<p>${data.description || ''}</p>
`;
}
// 添加到DOM
sitesGrid.appendChild(newSite);
// 移除"暂无网站"提示(如果存在)
const emptyMessage = sitesGrid.querySelector('.empty-sites');
if (emptyMessage) {
@@ -504,7 +530,7 @@ document.addEventListener('DOMContentLoaded', () => {
const title = card.querySelector('h3')?.textContent?.toLowerCase() || '';
const description = card.querySelector('p')?.textContent?.toLowerCase() || '';
const url = card.href || card.getAttribute('href') || '#';
const icon = card.querySelector('i')?.className || '';
const icon = card.querySelector('i.icon-fallback')?.className || card.querySelector('i')?.className || '';
// 将卡片信息添加到索引中
searchIndex.items.push({