Files
pengzhan.dev/views/partials/admin-header.ejs
T
haopengzhan 95a7dcb93b feat(admin): add ephemeral staging DB, read-only posts overview, and dynamic search
- Implement ephemeral staging mode (APP_ENV=staging) to isolate test/dev DB writes in /tmp
- Add read-only posts management dashboard under /guanli/posts with live links and comment counters
- Add hot re-indexing endpoint (/guanli/reindex) to refresh Markdown without restarting server
- Replace static recommended search config with dynamic frequency-based trending searches
- Remove early scaffold mockup file (dropbox/zh.md) and clean legacy mock test queries
- Add native Makefile with dev, dev-persistent, test, lint, and docker targets
- Update test suite and documentation for development workflows
2026-09-16 23:09:14 -07:00

63 lines
3.9 KiB
Plaintext

<div class="admin-header-wrapper" style="margin-bottom: 2.5rem; border-bottom: 1px solid var(--color-border); padding-bottom: 1.5rem;">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; margin-bottom: 1.75rem;">
<div>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<span style="font-size: 1.5rem;">⚙️</span>
<h1 style="font-size: 1.8rem; margin: 0; font-family: var(--font-serif); font-weight: 700;">Site Administration</h1>
</div>
<p style="color: var(--color-text-secondary); margin: 0.25rem 0 0 0; font-size: 0.92rem;">Unified control panel for comments moderation, SEO health, and search logs.</p>
</div>
<!-- Admin Navigation Tabs -->
<div style="display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap;">
<a href="/guanli/posts" class="btn <%= activeAdminTab === 'posts' ? 'btn-primary' : 'btn-secondary' %>" style="padding: 0.45rem 0.95rem; font-size: 0.88rem;">
📝 Posts
</a>
<a href="/guanli/comments" class="btn <%= activeAdminTab === 'comments' ? 'btn-primary' : 'btn-secondary' %>" style="padding: 0.45rem 0.95rem; font-size: 0.88rem;">
💬 Comments
<% if (stats && stats.pendingComments > 0) { %>
<span style="background: #ef4444; color: white; padding: 1px 6px; border-radius: 9999px; font-size: 0.72rem; margin-left: 0.35rem; font-weight: 700;"><%= stats.pendingComments %></span>
<% } %>
</a>
<a href="/guanli/seo" class="btn <%= activeAdminTab === 'seo' ? 'btn-primary' : 'btn-secondary' %>" style="padding: 0.45rem 0.95rem; font-size: 0.88rem;">
📊 SEO Health
</a>
<a href="/guanli/search" class="btn <%= activeAdminTab === 'search' ? 'btn-primary' : 'btn-secondary' %>" style="padding: 0.45rem 0.95rem; font-size: 0.88rem;">
🔍 Search Analytics
</a>
<a href="/guanli/logout" class="btn btn-secondary" style="padding: 0.45rem 0.85rem; font-size: 0.88rem; color: #b91c1c;" title="Sign Out">
Sign Out 🚪
</a>
</div>
</div>
<!-- Unified KPI Cards -->
<% if (typeof stats !== 'undefined') { %>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; margin-top: 1.5rem;">
<div class="admin-kpi-card">
<div style="font-size: 0.8rem; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;">Published Posts</div>
<div style="font-size: 1.6rem; font-family: var(--font-serif); font-weight: 700; margin-top: 0.25rem;"><%= stats.totalPosts %></div>
</div>
<div class="admin-kpi-card <%= stats.pendingComments > 0 ? 'has-pending' : '' %>">
<div class="<%= stats.pendingComments > 0 ? 'kpi-title-pending' : 'kpi-title-default' %>" style="font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;">Pending Moderation</div>
<div class="<%= stats.pendingComments > 0 ? 'kpi-value-pending' : '' %>" style="font-size: 1.6rem; font-family: var(--font-serif); font-weight: 700; margin-top: 0.25rem;"><%= stats.pendingComments %></div>
</div>
<div class="admin-kpi-card">
<div style="font-size: 0.8rem; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;">Approved Comments</div>
<div class="kpi-value-approved" style="font-size: 1.6rem; font-family: var(--font-serif); font-weight: 700; margin-top: 0.25rem;"><%= stats.approvedComments %></div>
</div>
<div class="admin-kpi-card">
<div style="font-size: 0.8rem; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600;">Search Queries Logged</div>
<div style="font-size: 1.6rem; font-family: var(--font-serif); font-weight: 700; margin-top: 0.25rem;"><%= stats.totalSearches %></div>
</div>
</div>
<% } %>
</div>