fix: add explicit admin sign-in entry

This commit is contained in:
2026-09-15 06:44:30 +08:00
parent 68e3d0bfce
commit 528db25833
+3 -3
View File
@@ -2,12 +2,12 @@
<html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>{{ .site_title }}</title><link rel="stylesheet" href="/static/css/tonav.css"></head>
<body class="app-shell">
<div class="app-layout">
<aside class="sidebar"><a class="brand" href="/">{{ .site_title }}</a><div class="sidebar-section"><div class="section-label">SERVICES</div><button class="nav-item active" data-category="all">All <span id="allCount"></span></button><div id="categoryNav"></div></div><div class="sidebar-footer"><a href="/admin/dashboard">Administration</a></div></aside>
<main class="main"><header class="topbar"><div><div class="eyebrow">SERVICES</div><h1>Service directory</h1></div><div class="top-actions"><button class="icon-button" id="themeBtn" title="Toggle theme">◐</button><a class="admin-link" href="/admin/dashboard">Admin</a></div></header>
<aside class="sidebar"><a class="brand" href="/">{{ .site_title }}</a><div class="sidebar-section"><div class="section-label">SERVICES</div><button class="nav-item active" data-category="all">All <span id="allCount"></span></button><div id="categoryNav"></div></div><div class="sidebar-footer"><a href="/admin/login">Admin sign in <span>↗</span></a></div></aside>
<main class="main"><header class="topbar"><div><div class="eyebrow">SERVICES</div><h1>Service directory</h1></div><div class="top-actions"><button class="icon-button" id="themeBtn" title="Toggle theme">◐</button><a class="admin-link" href="/admin/login">Sign in</a></div></header>
<div class="toolbar"><label class="search"><span>⌕</span><input id="searchInput" placeholder="Search services, tags, descriptions…" autocomplete="off"><kbd>/</kbd></label><div class="result-count" id="resultCount"></div></div>
<section class="service-list" id="servicesGrid"><div class="empty-state">Loading…</div></section>
<footer class="page-footer"><span>ToNav</span><span id="lastCheckTime"></span></footer></main></div>
<script>const categoriesData={{ .categories_json }};const servicesData={{ .services_json }};let currentTab='all',currentKeyword='';const map={};categoriesData.forEach(c=>map[c.id]=c.name);const esc=s=>{const d=document.createElement('div');d.textContent=s||'';return d.innerHTML};
function renderNav(){const n=document.getElementById('categoryNav');document.getElementById('allCount').textContent=servicesData.length;n.innerHTML=categoriesData.map(c=>`<button class="nav-item" data-category="${esc(c.name)}">${esc(c.name)} <span>${servicesData.filter(s=>s.category_id===c.id).length}</span></button>`).join('');document.querySelectorAll('.nav-item').forEach(b=>b.onclick=()=>{currentTab=b.dataset.category;document.querySelectorAll('.nav-item').forEach(x=>x.classList.toggle('active',x.dataset.category===currentTab));render()})}
function render(){let a=currentTab==='all'?servicesData:servicesData.filter(s=>map[s.category_id]===currentTab);if(currentKeyword)a=a.filter(s=>(s.name+' '+(s.description||'')+' '+(s.tags||'')).toLowerCase().includes(currentKeyword));document.getElementById('resultCount').textContent=`${a.length} services`;document.getElementById('servicesGrid').innerHTML=a.length?a.map(s=>`<a class="service-row" href="${esc(s.url)}" target="_blank" rel="noopener"><span class="service-icon">${esc(s.icon)||'↗'}</span><span class="service-main"><strong>${esc(s.name)}</strong><span>${esc(s.description||s.url)}</span></span><span class="service-meta"><span class="status ${s.status==='online'?'online':s.status==='offline'?'offline':''}"></span>${esc(map[s.category_id]||'Uncategorized')}</span><span class="service-arrow">→</span></a>`).join(''):'<div class="empty-state">No services found</div>'}
document.getElementById('searchInput').oninput=e=>{currentKeyword=e.target.value.toLowerCase().trim();render()};document.addEventListener('keydown',e=>{if(e.key==='/'&&document.activeElement.tagName!=='INPUT'){e.preventDefault();document.getElementById('searchInput').focus()}});document.getElementById('themeBtn').onclick=()=>document.documentElement.classList.toggle('dark');renderNav();render();document.getElementById('lastCheckTime').textContent=new Date().toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'});</script></body></html>
document.getElementById('searchInput').oninput=e=>{currentKeyword=e.target.value.toLowerCase().trim();render()};document.addEventListener('keydown',e=>{if(e.key==='/'&&document.activeElement.tagName!=='INPUT'){e.preventDefault();document.getElementById('searchInput').focus()}});document.getElementById('themeBtn').onclick=()=>{document.documentElement.classList.toggle('dark');localStorage.setItem('tonav-theme',document.documentElement.classList.contains('dark')?'dark':'light')};if(localStorage.getItem('tonav-theme')==='dark')document.documentElement.classList.add('dark');renderNav();render();document.getElementById('lastCheckTime').textContent=new Date().toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'});</script></body></html>