Files
drawlogo/materials.html
T

458 lines
24 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="logo/favicon.svg">
<title>素材库 · 画个标</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: "PingFang SC", "Microsoft YaHei", "Segoe UI", sans-serif; font-size: 14px; color: #1f2937; background: #f3f4f6; min-height: 100vh; }
a { color: #4f46e5; text-decoration: none; }
a:hover { text-decoration: underline; }
.hidden { display: none !important; }
/* ===== 顶栏 ===== */
.topbar { display: flex; align-items: center; justify-content: space-between; padding: 0 20px; height: 54px; background: linear-gradient(90deg, #1e1b4b, #312e81); color: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.15); position: sticky; top: 0; z-index: 20; }
.topbar .brand { display: flex; align-items: center; gap: 10px; }
.topbar .brand .icon { font-size: 20px; }
.topbar .brand .name { font-size: 17px; font-weight: 700; letter-spacing: 1px; }
.topbar .brand .tag { font-size: 11px; color: #c7d2fe; background: rgba(255,255,255,.12); padding: 2px 8px; border-radius: 20px; }
.topbar .nav { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.topbar .nav a { color: #e0e7ff; font-size: 13px; padding: 6px 12px; border: 1px solid rgba(255,255,255,.35); border-radius: 6px; background: rgba(255,255,255,.1); transition: background .15s; }
.topbar .nav a:hover { background: rgba(255,255,255,.22); text-decoration: none; }
.topbar .nav a.active { background: #fff; color: #312e81; font-weight: 700; }
.wrap { max-width: 1180px; margin: 22px auto 60px; padding: 0 16px; }
/* ===== 统计 ===== */
.stats { display: flex; gap: 14px; flex-wrap: wrap; margin-bottom: 16px; }
.stat-card { flex: 1; min-width: 140px; background: #fff; border: 1px solid #e5e7eb; border-radius: 10px; padding: 12px 16px; box-shadow: 0 1px 3px rgba(0,0,0,.06); }
.stat-card .num { font-size: 24px; font-weight: 800; color: #4f46e5; }
.stat-card .lab { font-size: 12px; color: #6b7280; margin-top: 2px; }
/* ===== 工具栏(Tab + 搜索) ===== */
.toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.tchip { border: 1px solid #e5e7eb; background: #fff; color: #4b5563; padding: 7px 16px; border-radius: 20px; font-size: 13px; cursor: pointer; transition: all .15s; }
.tchip:hover { border-color: #c7d2fe; color: #4338ca; }
.tchip.active { background: #4f46e5; border-color: #4f46e5; color: #fff; }
.search { flex: 1; min-width: 220px; border: 1px solid #e5e7eb; border-radius: 8px; padding: 9px 12px; font-size: 13px; color: #1f2937; outline: none; }
.search:focus { border-color: #4f46e5; }
/* ===== 素材行 ===== */
.row { background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 14px 16px; margin-bottom: 12px; box-shadow: 0 1px 3px rgba(0,0,0,.06); transition: box-shadow .15s; }
.row:hover { box-shadow: 0 4px 14px rgba(79,70,229,.1); }
.row-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.row-name { font-size: 15px; font-weight: 700; }
.row-en { font-size: 11px; color: #9ca3af; }
.row-cat { font-size: 11px; padding: 2px 10px; border-radius: 20px; white-space: nowrap; }
.row-cat.icon { background: #dbeafe; color: #1d4ed8; }
.row-cat.emoji { background: #fef3c7; color: #b45309; }
.row-cat.brand { background: #e0e7ff; color: #4338ca; }
.row-cat.avatar{ background: #fce7f3; color: #be185d; }
.row-cat.palette { background: #dbeafe; color: #1d4ed8; }
.row-cat.font { background: #dcfce7; color: #15803d; }
.row-cat.bg { background: #e0e7ff; color: #4338ca; }
.row-cat.decoration { background: #fef3c7; color: #b45309; }
.row-count { font-size: 11px; color: #6b7280; margin-left: auto; }
.row-desc { font-size: 12px; color: #4b5563; line-height: 1.7; margin-top: 5px; }
.row-meta { font-size: 11px; color: #9ca3af; margin-top: 3px; }
/* ===== 缩略预览 ===== */
.thumbs { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; align-items: center; }
.thumb { width: 44px; height: 44px; border: 1px solid #e5e7eb; border-radius: 8px; background: #f9fafb; display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; }
.thumb svg { width: 26px; height: 26px; }
.thumb.avatar { width: 52px; height: 52px; border-radius: 50%; padding: 4px; }
.thumb.avatar svg { width: 100%; height: 100%; }
.thumb.svg-item { width: 56px; height: 56px; }
.thumb.svg-item svg { width: 100%; height: 100%; }
.swatch { width: 24px; height: 42px; border: 1px solid rgba(0,0,0,.08); border-radius: 5px; flex-shrink: 0; }
.font-sample { font-size: 15px; padding: 4px 10px; border: 1px solid #e5e7eb; border-radius: 8px; background: #f9fafb; color: #1f2937; min-width: 130px; }
.thumb.placeholder { color: #cbd5e1; font-size: 11px; }
/* ===== 更多 ===== */
.more-wrap { margin-top: 10px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.more-btn { border: 1px solid #c7d2fe; background: #eef2ff; color: #4338ca; padding: 5px 14px; border-radius: 16px; font-size: 12px; cursor: pointer; transition: all .15s; }
.more-btn:hover { background: #e0e7ff; }
.more-btn:disabled { opacity: .5; cursor: wait; }
.more-info { font-size: 11px; color: #9ca3af; }
.empty { text-align: center; color: #6b7280; padding: 60px 0; }
</style>
</head>
<body>
<!-- ===== 顶部工具栏 ===== -->
<header class="topbar">
<div class="brand">
<img class="icon" src="logo/logo-mark.svg" alt="画个标" width="20" height="20">
<span class="name">画个标</span>
<span class="tag">素材库</span>
</div>
<nav class="nav">
<a href="index.html" title="LOGO 设计工作台">🎨 LOGO</a>
<a href="avatar.html" title="头像设计工作台">🖼 头像</a>
<a href="poster.html" title="海报设计工作台">📰 海报</a>
<a href="skills.html" title="共享技能中心">🧩 技能中心</a>
<a href="poster-skills.html" title="海报技能中心">🧩 海报技能</a>
<a class="active" href="materials.html" title="素材库:按行预览 LOGO/头像/海报素材">🗃 素材库</a>
<a href="sources.html" title="图标素材中心(来源信息)">📚 素材中心</a>
<a href="poster-sources.html" title="海报素材中心(来源信息)">📚 海报素材</a>
</nav>
</header>
<div class="wrap">
<div class="stats">
<div class="stat-card"><div class="num" id="st-total">-</div><div class="lab">当前分组素材(类)</div></div>
<div class="stat-card"><div class="num" id="st-items">-</div><div class="lab">素材总数(个)</div></div>
</div>
<div class="toolbar">
<div class="tabs" id="tabs"></div>
<input class="search" id="search" placeholder="🔍 搜索素材(名称 / 类别 / 特性描述)">
</div>
<div id="list"></div>
<div class="empty hidden" id="empty">未找到匹配素材,请调整分类或搜索词。</div>
</div>
<script src="js/core/dicebear.js?v=20260822e"></script>
<script src="js/data/builtin-icons.js?v=20260823g"></script>
<script src="js/data/poster-builtin.js?v=20260823e"></script>
<script>
(function () {
'use strict';
/* ============ 工具 ============ */
function esc(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
function loadScript(src) {
return new Promise(function (res, rej) {
var s = document.createElement('script');
s.src = src; s.onload = res; s.onerror = function () { rej(new Error('加载失败 ' + src)); };
document.head.appendChild(s);
});
}
/* 描边型判断 + 渲染属性(与 sources.html 一致) */
var STROKE_SOURCES = new Set(['feather', 'lucide', 'tabler', 'iconoir']);
function isStroke(ic, sid) {
return STROKE_SOURCES.has(sid) || /stroke\s*=|\bstroke-linecap\s*=|\bstroke-linejoin\s*=/.test(ic && ic.svg || '');
}
function iconAttrs(ic, sid) {
if (ic.type && ic.type !== 'icon') return 'fill="inherit" stroke="inherit"';
return isStroke(ic, sid)
? 'fill="none" stroke="#4f46e5" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"'
: 'fill="#4f46e5" stroke="none"';
}
function bodyOf(ic) {
return ic.svg.replace(/fill="currentColor"/g, 'fill="inherit"').replace(/stroke="currentColor"/g, 'stroke="inherit"');
}
/* 从 palette data 递归提取全部 hex */
function collectHex(obj, out) {
if (!obj) return;
if (typeof obj === 'string') { if (/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(obj)) out.push(obj); return; }
if (Array.isArray(obj)) { for (var i = 0; i < obj.length; i++) collectHex(obj[i], out); return; }
for (var k in obj) collectHex(obj[k], out);
}
/* ============ 状态 ============ */
var TAB = 'logo'; // logo / avatar / poster
var kw = '';
var ICON_SRC = []; // LOGO 源(manifest)
var POSTER_SRC = []; // 海报源(manifest)
var BUILTIN = (typeof HGB_BuiltinIcons !== 'undefined') ? HGB_BuiltinIcons : null;
var PBUILTIN = window.HGB_PosterBuiltin || { sources: {} };
var DICE = (typeof HGB_Dicebear !== 'undefined') ? HGB_Dicebear : null;
var loadedCache = {}; // 已加载的数据文件
var fontSeq = 0;
var TYPE_CN = { icon: '单色图标', emoji: '多色表情', brand: '品牌标识' };
var POSTER_TYPE_CN = { palette: '配色', font: '字体', bg: '背景', decoration: '装饰' };
var CAT_CLS = { icon: 'icon', emoji: 'emoji', brand: 'brand', palette: 'palette', font: 'font', bg: 'bg', decoration: 'decoration', avatar: 'avatar' };
/* ============ Manifest 加载 ============ */
function loadIconManifest() {
return fetch('js/data/manifest/icons.json?v=20260823g')
.then(function (r) { return r.json(); })
.then(function (m) { ICON_SRC = m.sources || []; })
.catch(function () { ICON_SRC = window.HGB_IconSources || []; });
}
function loadPosterManifest() {
return fetch('js/data/manifest/posters.json?v=20260823e')
.then(function (r) { return r.json(); })
.then(function (m) { POSTER_SRC = m.sources || []; })
.catch(function () { POSTER_SRC = window.HGB_PosterSources || []; });
}
/* ============ 数据文件懒加载 ============ */
function loadIconData(id) {
if (loadedCache['i_' + id]) return loadedCache['i_' + id];
loadedCache['i_' + id] = loadScript('js/data/sources/' + id + '.js?v=20260823g')
.then(function () { return window['HGB_Source_' + id] || null; });
return loadedCache['i_' + id];
}
function loadPosterData(id) {
if (loadedCache['p_' + id]) return loadedCache['p_' + id];
loadedCache['p_' + id] = loadScript('js/data/posters/' + id + '.js?v=20260823e')
.then(function () { return window['HGB_PosterSource_' + id] || null; });
return loadedCache['p_' + id];
}
/* ============ 渲染 ============ */
var tabs = [
{ id: 'logo', name: '🖼️ LOGO 素材' },
{ id: 'avatar', name: '🧑‍🎨 头像素材' },
{ id: 'poster', name: '🎨 海报素材' }
];
function renderTabs() {
var counts = { logo: ICON_SRC.length, avatar: (DICE ? DICE.STYLES.length : 0), poster: POSTER_SRC.length };
document.getElementById('tabs').innerHTML = tabs.map(function (t) {
return '<button class="tchip ' + (TAB === t.id ? 'active' : '') + '" data-t="' + t.id + '">' + t.name + ' <span style="opacity:.7">' + counts[t.id] + '</span></button>';
}).join('');
document.querySelectorAll('#tabs [data-t]').forEach(function (b) {
b.addEventListener('click', function () { TAB = b.dataset.t; renderTabs(); render(); });
});
}
function renderStats() {
var total = 0, items = 0;
if (TAB === 'logo') {
total = ICON_SRC.length;
items = ICON_SRC.reduce(function (s, x) { return s + ((typeof x.count === 'number') ? x.count : ((BUILTIN && BUILTIN.sources[x.id]) ? BUILTIN.sources[x.id].count : 0)); }, 0);
} else if (TAB === 'avatar') {
total = DICE ? DICE.STYLES.length : 0;
items = total; // 每风格可确定性生成无限头像,按风格数计
} else {
total = POSTER_SRC.length;
items = POSTER_SRC.reduce(function (s, x) { return s + ((typeof x.count === 'number') ? x.count : ((PBUILTIN.sources[x.id] || {}).count || 0)); }, 0);
}
document.getElementById('st-total').textContent = total;
document.getElementById('st-items').textContent = (TAB === 'avatar') ? (total + ' 风格 · 无限生成') : items.toLocaleString();
}
function rowHead(name, en, cat, catCn, count, countText) {
return '<div class="row-top">' +
'<span class="row-name">' + esc(name) + '</span>' +
(en ? '<span class="row-en">' + esc(en) + '</span>' : '') +
'<span class="row-cat ' + (CAT_CLS[cat] || '') + '">' + esc(catCn || cat) + '</span>' +
'<span class="row-count">' + (countText || ('共 ' + count + ' 个')) + '</span>' +
'</div>';
}
/* ---- LOGO 行 ---- */
function iconRow(s) {
var srcData = BUILTIN && BUILTIN.sources[s.id];
var count = (typeof s.count === 'number') ? s.count : (srcData ? srcData.count : '—');
var samples = (srcData && srcData.samples ? srcData.samples.map(function (b) { return { svg: b, type: srcData.type }; }) : []);
var type = s.type || 'icon';
var html = '<div class="row" id="row-i-' + esc(s.id) + '">' +
rowHead(s.nameCn || s.name, s.name, type, TYPE_CN[type] || s.style, count) +
'<div class="row-desc">' + esc(s.desc || '') + '</div>' +
'<div class="row-meta">' + esc(s.style || '') + ' · ' + esc(s.coordText || '') + ' · ' + esc(s.variants || '') + '</div>' +
'<div class="thumbs">' + samples.map(function (ic) {
return '<div class="thumb" title="' + esc((s.nameCn || s.name)) + '"><svg viewBox="0 0 24 24" ' + iconAttrs(ic, s.id) + '>' + bodyOf(ic) + '</svg></div>';
}).join('') + '</div>' +
'<div class="more-wrap"><button class="more-btn" data-act="more" data-id="' + esc(s.id) + '">查看更多(共 ' + count + ' 个)</button><span class="more-info" id="mi-i-' + esc(s.id) + '"></span></div>' +
'</div>';
return html;
}
function iconMore(btn, id, count) {
btn.disabled = true;
loadIconData(id).then(function (def) {
btn.disabled = false;
if (!def || !def.icons || !def.icons.length) { btn.textContent = '暂无更多数据'; return; }
var icons = def.icons;
var shown = parseInt(btn.dataset.shown || '0', 10) || 0;
var LIMIT = 100;
var slice = icons.slice(shown, shown + LIMIT);
var box = btn.closest('.row').querySelector('.thumbs');
box.insertAdjacentHTML('beforeend', slice.map(function (ic) {
return '<div class="thumb" title="' + esc(ic.name || ic.id || '') + '"><svg viewBox="0 0 24 24" ' + iconAttrs(ic, id) + '>' + bodyOf(ic) + '</svg></div>';
}).join(''));
shown += slice.length;
var info = document.getElementById('mi-i-' + id);
if (info) info.textContent = '已显示 ' + shown + ' / 共 ' + icons.length + ' 个';
if (shown < icons.length) { btn.dataset.shown = shown; btn.textContent = '再加载 ' + Math.min(LIMIT, icons.length - shown) + ' 个'; }
else { btn.textContent = '已全部加载'; btn.disabled = true; }
}).catch(function () { btn.disabled = false; btn.textContent = '加载失败,点击重试'; });
}
/* ---- 头像行 ---- */
var AV_SEEDS = ['画个标', 'brand', 'sun', 'star', 'cat', 'wow', 'happy', 'cool', 'blue', 'red', 'green', 'code'];
function avatarRow(styleId) {
var cn = DICE.CN[styleId] || styleId;
var html = '<div class="row" id="row-a-' + esc(styleId) + '">' +
rowHead(cn, styleId, 'avatar', '头像风格', 0, '无限生成') +
'<div class="row-desc">DiceBear 确定性头像生成器:同一 seed 永远生成同一头像,风格可无限产出(' + esc(styleId) + ')。</div>' +
'<div class="row-meta">seed 驱动 · 浏览器本地渲染 · 中性与彩色变体</div>' +
'<div class="thumbs" id="th-a-' + esc(styleId) + '"><div class="thumb placeholder">加载中…</div></div>' +
'<div class="more-wrap"><button class="more-btn" data-act="amore" data-id="' + esc(styleId) + '">查看更多头像</button></div>' +
'</div>';
return html;
}
function avatarPreview(styleId, n) {
var box = document.getElementById('th-a-' + styleId);
if (!box) return;
if (!DICE) { box.innerHTML = '<div class="thumb placeholder">引擎缺失</div>'; return; }
var inner = AV_SEEDS.slice(0, n).map(function (seed) {
var r = DICE.renderAvatar(styleId, seed);
if (!r.svg) return '<div class="thumb placeholder">—</div>';
return '<div class="thumb avatar" title="seed: ' + esc(seed) + '">' + r.svg + '</div>';
}).join('');
box.innerHTML = inner;
}
/* ---- 海报行 ---- */
function posterRow(s) {
var meta = PBUILTIN.sources[s.id] || {};
var count = (typeof s.count === 'number') ? s.count : (meta.count || 0);
var html = '<div class="row" id="row-p-' + esc(s.id) + '">' +
rowHead(s.nameCn || s.name, s.name, s.type, POSTER_TYPE_CN[s.type] || s.type, count) +
'<div class="row-desc">' + esc(s.desc || '') + '</div>' +
'<div class="row-meta">' + esc(s.coordText || '') + ' · ' + esc(s.variants || '') + '</div>' +
'<div class="thumbs" id="th-p-' + esc(s.id) + '"><div class="thumb placeholder">加载中…</div></div>' +
'<div class="more-wrap"><button class="more-btn" data-act="pmore" data-id="' + esc(s.id) + '">查看更多(共 ' + count + ' 个)</button><span class="more-info" id="mi-p-' + esc(s.id) + '"></span></div>' +
'</div>';
return html;
}
function posterPreview(s, limit) {
var box = document.getElementById('th-p-' + s.id);
if (!box) return;
loadPosterData(s.id).then(function (def) {
if (!def || !def.items) { box.innerHTML = '<div class="thumb placeholder">无数据</div>'; return; }
var items = def.items;
if (s.type === 'palette') {
var hexes = [];
items.forEach(function (it) { collectHex(it.data, hexes); });
var shown = hexes.slice(0, limit);
box.innerHTML = shown.map(function (h) { return '<div class="swatch" title="' + esc(h) + '" style="background:' + h + '"></div>'; }).join('');
var info = document.getElementById('mi-p-' + s.id);
if (info) info.textContent = '共 ' + hexes.length + ' 色';
} else if (s.type === 'font') {
box.innerHTML = '';
items.slice(0, limit).forEach(function (it) {
renderFontSample(box, s.id, it);
});
} else { // bg / decoration
var slice = items.slice(0, limit);
box.innerHTML = slice.map(function (it) {
var vb = it.viewBox ? ' viewBox="' + it.viewBox + '"' : ' viewBox="0 0 ' + (it.width || 100) + ' ' + (it.height || 100) + '"';
return '<div class="thumb svg-item" title="' + esc(it.name || it.id || '') + '"><svg' + vb + ' xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">' + (it.svg || '') + '</svg></div>';
}).join('');
}
}).catch(function () { box.innerHTML = '<div class="thumb placeholder">加载失败</div>'; });
}
function renderFontSample(box, sid, it) {
var name = String(it.name || '字重').replace(/[_-]/g, ' ');
var holder = document.createElement('div');
holder.className = 'font-sample';
holder.textContent = name + ' — 画个标 123 ABC';
box.appendChild(holder);
var fam = 'mlfont' + (fontSeq++);
try {
var ff = new FontFace(fam, 'url(js/data/' + it.file + ')');
ff.load().then(function (f) {
document.fonts.add(f);
holder.style.fontFamily = '"' + fam + '", sans-serif';
}).catch(function () { holder.style.color = '#9ca3af'; });
} catch (e) { holder.style.color = '#9ca3af'; }
}
function posterMore(btn, s) {
btn.disabled = true;
loadPosterData(s.id).then(function (def) {
btn.disabled = false;
if (!def || !def.items) { btn.textContent = '暂无更多数据'; return; }
var items = def.items;
var n;
if (s.type === 'palette') { n = 9999; } // 色块轻量,全显
else if (s.type === 'font') { n = items.length; } // 字重少,全显
else { n = 60; } // SVG 上限 60,避免卡顿
posterPreview(s, n);
var info = document.getElementById('mi-p-' + s.id);
if (info) info.textContent = (s.type === 'palette') ? '全部色板已加载' : ('已显示 ' + Math.min(n, items.length) + ' / 共 ' + items.length + ' 个');
btn.textContent = '已全部加载';
btn.disabled = true;
}).catch(function () { btn.disabled = false; btn.textContent = '加载失败,点击重试'; });
}
/* ============ 主渲染 ============ */
function currentList() {
var kwl = kw.trim().toLowerCase();
if (TAB === 'logo') {
return ICON_SRC.filter(function (s) {
if (!kwl) return true;
return (s.nameCn || '').toLowerCase().includes(kwl) || (s.name || '').toLowerCase().includes(kwl) ||
(s.desc || '').toLowerCase().includes(kwl) || (s.id || '').toLowerCase().includes(kwl);
});
}
if (TAB === 'avatar') {
if (!DICE) return [];
return DICE.STYLES.filter(function (id) {
if (!kwl) return true;
var cn = DICE.CN[id] || '';
return cn.toLowerCase().includes(kwl) || id.toLowerCase().includes(kwl);
});
}
return POSTER_SRC.filter(function (s) {
if (!kwl) return true;
return (s.nameCn || '').toLowerCase().includes(kwl) || (s.name || '').toLowerCase().includes(kwl) ||
(s.desc || '').toLowerCase().includes(kwl) || (s.id || '').toLowerCase().includes(kwl) ||
(POSTER_TYPE_CN[s.type] || '').includes(kwl);
});
}
function render() {
var listEl = document.getElementById('list');
var empty = document.getElementById('empty');
renderStats();
var list = currentList();
if (!list.length) { listEl.innerHTML = ''; empty.classList.remove('hidden'); empty.textContent = '未找到匹配素材,请调整分类或搜索词。'; return; }
empty.classList.add('hidden');
if (TAB === 'logo') {
listEl.innerHTML = list.map(iconRow).join('');
// LOGO 行默认预览来自内置索引,无需异步
} else if (TAB === 'avatar') {
listEl.innerHTML = list.map(avatarRow).join('');
// 并发懒加载全部风格数据后批量渲染前 4 个预览
Promise.all(list.map(function (id) {
return DICE.loadStyle(id).catch(function () { return null; });
})).then(function () {
list.forEach(function (id) { avatarPreview(id, 4); });
});
} else {
listEl.innerHTML = list.map(posterRow).join('');
list.forEach(function (s) { posterPreview(s, 8); });
}
}
/* ============ 事件 ============ */
function onBtn(e) {
var btn = e.target.closest('[data-act]');
if (!btn) return;
var act = btn.dataset.act, id = btn.dataset.id;
if (act === 'more') {
var src = ICON_SRC.find(function (x) { return x.id === id; });
if (src) iconMore(btn, id, src.count);
} else if (act === 'amore') {
avatarPreview(id, 12);
btn.textContent = '已显示 12 个';
btn.disabled = true;
} else if (act === 'pmore') {
var ps = POSTER_SRC.find(function (x) { return x.id === id; });
if (ps) posterMore(btn, ps);
}
}
function init() {
document.getElementById('list').addEventListener('click', onBtn);
document.getElementById('search').addEventListener('input', function (e) { kw = e.target.value; render(); });
renderTabs();
render();
}
Promise.all([loadIconManifest(), loadPosterManifest()]).then(init).catch(init);
})();
</script>
</body>
</html>