chore: 初始化平芝126kV隔离开关MES_Manage_View项目
This commit is contained in:
151
src/icons/generate-icon-gallery.js
Normal file
151
src/icons/generate-icon-gallery.js
Normal file
@@ -0,0 +1,151 @@
|
||||
"use strict";
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const iconsDir = path.resolve(__dirname, "svg");
|
||||
const outFile = path.resolve(__dirname, "gallery.html");
|
||||
|
||||
if (!fs.existsSync(iconsDir)) {
|
||||
console.error(`SVG directory not found: ${iconsDir}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const entries = fs.readdirSync(iconsDir, { withFileTypes: true })
|
||||
.filter(d => d.isFile() && d.name.toLowerCase().endsWith(".svg"))
|
||||
.map(d => ({ name: d.name, size: fs.statSync(path.join(iconsDir, d.name)).size }))
|
||||
.sort((a, b) => a.name.localeCompare(b.name, "zh", { sensitivity: "base", numeric: true }));
|
||||
|
||||
const empty = entries.filter(e => e.size === 0);
|
||||
const nonEmpty = entries.filter(e => e.size > 0);
|
||||
|
||||
const escapeHtml = (s) => String(s)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/\"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
|
||||
function renderCard(file, kind) {
|
||||
const display = file.name.replace(/\.svg$/i, "");
|
||||
const safe = escapeHtml(display);
|
||||
const dataName = display.toLowerCase();
|
||||
const src = "svg/" + encodeURIComponent(file.name);
|
||||
if (kind === 'empty') {
|
||||
return `\n <div class="card empty" data-name="${escapeHtml(dataName)}">\n <div class="preview placeholder"></div>\n <div class="name" title="${safe}">${safe}</div>\n </div>`;
|
||||
}
|
||||
return `\n <div class="card" data-name="${escapeHtml(dataName)}">\n <div class="preview"><img loading="lazy" src="${src}" alt="${safe}" onerror="this.closest('div.card').classList.add('error')"></div>\n <div class="name" title="${safe}">${safe}</div>\n </div>`;
|
||||
}
|
||||
|
||||
const rowsNonEmpty = nonEmpty.map(f => renderCard(f, 'icon')).join("");
|
||||
const rowsEmpty = empty.map(f => renderCard(f, 'empty')).join("");
|
||||
|
||||
const html = `<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>SVG 图标预览</title>
|
||||
<style>
|
||||
:root { --gap: 12px; --size: 64px; --border: #e5e7eb; --text: #111827; --muted: #6b7280; --error: #ef4444; --checker-a:#e5e7eb; --checker-b:#ffffff; }
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, "Noto Sans", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; color: var(--text); }
|
||||
header { position: sticky; top: 0; background: #fff; border-bottom: 1px solid var(--border); padding: 14px 16px; display: flex; align-items: center; gap: 12px; z-index: 10; }
|
||||
h1 { margin: 0; font-size: 16px; font-weight: 600; }
|
||||
.search { flex: 1; }
|
||||
.search input { width: 100%; padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 14px; }
|
||||
.count { font-size: 12px; color: var(--muted); white-space: nowrap; }
|
||||
main { padding: 16px; }
|
||||
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--gap); }
|
||||
.card { border: 1px solid var(--border); border-radius: 12px; padding: 12px; display: flex; flex-direction: column; align-items: center; gap: 10px; background: #fff; }
|
||||
.preview { width: var(--size); height: var(--size); border-radius: 10px; display: flex; align-items: center; justify-content: center; background: repeating-conic-gradient(var(--checker-a) 0 25%, var(--checker-b) 0 50%) 50% / 12px 12px; }
|
||||
.preview img { max-width: 100%; max-height: 100%; filter: drop-shadow(0 0 1px rgba(0,0,0,.45)) drop-shadow(0 0 2px rgba(0,0,0,.25)); }
|
||||
.name { text-align: center; font-size: 12px; color: var(--muted); width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.card.error { border-color: var(--error); }
|
||||
.card.error .name { color: var(--error); }
|
||||
.card.empty { border-color: #f59e0b; }
|
||||
.card.empty .preview { background: repeating-conic-gradient(#fef3c7 0 25%, #fff7ed 0 50%) 50% / 12px 12px; }
|
||||
footer { padding: 16px; color: var(--muted); text-align: center; font-size: 12px; }
|
||||
.toolbar { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; }
|
||||
.size-input { width: 120px; }
|
||||
select, button, label.switch { border: 1px solid var(--border); background: #fff; padding: 6px 8px; border-radius: 6px; }
|
||||
label.switch { display: inline-flex; align-items: center; gap: 6px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>SVG 图标预览</h1>
|
||||
<div class="toolbar">
|
||||
<label>大小: <input class="size-input" type="range" min="24" max="160" value="64"></label>
|
||||
<label>背景:
|
||||
<select id="bg">
|
||||
<option value="checker" selected>棋盘</option>
|
||||
<option value="white">白色</option>
|
||||
<option value="gray">浅灰</option>
|
||||
<option value="dark">深色</option>
|
||||
</select>
|
||||
</label>
|
||||
<label class="switch"><input id="toggleEmpty" type="checkbox"> 显示空文件(${empty.length})</label>
|
||||
</div>
|
||||
<div class="search"><input id="q" type="search" placeholder="搜索图标名称...(支持中英文)" autofocus></div>
|
||||
<div class="count"><span id="shown"></span>/<span id="total"></span></div>
|
||||
</header>
|
||||
<main>
|
||||
<div id="grid" class="grid">${rowsNonEmpty}${rowsEmpty}\n </div>
|
||||
</main>
|
||||
<footer>共 ${nonEmpty.length} 个有效图标,${empty.length} 个空文件。默认隐藏空文件,你可在工具栏勾选显示。</footer>
|
||||
<script>
|
||||
const q = document.getElementById('q');
|
||||
const grid = document.getElementById('grid');
|
||||
const cards = Array.from(grid.querySelectorAll('.card'));
|
||||
const total = document.getElementById('total');
|
||||
const shown = document.getElementById('shown');
|
||||
const bg = document.getElementById('bg');
|
||||
const toggleEmpty = document.getElementById('toggleEmpty');
|
||||
total.textContent = String(cards.length);
|
||||
|
||||
function applyFilter() {
|
||||
const term = q.value.trim().toLowerCase();
|
||||
let visible = 0;
|
||||
for (const el of cards) {
|
||||
const isEmpty = el.classList.contains('empty');
|
||||
const matches = !term || el.dataset.name.includes(term);
|
||||
const show = matches && (toggleEmpty.checked || !isEmpty);
|
||||
el.style.display = show ? '' : 'none';
|
||||
if (show) visible++;
|
||||
}
|
||||
shown.textContent = String(visible);
|
||||
}
|
||||
q.addEventListener('input', applyFilter);
|
||||
toggleEmpty.addEventListener('change', applyFilter);
|
||||
applyFilter();
|
||||
|
||||
const sizeInput = document.querySelector('.size-input');
|
||||
function applySize() { document.documentElement.style.setProperty('--size', sizeInput.value + 'px'); }
|
||||
sizeInput.addEventListener('input', applySize);
|
||||
applySize();
|
||||
|
||||
function applyBg() {
|
||||
const v = bg.value;
|
||||
if (v === 'checker') {
|
||||
document.documentElement.style.setProperty('--checker-a', '#e5e7eb');
|
||||
document.documentElement.style.setProperty('--checker-b', '#ffffff');
|
||||
} else if (v === 'white') {
|
||||
document.documentElement.style.setProperty('--checker-a', '#ffffff');
|
||||
document.documentElement.style.setProperty('--checker-b', '#ffffff');
|
||||
} else if (v === 'gray') {
|
||||
document.documentElement.style.setProperty('--checker-a', '#e5e7eb');
|
||||
document.documentElement.style.setProperty('--checker-b', '#e5e7eb');
|
||||
} else if (v === 'dark') {
|
||||
document.documentElement.style.setProperty('--checker-a', '#111827');
|
||||
document.documentElement.style.setProperty('--checker-b', '#1f2937');
|
||||
}
|
||||
}
|
||||
bg.addEventListener('change', applyBg);
|
||||
applyBg();
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const utf8NoBom = new (require('util').TextEncoder)();
|
||||
fs.writeFileSync(outFile, html, { encoding: "utf8" });
|
||||
console.log(`Generated: ${outFile} with ${nonEmpty.length} icons and ${empty.length} empty files`);
|
||||
Reference in New Issue
Block a user