Files
shell-gen/templates/index.html
T
cnbug 319f683a16 Initial commit: 50 shell-script generators with web UI
- 8 categories / 50 generators covering middleware, databases, runtimes,
  systemd services, system tools, network, monitoring, security
- VNC supports XFCE / GNOME / KDE Plasma / MATE / LXQt desktops
- Node.js versions 18-26 (incl. current LTS 24 Krypton and current 26)
- Live preview, copy / download / multi-script bundle in web UI
- Distro-aware (Ubuntu/Debian/CentOS/RHEL/Rocky/Alma/Fedora)
- All 50 generators pass bash -n syntax check
- Zero pip dependencies (Flask stdlib only)
2026-08-04 00:36:35 +08:00

73 lines
2.9 KiB
HTML

{% extends "base.html" %}
{% block title %}Shell-Gen · 首页{% endblock %}
{% block body %}
<main class="container">
<section class="hero">
<h1>选择需要部署的服务</h1>
<p class="lead">填写参数,实时生成可立即执行的 bash 脚本。所有脚本会先做 distro 检测
(Ubuntu/Debian/CentOS/RHEL/Rocky/Alma) 再安装,不会破坏现有服务。</p>
<div class="stats">
<div class="stat"><div class="num">{{ total }}</div><div class="lbl">生成器</div></div>
{% for cat in all_cats %}
{% set n = all_cats|length %}
{% endfor %}
<div class="stat"><div class="num">{{ categories|length }}</div><div class="lbl">分类</div></div>
<div class="stat"><div class="num">100%</div><div class="lbl">开源</div></div>
</div>
</section>
{% for cat in categories %}
<section class="cat-section" id="cat-{{ cat }}">
<h2><span class="cat-icon">{{ category_icons.get(cat, '📦') }}</span> {{ category_labels.get(cat, cat) }}</h2>
<div class="grid">
{% for gid, gen in (request.application_generator_items if false else []) %}{% endfor %}
{# Render via Python loop using all generators grouped by cat #}
{% for gid, gen in [] %}{% endfor %}
</div>
<div class="grid" data-cat="{{ cat }}">
{# Render in JS to keep templating simple #}
</div>
</section>
{% endfor %}
<section class="cat-section">
<h2>📚 全部生成器</h2>
<div class="grid" id="all-grid"></div>
</section>
</main>
<script>
fetch("/api/categories").then(r => r.json()).then(d => {
// populate per-category sections
for (const cat of d.categories) {
const target = document.querySelector(`#cat-${cat.id} .grid[data-cat]`);
if (target) target.innerHTML = cat.items.map(renderCard).join('');
}
// populate "全部生成器"
const all = d.categories.flatMap(c => c.items);
document.getElementById("all-grid").innerHTML = all.map(renderCard).join('');
});
function renderCard(g) {
const tags = (g.tags || []).slice(0, 4).map(t => `<span class="tag">${escapeHtml(t)}</span>`).join('');
const os = (g.os || []).slice(0, 3).map(t => `<span class="os">${escapeHtml(t)}</span>`).join('');
return `
<a class="card" href="/gen/${g.id}">
<div class="card-icon">${g.icon || '📦'}</div>
<div class="card-title">${escapeHtml(g.title)}</div>
<div class="card-desc">${escapeHtml(g.description)}</div>
<div class="card-meta">
<div class="tags">${tags}</div>
<div class="oss">${os}</div>
</div>
</a>`;
}
function escapeHtml(s) {
return String(s).replace(/[&<>"']/g, c => ({
'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'
}[c]));
}
</script>
{% endblock %}