feat(backend): 公开页自适应满屏 + 主题切换对齐 App ThemePickerPill
- 页面 flex 撑满视口(100dvh):页眉贴顶、页脚贴底、信息区弹性填充, 底部不再留大片空白;内容超屏时自然滚动(移动端上下滑不受影响) - 主题切换从 ◐ 循环钮改为与 App 一致的衬衫图标 pill + 下拉单选 (A·经典蓝 / B·琥珀 / C·酒窖,勾选态),图标 path 取自原型 icons.js #i-shirt Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
@@ -36,7 +36,9 @@
|
||||
--glow1:rgba(124,31,44,.05); --glow2:rgba(181,134,47,.04); --seal-bg:rgba(255,253,248,.78);
|
||||
}
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
html{background:var(--bg);height:100%;}
|
||||
body{
|
||||
min-height:100%;
|
||||
background-color:var(--bg);
|
||||
background-image:
|
||||
radial-gradient(circle at 12% 0%, var(--glow1), transparent 38%),
|
||||
@@ -44,9 +46,11 @@
|
||||
color:var(--text);
|
||||
font:var(--fs-title)/1.75 var(--font);
|
||||
-webkit-font-smoothing:antialiased;
|
||||
-webkit-tap-highlight-color:transparent;
|
||||
transition:background-color .25s,color .25s;
|
||||
}
|
||||
.page{max-width:560px;margin:0 auto;padding:0 16px 40px;}
|
||||
/* 自适应满屏:页眉贴顶、页脚贴底、中间信息弹性填充;内容超屏时自然滚动 */
|
||||
.page{max-width:560px;margin:0 auto;padding:0 16px 24px;min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;}
|
||||
a{color:var(--primary);text-decoration:none;}
|
||||
|
||||
/* 顶部题签 */
|
||||
@@ -56,11 +60,29 @@
|
||||
border-bottom:1px solid var(--border);position:relative;
|
||||
}
|
||||
.mast a{color:var(--primary-dark);font-weight:700;letter-spacing:.3em;}
|
||||
/* 主题选择器:与 App ThemePickerPill 同构(衬衫图标 + 主题名 + ▾ + 下拉单选) */
|
||||
.thm{
|
||||
position:absolute;right:0;top:50%;transform:translateY(-58%);width:30px;height:30px;
|
||||
position:absolute;right:0;top:50%;transform:translateY(-58%);
|
||||
display:flex;align-items:center;gap:6px;height:30px;padding:0 11px;
|
||||
border-radius:var(--r-pill);border:1px solid var(--border);background:var(--surface);
|
||||
color:var(--muted);font-size:14px;line-height:1;cursor:pointer;
|
||||
color:var(--text);font-size:var(--fs-sm);font-family:var(--font);cursor:pointer;letter-spacing:0;
|
||||
}
|
||||
.thm svg{width:15px;height:15px;stroke:var(--muted);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
|
||||
.thm svg.cv{width:13px;height:13px;}
|
||||
.thm-menu{
|
||||
position:absolute;right:0;top:calc(100% + 6px);z-index:50;min-width:136px;padding:4px;
|
||||
background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
|
||||
box-shadow:0 4px 14px var(--shadow);
|
||||
}
|
||||
.thm-menu[hidden]{display:none;}
|
||||
.thm-menu button{
|
||||
display:flex;align-items:center;gap:4px;width:100%;height:36px;padding:0 10px;
|
||||
border:none;background:none;color:var(--text);font-size:var(--fs-body);
|
||||
font-family:var(--font);cursor:pointer;border-radius:4px;text-align:left;
|
||||
}
|
||||
.thm-menu button:hover{background:var(--brand50);}
|
||||
.thm-menu button.on{color:var(--primary);font-weight:600;}
|
||||
.thm-menu .ck{width:16px;color:var(--primary);font-weight:700;flex:none;}
|
||||
|
||||
/* 图片区(永远存在)+ 右上「正品」章(--accent 酒红) */
|
||||
.hero{margin:18px 0 0;position:relative;animation:rise .5s ease both;}
|
||||
@@ -123,8 +145,8 @@
|
||||
.desc{padding:13px 2px;font-size:14px;color:var(--text);white-space:pre-wrap;text-align:justify;}
|
||||
.more{display:block;text-align:center;padding:12px 0 10px;font-size:13.5px;font-weight:600;border-top:1px solid var(--border-subtle);}
|
||||
|
||||
/* 页脚 */
|
||||
.foot{margin-top:30px;text-align:center;color:var(--muted);font-size:var(--fs-sm);line-height:2;animation:rise .5s ease .18s both;}
|
||||
/* 页脚:flex 撑到视口底部 */
|
||||
.foot{margin-top:auto;padding-top:30px;text-align:center;color:var(--muted);font-size:var(--fs-sm);line-height:2;animation:rise .5s ease .18s both;}
|
||||
.foot-rule{display:flex;align-items:center;gap:12px;margin-bottom:8px;color:var(--border);}
|
||||
.foot-rule::before,.foot-rule::after{content:"";height:1px;background:var(--border);flex:1;}
|
||||
.foot a{color:var(--muted);}
|
||||
@@ -149,7 +171,18 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<header class="mast"><a href="https://jiu.51yanmei.com">岩美酒库</a><button class="thm" id="thm" aria-label="切换主题">◐</button></header>
|
||||
<header class="mast"><a href="https://jiu.51yanmei.com">岩美酒库</a>
|
||||
<button class="thm" id="thm" aria-label="切换主题">
|
||||
<svg viewBox="0 0 24 24"><path d="M20.38 3.46 16 2a4 4 0 0 1-8 0L3.62 3.46a2 2 0 0 0-1.34 2.23l.58 3.47a1 1 0 0 0 .99.84H6v10c0 1.1.9 2 2 2h8a2 2 0 0 0 2-2V10h2.15a1 1 0 0 0 .99-.84l.58-3.47a2 2 0 0 0-1.34-2.23z"/></svg>
|
||||
<span id="thmName">经典蓝</span>
|
||||
<svg class="cv" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
|
||||
</button>
|
||||
<div class="thm-menu" id="thmMenu" hidden>
|
||||
<button data-t="a"><span class="ck"></span>A · 经典蓝</button>
|
||||
<button data-t="b"><span class="ck"></span>B · 琥珀</button>
|
||||
<button data-t="c"><span class="ck"></span>C · 酒窖</button>
|
||||
</div>
|
||||
</header>
|
||||
{{if .Found}}
|
||||
<div class="hero">
|
||||
<div class="frame">
|
||||
@@ -234,14 +267,27 @@
|
||||
</div>
|
||||
<script>
|
||||
(function(){
|
||||
var order=['a','b','c'],root=document.documentElement,btn=document.getElementById('thm');
|
||||
if(!btn)return;
|
||||
btn.addEventListener('click',function(){
|
||||
var cur=root.getAttribute('data-theme')||'a',
|
||||
next=order[(order.indexOf(cur)+1)%order.length];
|
||||
if(next==='a')root.removeAttribute('data-theme');else root.setAttribute('data-theme',next);
|
||||
try{localStorage.setItem('jiu-pub-theme',next);}catch(e){}
|
||||
});
|
||||
var NAMES={a:'经典蓝',b:'琥珀',c:'酒窖'},root=document.documentElement,
|
||||
btn=document.getElementById('thm'),menu=document.getElementById('thmMenu'),
|
||||
label=document.getElementById('thmName');
|
||||
if(!btn||!menu)return;
|
||||
var opts=[].slice.call(menu.children);
|
||||
function cur(){return root.getAttribute('data-theme')||'a';}
|
||||
function paint(){
|
||||
label.textContent=NAMES[cur()];
|
||||
opts.forEach(function(b){var on=b.getAttribute('data-t')===cur();
|
||||
b.className=on?'on':'';b.querySelector('.ck').textContent=on?'✓':'';});
|
||||
}
|
||||
btn.addEventListener('click',function(e){e.stopPropagation();menu.hidden=!menu.hidden;});
|
||||
opts.forEach(function(b){b.addEventListener('click',function(e){
|
||||
e.stopPropagation();
|
||||
var t=b.getAttribute('data-t');
|
||||
if(t==='a')root.removeAttribute('data-theme');else root.setAttribute('data-theme',t);
|
||||
try{localStorage.setItem('jiu-pub-theme',t);}catch(err){}
|
||||
paint();menu.hidden=true;
|
||||
});});
|
||||
document.addEventListener('click',function(){menu.hidden=true;});
|
||||
paint();
|
||||
})();
|
||||
</script>
|
||||
{{if .Images}}
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
--glow1:rgba(124,31,44,.05); --glow2:rgba(181,134,47,.04);
|
||||
}
|
||||
*{box-sizing:border-box;margin:0;padding:0;}
|
||||
html{background:var(--bg);height:100%;}
|
||||
body{
|
||||
min-height:100%;
|
||||
background-color:var(--bg);
|
||||
background-image:
|
||||
radial-gradient(circle at 12% 0%, var(--glow1), transparent 38%),
|
||||
@@ -42,9 +44,11 @@
|
||||
color:var(--text);
|
||||
font:var(--fs-title)/1.7 var(--font);
|
||||
-webkit-font-smoothing:antialiased;
|
||||
-webkit-tap-highlight-color:transparent;
|
||||
transition:background-color .25s,color .25s;
|
||||
}
|
||||
.page{max-width:560px;margin:0 auto;padding:0 16px 40px;}
|
||||
/* 自适应满屏:页眉贴顶、页脚贴底、中间信息弹性填充;内容超屏时自然滚动 */
|
||||
.page{max-width:560px;margin:0 auto;padding:0 16px 24px;min-height:100vh;min-height:100dvh;display:flex;flex-direction:column;}
|
||||
a{color:var(--primary);text-decoration:none;}
|
||||
|
||||
.mast{
|
||||
@@ -53,11 +57,29 @@
|
||||
border-bottom:1px solid var(--border);position:relative;
|
||||
}
|
||||
.mast a{color:var(--primary-dark);font-weight:700;letter-spacing:.3em;}
|
||||
/* 主题选择器:与 App ThemePickerPill 同构(衬衫图标 + 主题名 + ▾ + 下拉单选) */
|
||||
.thm{
|
||||
position:absolute;right:0;top:50%;transform:translateY(-58%);width:30px;height:30px;
|
||||
position:absolute;right:0;top:50%;transform:translateY(-58%);
|
||||
display:flex;align-items:center;gap:6px;height:30px;padding:0 11px;
|
||||
border-radius:var(--r-pill);border:1px solid var(--border);background:var(--surface);
|
||||
color:var(--muted);font-size:14px;line-height:1;cursor:pointer;
|
||||
color:var(--text);font-size:var(--fs-sm);font-family:var(--font);cursor:pointer;letter-spacing:0;
|
||||
}
|
||||
.thm svg{width:15px;height:15px;stroke:var(--muted);fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;}
|
||||
.thm svg.cv{width:13px;height:13px;}
|
||||
.thm-menu{
|
||||
position:absolute;right:0;top:calc(100% + 6px);z-index:50;min-width:136px;padding:4px;
|
||||
background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);
|
||||
box-shadow:0 4px 14px var(--shadow);
|
||||
}
|
||||
.thm-menu[hidden]{display:none;}
|
||||
.thm-menu button{
|
||||
display:flex;align-items:center;gap:4px;width:100%;height:36px;padding:0 10px;
|
||||
border:none;background:none;color:var(--text);font-size:var(--fs-body);
|
||||
font-family:var(--font);cursor:pointer;border-radius:4px;text-align:left;letter-spacing:0;text-indent:0;
|
||||
}
|
||||
.thm-menu button:hover{background:var(--brand50);}
|
||||
.thm-menu button.on{color:var(--primary);font-weight:600;}
|
||||
.thm-menu .ck{width:16px;color:var(--primary);font-weight:700;flex:none;}
|
||||
|
||||
/* 店铺题名 */
|
||||
.shop{text-align:center;padding:24px 0 4px;animation:rise .5s ease both;}
|
||||
@@ -110,7 +132,7 @@
|
||||
.empty h2{font-size:17px;margin-bottom:8px;color:var(--heading);}
|
||||
.empty p{color:var(--muted);font-size:var(--fs-body);}
|
||||
|
||||
.foot{margin-top:30px;text-align:center;color:var(--muted);font-size:var(--fs-sm);line-height:2;}
|
||||
.foot{margin-top:auto;padding-top:30px;text-align:center;color:var(--muted);font-size:var(--fs-sm);line-height:2;}
|
||||
.foot-rule{display:flex;align-items:center;gap:12px;margin-bottom:8px;color:var(--border);}
|
||||
.foot-rule::before,.foot-rule::after{content:"";height:1px;background:var(--border);flex:1;}
|
||||
.foot a{color:var(--muted);}
|
||||
@@ -131,7 +153,18 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<header class="mast"><a href="https://jiu.51yanmei.com">岩美酒库</a><button class="thm" id="thm" aria-label="切换主题">◐</button></header>
|
||||
<header class="mast"><a href="https://jiu.51yanmei.com">岩美酒库</a>
|
||||
<button class="thm" id="thm" aria-label="切换主题">
|
||||
<svg viewBox="0 0 24 24"><path d="M20.38 3.46 16 2a4 4 0 0 1-8 0L3.62 3.46a2 2 0 0 0-1.34 2.23l.58 3.47a1 1 0 0 0 .99.84H6v10c0 1.1.9 2 2 2h8a2 2 0 0 0 2-2V10h2.15a1 1 0 0 0 .99-.84l.58-3.47a2 2 0 0 0-1.34-2.23z"/></svg>
|
||||
<span id="thmName">经典蓝</span>
|
||||
<svg class="cv" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>
|
||||
</button>
|
||||
<div class="thm-menu" id="thmMenu" hidden>
|
||||
<button data-t="a"><span class="ck"></span>A · 经典蓝</button>
|
||||
<button data-t="b"><span class="ck"></span>B · 琥珀</button>
|
||||
<button data-t="c"><span class="ck"></span>C · 酒窖</button>
|
||||
</div>
|
||||
</header>
|
||||
{{if .Found}}
|
||||
<div class="shop">
|
||||
{{if .LogoURL}}<img src="{{.LogoURL}}" alt="{{.ShopName}}" decoding="async">{{end}}
|
||||
@@ -184,14 +217,27 @@
|
||||
</div>
|
||||
<script>
|
||||
(function(){
|
||||
var order=['a','b','c'],root=document.documentElement,btn=document.getElementById('thm');
|
||||
if(!btn)return;
|
||||
btn.addEventListener('click',function(){
|
||||
var cur=root.getAttribute('data-theme')||'a',
|
||||
next=order[(order.indexOf(cur)+1)%order.length];
|
||||
if(next==='a')root.removeAttribute('data-theme');else root.setAttribute('data-theme',next);
|
||||
try{localStorage.setItem('jiu-pub-theme',next);}catch(e){}
|
||||
});
|
||||
var NAMES={a:'经典蓝',b:'琥珀',c:'酒窖'},root=document.documentElement,
|
||||
btn=document.getElementById('thm'),menu=document.getElementById('thmMenu'),
|
||||
label=document.getElementById('thmName');
|
||||
if(!btn||!menu)return;
|
||||
var opts=[].slice.call(menu.children);
|
||||
function cur(){return root.getAttribute('data-theme')||'a';}
|
||||
function paint(){
|
||||
label.textContent=NAMES[cur()];
|
||||
opts.forEach(function(b){var on=b.getAttribute('data-t')===cur();
|
||||
b.className=on?'on':'';b.querySelector('.ck').textContent=on?'✓':'';});
|
||||
}
|
||||
btn.addEventListener('click',function(e){e.stopPropagation();menu.hidden=!menu.hidden;});
|
||||
opts.forEach(function(b){b.addEventListener('click',function(e){
|
||||
e.stopPropagation();
|
||||
var t=b.getAttribute('data-t');
|
||||
if(t==='a')root.removeAttribute('data-theme');else root.setAttribute('data-theme',t);
|
||||
try{localStorage.setItem('jiu-pub-theme',t);}catch(err){}
|
||||
paint();menu.hidden=true;
|
||||
});});
|
||||
document.addEventListener('click',function(){menu.hidden=true;});
|
||||
paint();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user