主要改动 - templates/public/base.html - 增加 3 套响应式断点:≤900px(平板)、≤600px(手机)、≤360px(小屏) - topbar 在小屏下压缩 padding/字号,actions 自适应换行 - grid 卡片在手机端最小 160px,小屏单列 - 卡片字号、间距在手机端缩放 - 增加 sticky 分类目录条占位 - 增加回到顶部按钮(滚动后显示) - 增加暗色模式 CSS(prefers-color-scheme + data-theme 手动覆盖)和主题切换按钮 - 补充 theme-color、viewport 等移动端 meta - templates/public/index.html - 输出 5 个分类的 sticky 目录导航(点击锚点跳转) - 每个 section 设置 id=cat-N 锚点 - 卡片 title/url 增加 title 提示 - templates/public/category.html - 目录条加返回首页 + 当前分类名 - section 锚点统一为 cat-detail 验证 - curl 抓取 /site/ 响应 200,HTML 中 10 项响应式/交互特性检查全部通过 - 服务器本地运行无异常
345 lines
13 KiB
HTML
345 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
|
<meta name="theme-color" content="#16baaa">
|
|
<meta name="format-detection" content="telephone=no">
|
|
<title>{% block title %}{{ site_name|default('BWStudio · 导航') }}{% endblock %}</title>
|
|
<meta name="description" content="BWStudio 公开导航聚合页:精选开发工具、AI、设计资源、效率工具等优质站点。">
|
|
<meta property="og:title" content="{{ site_name|default('BWStudio · 导航') }}">
|
|
<meta property="og:description" content="精选优质站点,按分类聚合展示。">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/layui@2.9.7/dist/css/layui.css">
|
|
<style>
|
|
:root {
|
|
--brand: #16baaa;
|
|
--brand-2: #2e8de8;
|
|
--bg: #f5f7fa;
|
|
--card-bg: #ffffff;
|
|
--text: #2c3e50;
|
|
--text-muted: #6c7a89;
|
|
--text-soft: #b0bac3;
|
|
--border: #e8eef0;
|
|
--topbar-text: #ffffff;
|
|
--shadow: 0 2px 12px rgba(0,0,0,0.06);
|
|
--shadow-hover: 0 8px 24px rgba(22, 186, 170, 0.18);
|
|
}
|
|
/* 暗色模式(手动覆盖 / 系统跟随) */
|
|
[data-theme="dark"] {
|
|
--bg: #0f1419;
|
|
--card-bg: #1a1f29;
|
|
--text: #e6edf3;
|
|
--text-muted: #8b949e;
|
|
--text-soft: #6e7681;
|
|
--border: #2d333b;
|
|
--topbar-text: #ffffff;
|
|
--shadow: 0 2px 12px rgba(0,0,0,0.4);
|
|
--shadow-hover: 0 8px 24px rgba(22, 186, 170, 0.25);
|
|
}
|
|
@media (prefers-color-scheme: dark) {
|
|
:root:not([data-theme="light"]) {
|
|
--bg: #0f1419;
|
|
--card-bg: #1a1f29;
|
|
--text: #e6edf3;
|
|
--text-muted: #8b949e;
|
|
--text-soft: #6e7681;
|
|
--border: #2d333b;
|
|
--shadow: 0 2px 12px rgba(0,0,0,0.4);
|
|
--shadow-hover: 0 8px 24px rgba(22, 186, 170, 0.25);
|
|
}
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
html { -webkit-text-size-adjust: 100%; }
|
|
body {
|
|
margin: 0;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
font-size: 15px;
|
|
line-height: 1.5;
|
|
transition: background-color 0.2s, color 0.2s;
|
|
}
|
|
|
|
/* ===== Topbar ===== */
|
|
.topbar {
|
|
background: linear-gradient(135deg, var(--brand) 0%, var(--brand-2) 100%);
|
|
color: var(--topbar-text);
|
|
padding: 56px 0 40px;
|
|
position: relative;
|
|
}
|
|
.topbar .container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
|
|
.topbar h1 { font-size: 36px; margin: 0 0 8px; font-weight: 600; line-height: 1.2; }
|
|
.topbar .sub { font-size: 15px; opacity: 0.92; }
|
|
.topbar .actions { margin-top: 18px; display: flex; flex-wrap: wrap; gap: 8px; }
|
|
.topbar .actions a, .topbar .actions button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 6px 14px;
|
|
background: rgba(255,255,255,0.18);
|
|
border: 1px solid rgba(255,255,255,0.35);
|
|
color: var(--topbar-text);
|
|
border-radius: 999px;
|
|
font-size: 13px;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
transition: background 0.2s;
|
|
font-family: inherit;
|
|
}
|
|
.topbar .actions a:hover, .topbar .actions button:hover { background: rgba(255,255,255,0.32); }
|
|
|
|
.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
|
|
|
|
/* ===== 分类目录条(横向滚动) ===== */
|
|
.cat-nav {
|
|
background: var(--card-bg);
|
|
border-bottom: 1px solid var(--border);
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 10;
|
|
backdrop-filter: saturate(180%) blur(8px);
|
|
-webkit-backdrop-filter: saturate(180%) blur(8px);
|
|
}
|
|
.cat-nav-inner {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 8px 24px;
|
|
display: flex;
|
|
gap: 6px;
|
|
overflow-x: auto;
|
|
scrollbar-width: thin;
|
|
scroll-behavior: smooth;
|
|
}
|
|
.cat-nav-inner::-webkit-scrollbar { height: 4px; }
|
|
.cat-nav-inner::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
|
|
.cat-nav a {
|
|
flex-shrink: 0;
|
|
padding: 6px 14px;
|
|
border-radius: 999px;
|
|
font-size: 13px;
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
transition: all 0.15s;
|
|
white-space: nowrap;
|
|
}
|
|
.cat-nav a:hover { background: rgba(22,186,170,0.1); color: var(--brand); }
|
|
.cat-nav a.active { background: var(--brand); color: #fff; }
|
|
|
|
/* ===== Section ===== */
|
|
.section { margin: 32px 0; scroll-margin-top: 70px; }
|
|
.section-header {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
margin-bottom: 16px;
|
|
border-left: 4px solid var(--brand);
|
|
padding-left: 12px;
|
|
}
|
|
.section-header h2 { font-size: 20px; margin: 0; font-weight: 600; }
|
|
.section-header .meta { font-size: 13px; color: var(--text-muted); }
|
|
|
|
/* ===== Grid ===== */
|
|
.grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
gap: 16px;
|
|
}
|
|
.card {
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 10px;
|
|
padding: 18px;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
box-shadow: var(--shadow);
|
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
|
display: flex; flex-direction: column; gap: 6px;
|
|
min-width: 0;
|
|
}
|
|
.card:hover {
|
|
transform: translateY(-3px);
|
|
box-shadow: var(--shadow-hover);
|
|
border-color: var(--brand);
|
|
}
|
|
.card:active { transform: translateY(0); } /* 移动端点击反馈 */
|
|
.card .title-row { display: flex; align-items: center; gap: 10px; min-width: 0; }
|
|
.card .icon-wrap {
|
|
width: 36px; height: 36px;
|
|
background: rgba(22, 186, 170, 0.1);
|
|
color: var(--brand);
|
|
border-radius: 8px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
font-size: 18px;
|
|
flex-shrink: 0;
|
|
}
|
|
.card .title {
|
|
font-size: 15px; font-weight: 600; color: var(--text);
|
|
flex: 1; min-width: 0;
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
}
|
|
.card .desc {
|
|
font-size: 13px; color: var(--text-muted);
|
|
line-height: 1.5;
|
|
overflow: hidden;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
min-height: 38px;
|
|
}
|
|
.card .url {
|
|
font-size: 12px; color: var(--text-soft);
|
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
direction: rtl;
|
|
text-align: left;
|
|
}
|
|
.empty {
|
|
text-align: center; padding: 48px 0; color: var(--text-muted);
|
|
}
|
|
|
|
footer.site-footer {
|
|
margin-top: 48px; padding: 24px 0;
|
|
text-align: center; color: var(--text-muted); font-size: 13px;
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
footer.site-footer a { color: var(--brand); text-decoration: none; }
|
|
|
|
/* ===== 回到顶部 ===== */
|
|
.to-top {
|
|
position: fixed;
|
|
right: 20px; bottom: 20px;
|
|
width: 42px; height: 42px;
|
|
background: var(--brand);
|
|
color: #fff;
|
|
border-radius: 50%;
|
|
display: flex; align-items: center; justify-content: center;
|
|
cursor: pointer;
|
|
box-shadow: var(--shadow-hover);
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
transition: all 0.2s;
|
|
pointer-events: none;
|
|
z-index: 20;
|
|
border: none;
|
|
font-size: 18px;
|
|
}
|
|
.to-top.visible { opacity: 1; transform: translateY(0); pointer-events: auto; }
|
|
|
|
/* ===== 响应式:平板 ===== */
|
|
@media (max-width: 900px) {
|
|
.grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
|
|
.topbar h1 { font-size: 30px; }
|
|
}
|
|
|
|
/* ===== 响应式:手机 ===== */
|
|
@media (max-width: 600px) {
|
|
body { font-size: 14px; }
|
|
.container { padding: 0 14px; }
|
|
.topbar { padding: 32px 0 28px; }
|
|
.topbar .container { padding: 0 14px; }
|
|
.topbar h1 { font-size: 24px; }
|
|
.topbar .sub { font-size: 13px; }
|
|
.topbar .actions a, .topbar .actions button { padding: 5px 11px; font-size: 12px; }
|
|
.cat-nav-inner { padding: 6px 14px; }
|
|
.cat-nav a { padding: 5px 11px; font-size: 12px; }
|
|
.section { margin: 22px 0; scroll-margin-top: 60px; }
|
|
.section-header h2 { font-size: 17px; }
|
|
.section-header .meta { font-size: 12px; }
|
|
.grid {
|
|
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
|
gap: 10px;
|
|
}
|
|
.card { padding: 12px; border-radius: 8px; }
|
|
.card .title { font-size: 14px; }
|
|
.card .desc { font-size: 12px; min-height: 32px; }
|
|
.card .icon-wrap { width: 30px; height: 30px; font-size: 16px; }
|
|
.to-top { right: 14px; bottom: 14px; width: 38px; height: 38px; }
|
|
}
|
|
@media (max-width: 360px) {
|
|
.grid { grid-template-columns: 1fr; }
|
|
}
|
|
</style>
|
|
{% block extra_head %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<header class="topbar">
|
|
<div class="container">
|
|
<h1>{{ site_name|default('BWStudio · 导航') }}</h1>
|
|
<div class="sub">{% block subtitle %}精选优质站点,按分类聚合展示 · 共 {{ total|default(0) }} 个链接{% endblock %}</div>
|
|
<div class="actions">
|
|
<a href="{{ url_for('public_nav.index') }}">🏠 首页</a>
|
|
<a href="/admin/login">🔐 登录后台</a>
|
|
<button type="button" id="theme-toggle" title="切换主题" aria-label="切换主题">🌗 主题</button>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
{% block cat_nav %}{% endblock %}
|
|
|
|
<main class="container">
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
<footer class="site-footer">
|
|
© 2026 BWStudio · 基于 <a href="https://gitea.bwhome.top/bwadmin/pear-admin-flask">Pear Admin Flask</a> 构建
|
|
</footer>
|
|
|
|
<button class="to-top" id="to-top" aria-label="回到顶部" title="回到顶部">↑</button>
|
|
|
|
{% block extra_js %}{% endblock %}
|
|
<script>
|
|
// 暗色模式:localStorage > data-theme > 系统
|
|
(function(){
|
|
var saved = localStorage.getItem('bw-theme');
|
|
if (saved === 'dark' || saved === 'light') {
|
|
document.documentElement.setAttribute('data-theme', saved);
|
|
}
|
|
var btn = document.getElementById('theme-toggle');
|
|
if (btn) {
|
|
btn.addEventListener('click', function(){
|
|
var cur = document.documentElement.getAttribute('data-theme');
|
|
var sysDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
var isDark = cur ? (cur === 'dark') : sysDark;
|
|
var next = isDark ? 'light' : 'dark';
|
|
document.documentElement.setAttribute('data-theme', next);
|
|
localStorage.setItem('bw-theme', next);
|
|
});
|
|
}
|
|
// 回到顶部
|
|
var top = document.getElementById('to-top');
|
|
if (top) {
|
|
window.addEventListener('scroll', function(){
|
|
if (window.scrollY > 400) top.classList.add('visible');
|
|
else top.classList.remove('visible');
|
|
});
|
|
top.addEventListener('click', function(){
|
|
window.scrollTo({top: 0, behavior: 'smooth'});
|
|
});
|
|
}
|
|
// 目录高亮当前 section
|
|
var navLinks = document.querySelectorAll('.cat-nav a[href^="#"]');
|
|
if (navLinks.length) {
|
|
var sections = [];
|
|
navLinks.forEach(function(a){
|
|
var id = a.getAttribute('href').slice(1);
|
|
var el = document.getElementById(id);
|
|
if (el) sections.push({link: a, el: el});
|
|
});
|
|
function onScroll(){
|
|
var y = window.scrollY + 100;
|
|
var active = sections[0];
|
|
for (var i = 0; i < sections.length; i++) {
|
|
if (sections[i].el.offsetTop <= y) active = sections[i];
|
|
}
|
|
navLinks.forEach(function(a){ a.classList.remove('active'); });
|
|
if (active) active.link.classList.add('active');
|
|
}
|
|
window.addEventListener('scroll', onScroll, {passive: true});
|
|
onScroll();
|
|
}
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html> |