孕妈广场五版效果稿演示页(demo/gc 汇总 + gc-v1~v5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
338
demo/gc-v1/index.html
Normal file
338
demo/gc-v1/index.html
Normal file
@@ -0,0 +1,338 @@
|
||||
<!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,viewport-fit=cover">
|
||||
<title>孕妈周刊 · 效果稿 V1</title>
|
||||
<!-- 效果稿 V1 · 孕妈周刊(杂志封面):广场列表页演示,独立页面,不接后端;数据读 guangchang/topics.js + data.js -->
|
||||
<style>
|
||||
:root{
|
||||
--paper:#F7F2EA;--paper-2:#EFE7DB;--ink:#221C18;--ink-2:#5E554E;--muted:#9B8F85;--rule:#D9CEC0;
|
||||
--brand:#F4593C;--fam:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
|
||||
--serif:"Songti SC","STSong","Noto Serif CJK SC","Source Han Serif SC","Noto Serif SC","SimSun",serif;
|
||||
--sans:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC",sans-serif;
|
||||
--st:env(safe-area-inset-top);
|
||||
}
|
||||
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
|
||||
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
|
||||
body{background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
|
||||
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
|
||||
a{color:inherit;text-decoration:none}
|
||||
img{display:block}
|
||||
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;background:var(--paper)}
|
||||
#sc::-webkit-scrollbar{display:none}
|
||||
|
||||
/* ---------- 顶栏(盖在封面上,滚动后变纸色) ---------- */
|
||||
.bar{position:sticky;top:0;z-index:30;height:calc(46px + var(--st));padding-top:var(--st);margin-bottom:calc(-46px - var(--st));
|
||||
display:flex;align-items:center;padding-left:6px;padding-right:12px;color:#fff;transition:background .25s,color .25s,box-shadow .25s}
|
||||
.bar.on{background:rgba(247,242,234,.94);color:var(--ink);box-shadow:0 1px 0 var(--rule);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
|
||||
.bar .bk{width:38px;height:38px;display:grid;place-items:center;border-radius:50%}
|
||||
.bar .bk svg{width:22px;height:22px}
|
||||
.bar .tt{flex:1;text-align:center;font-family:var(--serif);font-weight:700;font-size:16px;letter-spacing:4px;opacity:0;transition:opacity .25s;margin-right:-26px}
|
||||
.bar.on .tt{opacity:1}
|
||||
.bar .ver{font-size:11px;opacity:.75;letter-spacing:.5px;white-space:nowrap}
|
||||
|
||||
/* ---------- 封面 ---------- */
|
||||
.cover{position:relative;height:620px;overflow:hidden;background:#3a302a;color:#fff}
|
||||
.cover>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
|
||||
.cover::after{content:"";position:absolute;inset:0;background:
|
||||
linear-gradient(90deg,rgba(20,14,10,.5) 0,rgba(20,14,10,.18) 55%,rgba(20,14,10,0) 80%),
|
||||
linear-gradient(180deg,rgba(20,14,10,.55) 0,rgba(20,14,10,.12) 26%,rgba(20,14,10,.12) 40%,rgba(20,14,10,.42) 60%,rgba(20,14,10,.88) 100%)}
|
||||
.cv{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;padding:calc(50px + var(--st)) 20px 22px}
|
||||
.mast{display:flex;align-items:flex-end;justify-content:space-between;border-bottom:1px solid rgba(255,255,255,.55);padding-bottom:8px}
|
||||
.mast h1{margin:0;font-family:var(--serif);font-weight:900;font-size:50px;line-height:1;letter-spacing:6px;text-shadow:0 2px 14px rgba(0,0,0,.25)}
|
||||
.mast .iss{text-align:right;font-size:11px;line-height:1.5;letter-spacing:1px;opacity:.95}
|
||||
.mast .iss b{display:block;font-family:var(--serif);font-size:15px;letter-spacing:2px}
|
||||
.mast-sub{display:flex;justify-content:space-between;font-size:11px;letter-spacing:3px;margin-top:6px;opacity:.85}
|
||||
.cv .sp{flex:1}
|
||||
.lines{list-style:none;margin:0 0 18px;padding:0;width:58%}
|
||||
.lines li{margin-bottom:12px;padding-left:10px;border-left:2px solid var(--brand)}
|
||||
.lines li small{display:block;font-size:11px;letter-spacing:2px;opacity:.9;text-shadow:0 1px 4px rgba(0,0,0,.6)}
|
||||
.lines li span{display:block;font-family:var(--serif);font-weight:700;font-size:14px;line-height:1.4;text-shadow:0 1px 3px rgba(0,0,0,.55),0 0 12px rgba(0,0,0,.35)}
|
||||
.story .kick{display:inline-block;font-size:11px;letter-spacing:3px;padding:2px 8px;background:var(--brand);color:#fff;margin-bottom:10px}
|
||||
.story h2{margin:0;font-family:var(--serif);font-weight:900;font-size:29px;line-height:1.28;letter-spacing:1px;text-shadow:0 2px 12px rgba(0,0,0,.35)}
|
||||
.story p{margin:10px 0 0;font-size:13px;line-height:1.6;opacity:.9;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.story .by{margin-top:12px;display:flex;align-items:center;gap:8px;font-size:12px;opacity:.95}
|
||||
.story .by img{width:22px;height:22px;border-radius:50%;object-fit:cover;border:1px solid rgba(255,255,255,.7)}
|
||||
.story .by .rd{margin-left:auto;font-size:12px;letter-spacing:1px;border-bottom:1px solid rgba(255,255,255,.7)}
|
||||
|
||||
/* ---------- 栏目导航 ---------- */
|
||||
.secnav{position:sticky;top:calc(46px + var(--st));z-index:25;background:var(--paper);border-bottom:1px solid var(--ink);display:flex;padding:0 16px}
|
||||
.secnav button{flex:1;height:44px;font-size:14px;color:var(--muted);position:relative;letter-spacing:1px}
|
||||
.secnav button.on{color:var(--ink);font-weight:700}
|
||||
.secnav button.on::after{content:"";position:absolute;left:28%;right:28%;bottom:-1px;height:3px;background:var(--c,var(--brand))}
|
||||
|
||||
/* ---------- 通用版块标题 ---------- */
|
||||
.sec{padding:26px 20px 0}
|
||||
.hd{display:flex;align-items:baseline;gap:10px;border-top:3px double var(--ink);padding-top:12px;margin-bottom:6px}
|
||||
.hd h3{margin:0;font-family:var(--serif);font-weight:900;font-size:22px;letter-spacing:3px}
|
||||
.hd em{font-style:normal;font-size:11px;letter-spacing:2px;color:var(--muted);text-transform:uppercase}
|
||||
.hd .r{margin-left:auto;font-size:12px;color:var(--ink-2)}
|
||||
.lede{font-size:13px;color:var(--ink-2);margin:0 0 6px}
|
||||
|
||||
/* ---------- 目录 ---------- */
|
||||
.toc{list-style:none;margin:0;padding:0}
|
||||
.toc li{border-bottom:1px solid var(--rule)}
|
||||
.toc a{display:flex;gap:14px;padding:13px 0 12px;align-items:flex-start}
|
||||
.toc .no{font-family:Georgia,"Times New Roman",var(--serif);font-size:26px;line-height:1;font-style:italic;color:var(--c);width:34px;flex:none;padding-top:2px}
|
||||
.toc .bd{flex:1;min-width:0}
|
||||
.toc .col{font-size:11px;letter-spacing:2px;color:var(--c);font-weight:700}
|
||||
.toc .col i{font-style:normal;color:var(--muted);font-weight:400;letter-spacing:0;margin-left:6px}
|
||||
.toc .nm{font-family:var(--serif);font-weight:700;font-size:16px;line-height:1.4;margin-top:2px}
|
||||
.toc .mt{font-size:12px;color:var(--muted);margin-top:3px}
|
||||
.toc .hot{font-size:11px;color:var(--brand);border:1px solid var(--brand);padding:0 4px;margin-left:6px;letter-spacing:1px}
|
||||
.more{display:block;width:100%;margin-top:12px;height:40px;border:1px solid var(--ink);font-size:13px;letter-spacing:2px;color:var(--ink)}
|
||||
|
||||
/* ---------- 征稿启事 ---------- */
|
||||
.call{margin:26px 20px 0;border:1px solid var(--ink);padding:4px}
|
||||
.call .in{border:1px solid var(--ink);padding:16px 16px 14px;position:relative;background:#FBF8F2}
|
||||
.call .ti{text-align:center;font-family:var(--serif);font-weight:900;font-size:18px;letter-spacing:8px}
|
||||
.call .ti small{display:block;font-family:var(--sans);font-weight:400;font-size:11px;letter-spacing:3px;color:var(--muted);margin-top:2px}
|
||||
.call p{margin:10px 0 0;font-size:13px;color:var(--ink-2);line-height:1.7;text-align:justify}
|
||||
.call .pay{display:flex;justify-content:center;gap:0;margin:12px 0 2px;border-top:1px dashed var(--rule);border-bottom:1px dashed var(--rule)}
|
||||
.call .pay div{flex:1;text-align:center;padding:8px 0}
|
||||
.call .pay div+div{border-left:1px dashed var(--rule)}
|
||||
.call .pay b{display:block;font-family:Georgia,var(--serif);font-size:22px;color:var(--brand);line-height:1.2}
|
||||
.call .pay span{font-size:11px;color:var(--muted);letter-spacing:1px}
|
||||
.call .act{display:flex;gap:10px;margin-top:12px}
|
||||
.call .act a{flex:1;height:36px;display:grid;place-items:center;font-size:13px;letter-spacing:1px;border:1px solid var(--ink)}
|
||||
.call .act a.p{background:var(--ink);color:var(--paper)}
|
||||
.call .stamp{position:absolute;right:10px;top:10px;width:46px;height:46px;border:1.5px solid var(--brand);border-radius:50%;color:var(--brand);
|
||||
display:grid;place-items:center;font-size:11px;line-height:1.15;text-align:center;transform:rotate(-14deg);font-weight:700;opacity:.85}
|
||||
|
||||
/* ---------- 专栏 ---------- */
|
||||
.feat{display:block;margin-top:14px}
|
||||
.feat .ph{position:relative;aspect-ratio:4/3;overflow:hidden;background:var(--paper-2)}
|
||||
.feat .ph img{width:100%;height:100%;object-fit:cover}
|
||||
.feat .ph .tag{position:absolute;left:0;bottom:0;background:var(--paper);color:var(--c);font-size:11px;letter-spacing:2px;font-weight:700;padding:5px 10px 3px 0}
|
||||
.feat h4{margin:6px 0 0;font-family:var(--serif);font-weight:900;font-size:21px;line-height:1.38}
|
||||
.feat p{margin:8px 0 0;font-size:14px;color:var(--ink-2);line-height:1.7;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.feat p::first-letter{font-family:var(--serif);font-size:30px;float:left;line-height:1;margin:3px 6px 0 0;color:var(--c);font-weight:900}
|
||||
.by{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);margin-top:10px}
|
||||
.by img{width:20px;height:20px;border-radius:50%;object-fit:cover}
|
||||
.by .nm{color:var(--ink-2)}
|
||||
.by .lk{margin-left:auto;display:flex;align-items:center;gap:3px}
|
||||
.by .lk svg{width:13px;height:13px}
|
||||
.pair{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:20px;padding-top:18px;border-top:1px solid var(--rule)}
|
||||
.pair a{display:block;min-width:0}
|
||||
.pair .ph{aspect-ratio:3/4;overflow:hidden;background:var(--paper-2)}
|
||||
.pair img.cvr{width:100%;height:100%;object-fit:cover}
|
||||
.pair .col{font-size:11px;letter-spacing:2px;color:var(--c);font-weight:700;margin-top:8px}
|
||||
.pair h5{margin:3px 0 0;font-family:var(--serif);font-weight:700;font-size:15px;line-height:1.42;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.pair .by{margin-top:6px}
|
||||
.pair .by .lk{display:none}
|
||||
.quote{display:block;margin:22px 0 0;padding:22px 20px 18px;background:var(--paper-2);position:relative;border-top:3px solid var(--c)}
|
||||
.quote .mk{position:absolute;left:14px;top:-4px;font-family:Georgia,serif;font-size:64px;line-height:1;color:var(--c);opacity:.35}
|
||||
.quote q{display:block;quotes:none;font-family:var(--serif);font-weight:700;font-size:18px;line-height:1.65;letter-spacing:.5px;padding-left:8px}
|
||||
.quote .src{margin-top:12px;font-size:12px;color:var(--muted);text-align:right}
|
||||
.quote .src b{color:var(--ink-2);font-weight:400}
|
||||
.grp{margin-top:6px}
|
||||
.grp+.grp{margin-top:26px;padding-top:4px;border-top:1px solid var(--ink)}
|
||||
|
||||
.colo{margin:34px 20px 0;padding:16px 0 calc(28px + env(safe-area-inset-bottom));border-top:3px double var(--ink);text-align:center;font-size:11px;color:var(--muted);letter-spacing:1px;line-height:1.9}
|
||||
.colo b{display:block;font-family:var(--serif);font-size:16px;color:var(--ink);letter-spacing:6px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="sc">
|
||||
<header class="bar" id="bar">
|
||||
<button class="bk" id="back" aria-label="返回"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
|
||||
<div class="tt">孕妈周刊</div>
|
||||
<span class="ver">效果稿 V1 · 孕妈周刊</span>
|
||||
</header>
|
||||
<section class="cover" id="cover"></section>
|
||||
<nav class="secnav" id="nav"></nav>
|
||||
<main id="main"></main>
|
||||
<footer class="colo">
|
||||
<b>孕妈周刊</b>
|
||||
第 44 期 · 2026 年 11 月刊 · 由妈妈们共同撰写<br>
|
||||
本期文章与数字均为示例占位,正式版替换为真实分享
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="../../guangchang/topics.js"></script>
|
||||
<script src="../../guangchang/data.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
|
||||
var $ = function (s) { return document.querySelector(s); };
|
||||
var H = location.hash || '';
|
||||
var COL = { /* 分类 → 杂志栏目名 */
|
||||
family: { tab: '家庭婚姻', col: '家事 · 围炉', c: '#E0566F' },
|
||||
work: { tab: '职场', col: '职场 · 手记', c: '#3A72B8' },
|
||||
baby: { tab: '经验', col: '过来人 · 说', c: '#2E8A7C' }
|
||||
};
|
||||
var TABS = ['', 'family', 'work', 'baby'];
|
||||
var cat = '', tocOpen = false;
|
||||
|
||||
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); }
|
||||
function hash(s) { var x = 7; for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); }
|
||||
var POOL = []; for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
|
||||
function av(name) { return '../../assets/img/mom/' + POOL[hash(name || '妈妈') % POOL.length] + '.jpg'; }
|
||||
function fmt(n) { return n >= 10000 ? (n / 10000).toFixed(1) + '万' : String(n); }
|
||||
function tUrl(id) { return '../../guangchang/?t=' + encodeURIComponent(id) + H; }
|
||||
function nUrl(id, idx) { return '../../guangchang/?t=' + encodeURIComponent(id) + '&n=' + encodeURIComponent(id + '-' + idx) + H; }
|
||||
var TBY = {}; T.forEach(function (t) { TBY[t.id] = t; });
|
||||
|
||||
/* 所有笔记扁平化 */
|
||||
var NOTES = [];
|
||||
T.forEach(function (t) {
|
||||
var d = D[t.id]; if (!d || !d.notes) return;
|
||||
d.notes.forEach(function (n, k) { NOTES.push({ t: t, n: n, idx: k + 1 }); });
|
||||
});
|
||||
function inCat(x) { return !cat || x.t.cat === cat; }
|
||||
/* 「全部」时三栏轮流排,看起来像一本综合刊 */
|
||||
function mix(list) {
|
||||
if (cat) return list;
|
||||
var b = { family: [], work: [], baby: [] }, out = [];
|
||||
list.forEach(function (x) { (b[(x.t || x).cat] || b.family).push(x); });
|
||||
for (var i = 0; out.length < list.length; i++) ['family', 'work', 'baby'].forEach(function (k) { if (b[k][i]) out.push(b[k][i]); });
|
||||
return out;
|
||||
}
|
||||
function excerpt(body, n) { var s = String(body || '').replace(/\s+/g, ''); return s.length > n ? s.slice(0, n) + '…' : s; }
|
||||
function pickQuote(body) {
|
||||
var parts = String(body || '').split(/[。!?\n]/).map(function (p) { return p.trim(); });
|
||||
var ok = function (p) { return p.length >= 12 && p.length <= 32 && !/[“”"「」::]|分享|办法|姐妹|参考|大家|评论/.test(p); };
|
||||
for (var i = parts.length - 1; i > parts.length / 2; i--) if (ok(parts[i])) return parts[i];
|
||||
for (i = 1; i < parts.length; i++) if (ok(parts[i])) return parts[i];
|
||||
return parts[0].slice(0, 30);
|
||||
}
|
||||
var heart = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20s-7-4.4-7-10a4 4 0 017-2.6A4 4 0 0119 10c0 5.6-7 10-7 10z"/></svg>';
|
||||
function by(n, likes) {
|
||||
return '<div class="by"><img loading="lazy" src="' + av(n.author) + '" alt=""><span class="nm">' + esc(n.author) + '</span><span>' + esc(n.stage || '') + '</span>' +
|
||||
(likes ? '<span class="lk">' + heart + fmt(n.likes || 0) + '</span>' : '') + '</div>';
|
||||
}
|
||||
|
||||
/* ---------- 封面 ---------- */
|
||||
var COVER_PICK = { '': 'b07', family: 'm07', work: 'w02', baby: 'b08' };
|
||||
function renderCover() {
|
||||
var photo = NOTES.filter(function (x) { return x.n.photo && inCat(x); });
|
||||
var pref = COVER_PICK[cat];
|
||||
var main = photo.filter(function (x) { return x.t.id === pref; })[0] || photo[0];
|
||||
if (!main) { $('#cover').innerHTML = ''; return; }
|
||||
var pool = T.filter(function (t) { return (!cat || t.cat === cat) && t.id !== main.t.id; });
|
||||
var lines = mix(pool.filter(function (t) { return t.hot; })).concat(pool.filter(function (t) { return !t.hot; })).slice(0, 3);
|
||||
var m = COL[main.t.cat];
|
||||
$('#cover').innerHTML =
|
||||
'<img src="../../guangchang/' + esc(main.n.photo) + '" alt="">' +
|
||||
'<div class="cv">' +
|
||||
'<div class="mast"><h1>孕妈周刊</h1><div class="iss"><b>第 44 期</b>11 月刊 · 2026</div></div>' +
|
||||
'<div class="mast-sub"><span>MAMA WEEKLY</span><span>' + (cat ? COL[cat].tab + '特辑' : '妈妈们自己写的杂志') + '</span></div>' +
|
||||
'<div class="sp"></div>' +
|
||||
'<ul class="lines">' + lines.map(function (t) {
|
||||
return '<li><a href="' + tUrl(t.id) + '"><small>' + esc(COL[t.cat].col) + '</small><span>' + esc(t.name) + '</span></a></li>';
|
||||
}).join('') + '</ul>' +
|
||||
'<a class="story" href="' + nUrl(main.t.id, main.idx) + '">' +
|
||||
'<span class="kick">本期封面故事 · ' + esc(m.tab) + '</span>' +
|
||||
'<h2>' + esc(main.n.title) + '</h2>' +
|
||||
'<p>' + esc(excerpt(main.n.body, 60)) + '</p>' +
|
||||
'<div class="by"><img src="' + av(main.n.author) + '" alt=""><span>文 / ' + esc(main.n.author) + ' · ' + esc(main.n.stage || '') + '</span><span class="rd">阅读全文 →</span></div>' +
|
||||
'</a>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
/* ---------- 栏目导航 ---------- */
|
||||
function renderNav() {
|
||||
$('#nav').innerHTML = TABS.map(function (k) {
|
||||
return '<button data-c="' + k + '" class="' + (k === cat ? 'on' : '') + '" style="--c:' + (k ? COL[k].c : 'var(--ink)') + '">' + (k ? COL[k].tab : '全部') + '</button>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
/* ---------- 正文 ---------- */
|
||||
function renderMain() {
|
||||
var topics = mix(T.filter(function (t) { return !cat || t.cat === cat; }));
|
||||
var shown = tocOpen ? topics : topics.slice(0, 8);
|
||||
var toc =
|
||||
'<section class="sec"><div class="hd"><h3>本期目录</h3><em>Contents</em><span class="r">共 ' + topics.length + ' 个话题</span></div>' +
|
||||
'<ol class="toc">' + shown.map(function (t, i) {
|
||||
var c = COL[t.cat];
|
||||
return '<li style="--c:' + c.c + '"><a href="' + tUrl(t.id) + '"><span class="no">' + (i < 9 ? '0' : '') + (i + 1) + '</span><div class="bd">' +
|
||||
'<div class="col">' + esc(c.col) + (t.hot ? '<span class="hot">热议</span>' : '') + '</div>' +
|
||||
'<div class="nm">' + esc(t.name) + '</div>' +
|
||||
'<div class="mt">' + t.n + ' 篇来稿 · ' + fmt(t.talk) + ' 人在聊</div></div></a></li>';
|
||||
}).join('') + '</ol>' +
|
||||
(topics.length > 8 ? '<button class="more" id="more">' + (tocOpen ? '收起目录 ↑' : '展开完整目录(' + topics.length + ')↓') + '</button>' : '') +
|
||||
'</section>';
|
||||
|
||||
var call =
|
||||
'<section class="call"><div class="in"><div class="stamp">入选<br>有奖</div>' +
|
||||
'<div class="ti">本刊征稿启事<small>CALL FOR STORIES</small></div>' +
|
||||
'<p>孕期里那些说不出口的委屈、哭笑不得的小事、熬过来的经验,都值得被写下来。挑一个本期话题,写写你的故事,编辑部每期从来稿中选登。</p>' +
|
||||
'<div class="pay"><div><b>¥30</b><span>现金稿酬</span></div><div><b>500</b><span>兜豆</span></div></div>' +
|
||||
'<div class="act"><a class="p" href="' + tUrl(topics[0] ? topics[0].id : 'f01') + '">我要投稿</a><a href="../../guangchang/' + H + '">我的投稿</a></div>' +
|
||||
'</div></section>';
|
||||
|
||||
/* 专栏:大图一篇 → 两篇小图并排 → 金句卡,循环 */
|
||||
var pics = mix(NOTES.filter(function (x) { return x.n.photo && inCat(x); }));
|
||||
var plain = mix(NOTES.filter(function (x) { return !x.n.photo && inCat(x); }));
|
||||
var used = {}; var cvId = ($('#cover .story') || {}).getAttribute ? $('#cover .story').getAttribute('href') : '';
|
||||
pics = pics.filter(function (x) { return cvId.indexOf('n=' + encodeURIComponent(x.t.id + '-' + x.idx)) < 0; });
|
||||
var groups = [], pi = 0, qi = 0;
|
||||
while (pi < pics.length && groups.length < 6) {
|
||||
var g = '', f = pics[pi++], c = COL[f.t.cat];
|
||||
g += '<a class="feat" style="--c:' + c.c + '" href="' + nUrl(f.t.id, f.idx) + '"><div class="ph"><img loading="lazy" src="../../guangchang/' + esc(f.n.photo) + '" alt=""><span class="tag">' + esc(c.col) + '</span></div>' +
|
||||
'<h4>' + esc(f.n.title) + '</h4><p>' + esc(excerpt(f.n.body, 90)) + '</p>' + by(f.n, true) + '</a>';
|
||||
var a = pics[pi], b = pics[pi + 1];
|
||||
if (a && b) {
|
||||
pi += 2;
|
||||
g += '<div class="pair">' + [a, b].map(function (x) {
|
||||
var cc = COL[x.t.cat];
|
||||
return '<a style="--c:' + cc.c + '" href="' + nUrl(x.t.id, x.idx) + '"><div class="ph"><img class="cvr" loading="lazy" src="../../guangchang/' + esc(x.n.photo) + '" alt=""></div>' +
|
||||
'<div class="col">' + esc(cc.col) + '</div><h5>' + esc(x.n.title) + '</h5>' + by(x.n, false) + '</a>';
|
||||
}).join('') + '</div>';
|
||||
}
|
||||
var q = plain[qi++] || pics[pi++];
|
||||
if (q) {
|
||||
var qc = COL[q.t.cat];
|
||||
g += '<a class="quote" style="--c:' + qc.c + '" href="' + nUrl(q.t.id, q.idx) + '"><span class="mk">“</span><q>' + esc(pickQuote(q.n.body)) + '</q>' +
|
||||
'<div class="src">—— <b>' + esc(q.n.author) + '</b>,《' + esc(q.n.title) + '》</div></a>';
|
||||
}
|
||||
groups.push('<div class="grp">' + g + '</div>');
|
||||
}
|
||||
var cols =
|
||||
'<section class="sec"><div class="hd"><h3>' + (cat ? COL[cat].col : '专栏') + '</h3><em>Features</em><span class="r">妈妈们的来稿</span></div>' +
|
||||
groups.join('') + '</section>';
|
||||
|
||||
$('#main').innerHTML = toc + call + cols;
|
||||
var mb = $('#more'); if (mb) mb.onclick = function () { tocOpen = !tocOpen; renderMain(); };
|
||||
}
|
||||
|
||||
function render() { renderCover(); renderNav(); renderMain(); }
|
||||
|
||||
$('#nav').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('button'); if (!b) return;
|
||||
var k = b.getAttribute('data-c'); if (k === cat) return;
|
||||
cat = k; tocOpen = false; render();
|
||||
var sc = $('#sc'); if (sc.scrollTop > 0) sc.scrollTop = 0;
|
||||
});
|
||||
$('#back').onclick = function () { history.length > 1 ? history.back() : (location.href = '../../' + location.hash); };
|
||||
|
||||
var bar = $('#bar'), sc = $('#sc');
|
||||
sc.addEventListener('scroll', function () { bar.classList.toggle('on', sc.scrollTop > 420); }, { passive: true });
|
||||
|
||||
/* 禁止下拉回弹:往上找能朝该方向滚的容器,找不到才拦 */
|
||||
var sx = 0, sy = 0;
|
||||
document.addEventListener('touchstart', function (e) { if (e.touches.length === 1) { sx = e.touches[0].clientX; sy = e.touches[0].clientY; } }, { passive: true });
|
||||
document.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
|
||||
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
|
||||
if (Math.abs(dy) <= Math.abs(dx)) return;
|
||||
var el = e.target;
|
||||
while (el && el !== document.body && el !== document.documentElement) {
|
||||
if (el.nodeType === 1) {
|
||||
var oy = getComputedStyle(el).overflowY;
|
||||
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
|
||||
if (dy > 0 && el.scrollTop > 0) return;
|
||||
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
|
||||
}
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
if (e.cancelable) e.preventDefault();
|
||||
}, { passive: false });
|
||||
|
||||
render();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
565
demo/gc-v2/index.html
Normal file
565
demo/gc-v2/index.html
Normal file
@@ -0,0 +1,565 @@
|
||||
<!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,viewport-fit=cover">
|
||||
<title>孕妈广场</title>
|
||||
<!-- 效果稿 V2 · 广场地图:首屏是一张俯视小广场插画(SVG),三个分类 = 广场上的三个角落;往下是该角落的话题和笔记。演示页,不接后端。 -->
|
||||
<style>
|
||||
:root{
|
||||
--brand:#F4593C;--ink:#2E2521;--ink-2:#6E625B;--muted:#A08F86;--line:#EFE3D8;
|
||||
--bg:#FAF4EC;--fam:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
|
||||
--zc:#F4593C;
|
||||
}
|
||||
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
|
||||
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
|
||||
body{background:var(--bg);font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC","Segoe UI",Roboto,sans-serif;
|
||||
color:var(--ink);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5;-webkit-text-size-adjust:100%}
|
||||
.hide{display:none!important}
|
||||
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
|
||||
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;background:var(--bg)}
|
||||
#sc::-webkit-scrollbar{display:none}
|
||||
|
||||
/* ---------- 顶栏 ---------- */
|
||||
.top{position:sticky;top:0;z-index:30;padding-top:env(safe-area-inset-top);background:rgba(250,244,236,.88);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);transition:box-shadow .2s}
|
||||
.top.on{box-shadow:0 4px 14px rgba(150,110,80,.10)}
|
||||
.nav{display:flex;align-items:center;height:46px;padding:0 8px}
|
||||
.nav .bk{width:36px;height:36px;display:grid;place-items:center;border-radius:50%}
|
||||
.nav .bk:active{background:rgba(0,0,0,.05)}
|
||||
.nav h1{flex:1;margin:0;text-align:center;font-size:17px;font-weight:800;letter-spacing:1px}
|
||||
.nav .mine{height:30px;padding:0 11px;border-radius:15px;font-size:12.5px;font-weight:700;color:#8A6E5E;background:#F1E5D8}
|
||||
.ver{position:absolute;left:50%;transform:translateX(-50%);bottom:-1px;font-size:11px;color:#C4B2A6;letter-spacing:.5px;white-space:nowrap;line-height:1}
|
||||
|
||||
/* ---------- 欢迎语 ---------- */
|
||||
.hello{padding:8px 18px 2px;display:flex;align-items:flex-end;justify-content:space-between;gap:10px}
|
||||
.hello h2{margin:0;font-size:20px;font-weight:800;line-height:1.3;letter-spacing:.5px}
|
||||
.hello h2 em{font-style:normal;color:var(--brand)}
|
||||
.hello p{margin:3px 0 0;font-size:12.5px;color:var(--muted)}
|
||||
.hello .wx{flex:none;text-align:right;font-size:11px;color:#B39A8A;line-height:1.35}
|
||||
.hello .wx b{display:block;font-size:15px;color:#8C6F5C;font-weight:700}
|
||||
|
||||
/* ---------- 广场地图 ---------- */
|
||||
.mapw{position:relative;margin:10px 12px 0;border-radius:26px;overflow:hidden;box-shadow:0 14px 30px -18px rgba(140,90,50,.45),0 0 0 1px rgba(200,170,140,.25);background:#F3E6D5}
|
||||
.map{position:relative;width:100%;aspect-ratio:351/440}
|
||||
.map svg.ground{position:absolute;inset:0;width:100%;height:100%;display:block}
|
||||
.pin{position:absolute;transform:translate(-50%,-50%)}
|
||||
/* 角落热区 */
|
||||
.zone{position:absolute;border-radius:50%;transform:translate(-50%,-50%)}
|
||||
.zone .halo{position:absolute;inset:0;border-radius:50%;border:2px dashed var(--zc);opacity:0;transform:scale(.92);transition:opacity .3s,transform .3s}
|
||||
.map.f-family .z-family .halo,.map.f-work .z-work .halo,.map.f-baby .z-baby .halo{opacity:.75;transform:scale(1);animation:spin 26s linear infinite}
|
||||
@keyframes spin{to{transform:rotate(360deg)}}
|
||||
/* 招牌 */
|
||||
.sign{position:absolute;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;pointer-events:none;z-index:4}
|
||||
.sign b{display:block;padding:4px 10px 4px;border-radius:10px;background:#FFFDF9;color:var(--zc);font-size:12.5px;font-weight:800;letter-spacing:.5px;white-space:nowrap;
|
||||
box-shadow:0 3px 0 rgba(0,0,0,.06),0 6px 14px -6px rgba(110,70,40,.35);border:1.5px solid color-mix(in srgb,var(--zc) 28%,#fff);transition:background .25s,color .25s}
|
||||
.sign small{margin-top:3px;padding:1px 7px;border-radius:8px;background:rgba(255,253,249,.82);font-size:11px;color:#8C7466;white-space:nowrap}
|
||||
.map.f-family .s-family b,.map.f-work .s-work b,.map.f-baby .s-baby b,.map.f-all .s-all b{background:var(--zc);color:#fff;border-color:var(--zc)}
|
||||
/* 妈妈 */
|
||||
.mom{position:absolute;width:34px;height:34px;margin:-17px 0 0 -17px;z-index:3;transition:filter .3s,opacity .3s}
|
||||
.mom i{display:block;width:100%;height:100%;border-radius:50%;border:2.5px solid #fff;background:#EADBCB center/cover no-repeat;
|
||||
box-shadow:0 5px 8px -3px rgba(90,55,30,.45);animation:breathe 3.4s ease-in-out infinite;transform-origin:50% 80%}
|
||||
.mom::after{content:"";position:absolute;left:50%;bottom:-5px;width:26px;height:7px;margin-left:-13px;border-radius:50%;background:rgba(90,60,30,.18);filter:blur(1.5px);z-index:-1;animation:shadow 3.4s ease-in-out infinite}
|
||||
.mom.sm{width:28px;height:28px;margin:-14px 0 0 -14px}
|
||||
@keyframes breathe{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-2px) scale(1.06)}}
|
||||
@keyframes shadow{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(.85);opacity:.7}}
|
||||
/* 对话气泡 */
|
||||
.bub{position:absolute;z-index:6;max-width:150px;padding:6px 10px 7px;border-radius:14px;background:#fff;font-size:12px;line-height:1.42;color:#3F3430;font-weight:600;
|
||||
box-shadow:0 8px 18px -8px rgba(100,60,30,.4);transition:opacity .35s,transform .35s,filter .3s;pointer-events:none}
|
||||
.bub::before{content:"";position:absolute;width:10px;height:10px;background:#fff;transform:rotate(45deg);border-radius:2px}
|
||||
.bub.tl::before{left:12px;bottom:-4px}.bub.tr::before{right:12px;bottom:-4px}.bub.br::before{right:34px;top:-4px}
|
||||
.bub span{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;position:relative}
|
||||
.bub em{font-style:normal;color:var(--zc);font-weight:800}
|
||||
.bub.out span{opacity:.15;transform:translateY(3px)}
|
||||
.bub span{transition:opacity .3s,transform .3s}
|
||||
.map:not(.f-all) .dim{opacity:.45;filter:grayscale(.6)}
|
||||
.map:not(.f-all) .bub.dim{opacity:0;transform:scale(.9)}
|
||||
/* 喷泉水波 */
|
||||
.rip{transform-origin:center;transform-box:fill-box;animation:rip 3.6s ease-out infinite}
|
||||
.rip.r2{animation-delay:1.2s}.rip.r3{animation-delay:2.4s}
|
||||
@keyframes rip{0%{transform:scale(.35);opacity:.9}100%{transform:scale(1.25);opacity:0}}
|
||||
.leaf{transform-origin:center;transform-box:fill-box;animation:sway 6s ease-in-out infinite}
|
||||
@keyframes sway{0%,100%{transform:rotate(0)}50%{transform:rotate(3deg)}}
|
||||
.bird{animation:peck 2.8s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
|
||||
@keyframes peck{0%,70%,100%{transform:translate(0,0)}78%{transform:translate(1.5px,1px)}86%{transform:translate(0,0)}}
|
||||
|
||||
/* 投稿信箱(地图上) */
|
||||
.box{position:absolute;z-index:5;display:flex;flex-direction:column;align-items:center;transform:translate(-50%,-50%)}
|
||||
.box .mb{position:relative;width:46px;height:62px}
|
||||
.box .mb svg{display:block;width:100%;height:100%;overflow:visible;animation:wob 4.5s ease-in-out infinite;transform-origin:50% 100%}
|
||||
@keyframes wob{0%,86%,100%{transform:rotate(0)}90%{transform:rotate(-4deg)}94%{transform:rotate(3deg)}}
|
||||
.box .tag{margin-top:2px;padding:3px 8px;border-radius:9px;background:#fff;font-size:11px;font-weight:800;color:var(--brand);white-space:nowrap;box-shadow:0 4px 10px -5px rgba(120,60,30,.5);line-height:1.35;text-align:center}
|
||||
.box .tag small{display:block;font-size:11px;font-weight:600;color:#A07C68}
|
||||
.box:active .mb{transform:scale(.95)}
|
||||
|
||||
/* 地图下方路牌(分类快捷切换) */
|
||||
.posts{display:flex;gap:6px;padding:12px 12px 2px}
|
||||
.posts button{flex:1;min-width:0;height:36px;border-radius:12px;background:#F2E7DA;color:#8A7468;font-size:13.5px;font-weight:700;display:flex;align-items:center;justify-content:center;gap:4px;transition:all .2s;white-space:nowrap}
|
||||
.posts button i{width:7px;height:7px;border-radius:50%;background:var(--zc);flex:none}
|
||||
.posts button.on{background:var(--zc);color:#fff;box-shadow:0 6px 14px -7px var(--zc)}
|
||||
.posts button.on i{background:#fff}
|
||||
|
||||
/* ---------- 列表 ---------- */
|
||||
.sec{padding:20px 16px 0}
|
||||
.sec-h{display:flex;align-items:center;gap:8px;margin-bottom:10px}
|
||||
.sec-h h3{margin:0;font-size:17px;font-weight:800;letter-spacing:.3px;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.sec-h h3 em{font-style:normal;color:var(--zc)}
|
||||
.live{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);flex:none}
|
||||
.live .dot{width:7px;height:7px;border-radius:50%;background:#58B37A;box-shadow:0 0 0 3px rgba(88,179,122,.2);animation:pulse 1.8s ease-in-out infinite}
|
||||
@keyframes pulse{50%{box-shadow:0 0 0 6px rgba(88,179,122,0)}}
|
||||
.stack{display:flex}
|
||||
.stack i{width:20px;height:20px;border-radius:50%;border:1.5px solid #fff;margin-left:-6px;background:#EADBCB center/cover}
|
||||
.stack i:first-child{margin-left:0}
|
||||
|
||||
/* 话题:广场石板 */
|
||||
.tps{display:flex;flex-direction:column;gap:8px}
|
||||
.tp{display:flex;align-items:center;gap:11px;padding:10px 12px 10px 10px;border-radius:18px;background:#fff;text-align:left;box-shadow:0 1px 0 rgba(160,120,90,.08)}
|
||||
.tp:active{transform:scale(.99)}
|
||||
.tp .ph{position:relative;flex:none;width:52px;height:52px;border-radius:14px;overflow:hidden;background:var(--tl)}
|
||||
.tp .ph img{width:100%;height:100%;object-fit:cover;display:block}
|
||||
.tp .ph b{position:absolute;inset:0;display:grid;place-items:center;font-size:26px;font-weight:900;color:var(--ti);font-family:"STKaiti","KaiTi","Kaiti SC",serif}
|
||||
.tp .ph img+b{display:none}
|
||||
.tp .tx{flex:1;min-width:0}
|
||||
.tp .nm{font-size:14.5px;font-weight:700;line-height:1.4;color:var(--ink);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.tp .mt{display:flex;align-items:center;gap:6px;margin-top:4px;font-size:11.5px;color:var(--muted)}
|
||||
.tp .mt .k{padding:0 6px;border-radius:6px;font-weight:700;color:var(--ti);background:var(--tl);line-height:18px}
|
||||
.tp .mt .hot{color:#E86A3A;font-weight:700}
|
||||
.tp .go{flex:none;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;background:#F7EFE6;color:#B49C8C}
|
||||
.more{display:block;width:100%;margin-top:8px;height:38px;border-radius:14px;background:transparent;border:1.5px dashed #E2CFBE;color:#9C8172;font-size:13px;font-weight:700}
|
||||
|
||||
/* 笔记:长椅上的分享 */
|
||||
.nts{display:flex;flex-direction:column;gap:12px}
|
||||
.nt{display:flex;gap:12px;padding:12px;border-radius:20px;background:#fff;text-align:left;box-shadow:0 1px 0 rgba(160,120,90,.08)}
|
||||
.nt:active{transform:scale(.99)}
|
||||
.nt .pic{flex:none;width:104px;height:138px;border-radius:14px;overflow:hidden;background:#EFE4D8;position:relative}
|
||||
.nt .pic img{width:100%;height:100%;object-fit:cover;display:block}
|
||||
.nt .cv{flex:none;width:104px;height:138px;border-radius:14px;position:relative;overflow:hidden;padding:12px 10px;background:linear-gradient(160deg,var(--c1),var(--c2));color:var(--ti);display:flex;flex-direction:column;justify-content:flex-end}
|
||||
.nt .cv b{position:relative;z-index:1;font-size:15px;font-weight:900;line-height:1.3}
|
||||
.nt .cv small{position:relative;z-index:1;font-size:11px;margin-top:4px;opacity:.8;line-height:1.35}
|
||||
.nt .cv .wm{position:absolute;right:-6px;top:-10px;font-size:76px;font-weight:900;line-height:1;color:#fff;opacity:.55;font-family:"STKaiti","KaiTi","Kaiti SC",serif}
|
||||
.nt .bd{flex:1;min-width:0;display:flex;flex-direction:column}
|
||||
.nt .tg{align-self:flex-start;max-width:100%;font-size:11.5px;font-weight:700;color:var(--ti);background:var(--tl);padding:0 7px;border-radius:7px;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.nt h4{margin:6px 0 0;font-size:15px;font-weight:800;line-height:1.42;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.nt p{margin:4px 0 0;font-size:13px;color:var(--ink-2);line-height:1.55;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.nt .ft{margin-top:auto;padding-top:6px;display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);min-width:0}
|
||||
.nt .ft i{width:22px;height:22px;border-radius:50%;flex:none;background:#EADBCB center/cover}
|
||||
.nt .ft .au{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#7A6A61}
|
||||
.nt .ft .st{flex:none}
|
||||
.nt .ft .lk{margin-left:auto;flex:none;display:flex;align-items:center;gap:3px}
|
||||
|
||||
/* 投稿明信片 */
|
||||
.card-mail{position:relative;display:flex;align-items:center;gap:12px;width:100%;padding:14px 14px 14px 16px;border-radius:20px;text-align:left;overflow:hidden;
|
||||
background:repeating-linear-gradient(-45deg,#F4593C 0 8px,#fff 8px 16px,#3A72B8 16px 24px,#fff 24px 32px);}
|
||||
.card-mail::before{content:"";position:absolute;inset:5px;border-radius:16px;background:#FFFBF5}
|
||||
.card-mail>*{position:relative}
|
||||
.card-mail .tx{flex:1;min-width:0}
|
||||
.card-mail .tx b{display:block;font-size:15px;font-weight:800}
|
||||
.card-mail .tx span{display:block;margin-top:2px;font-size:12.5px;color:var(--ink-2)}
|
||||
.card-mail .tx span em{font-style:normal;font-weight:800;color:var(--brand)}
|
||||
.card-mail .stamp{flex:none;width:62px;height:70px;padding:4px;background:#fff;border-radius:4px;border:2px dashed #F3B9A6;transform:rotate(4deg);box-shadow:0 3px 8px -4px rgba(0,0,0,.2)}
|
||||
.card-mail .stamp div{height:100%;border-radius:2px;background:linear-gradient(160deg,#FFB08F,#F4593C);color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.15}
|
||||
.card-mail .stamp b{font-size:17px;font-weight:900}
|
||||
.card-mail .stamp small{font-size:11px;font-weight:700;opacity:.95}
|
||||
.foot{padding:22px 16px calc(28px + env(safe-area-inset-bottom));text-align:center;font-size:11px;color:#C1AFA2}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="sc">
|
||||
<div class="top" id="top">
|
||||
<div class="nav">
|
||||
<button class="bk" id="back" aria-label="返回"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#2E2521" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
|
||||
<h1>孕妈广场</h1>
|
||||
<button class="mine" id="mine">我的投稿</button>
|
||||
</div>
|
||||
<div class="ver">效果稿 V2 · 广场地图</div>
|
||||
</div>
|
||||
|
||||
<div class="hello">
|
||||
<div>
|
||||
<h2><span id="tod">午后</span>的小广场,<br>有 <em id="nowN">0</em> 位妈妈在聊</h2>
|
||||
<p>点亭子、长椅或大树,去那个角落坐坐</p>
|
||||
</div>
|
||||
<div class="wx"><b id="clock">14:30</b><span id="wxs">晴 · 微风</span></div>
|
||||
</div>
|
||||
|
||||
<div class="mapw">
|
||||
<div class="map f-all" id="map">
|
||||
<svg class="ground" viewBox="0 0 351 440" preserveAspectRatio="none" aria-hidden="true">
|
||||
<defs>
|
||||
<pattern id="tile" width="22" height="22" patternUnits="userSpaceOnUse">
|
||||
<rect width="22" height="22" fill="#F4E8D8"/>
|
||||
<path d="M0 .5H22M.5 0V22" stroke="#EADAC6" stroke-width="1"/>
|
||||
<rect x="3" y="3" width="2" height="2" rx="1" fill="#EFE0CD"/>
|
||||
</pattern>
|
||||
<pattern id="grass" width="14" height="14" patternUnits="userSpaceOnUse">
|
||||
<rect width="14" height="14" fill="#CFE3BD"/>
|
||||
<path d="M3 5l1-2 1 2M10 11l1-2 1 2" stroke="#B9D6A3" stroke-width="1" fill="none" stroke-linecap="round"/>
|
||||
</pattern>
|
||||
<pattern id="deck" width="351" height="9" patternUnits="userSpaceOnUse">
|
||||
<rect width="351" height="9" fill="#EBD3B5"/>
|
||||
<path d="M0 8.5H351" stroke="#DDBF9C" stroke-width="1"/>
|
||||
</pattern>
|
||||
<radialGradient id="water" cx=".42" cy=".38" r=".7">
|
||||
<stop offset="0" stop-color="#E4F4F4"/><stop offset=".6" stop-color="#BFE1E3"/><stop offset="1" stop-color="#9FCFD3"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="roof" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#FAC6CE"/><stop offset="1" stop-color="#EA8C9D"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="glow"><stop offset="0" stop-color="#FFF4C8" stop-opacity=".95"/><stop offset="1" stop-color="#FFE59A" stop-opacity="0"/></radialGradient>
|
||||
<filter id="sh" x="-30%" y="-30%" width="160%" height="160%"><feDropShadow dx="3" dy="5" stdDeviation="3.5" flood-color="#6B4526" flood-opacity=".22"/></filter>
|
||||
<filter id="sh2" x="-30%" y="-30%" width="160%" height="160%"><feDropShadow dx="2" dy="3" stdDeviation="2" flood-color="#6B4526" flood-opacity=".2"/></filter>
|
||||
</defs>
|
||||
|
||||
<!-- 地砖 -->
|
||||
<rect width="351" height="440" fill="url(#tile)"/>
|
||||
|
||||
<!-- 草坪 -->
|
||||
<path d="M-10 -10H205C214 30 196 60 170 74C150 88 160 130 150 160C138 196 96 214 56 206C24 200 4 214 -10 230Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
|
||||
<path d="M-10 268C30 262 70 270 110 280C160 292 190 320 198 360C204 396 196 420 210 450H-10Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
|
||||
<path d="M262 -10H361V120C340 128 318 118 300 104C282 90 268 60 262 30Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
|
||||
<path d="M268 330C292 316 330 318 361 326V450H250C244 410 248 352 268 330Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
|
||||
|
||||
<!-- 小路 -->
|
||||
<g fill="none" stroke-linecap="round">
|
||||
<path d="M176 222C140 190 116 160 92 112M176 222C220 214 260 206 300 200M176 222C150 262 128 300 106 346M176 222C210 270 240 320 300 350" stroke="#E2CCB0" stroke-width="30"/>
|
||||
<path d="M176 222C140 190 116 160 92 112M176 222C220 214 260 206 300 200M176 222C150 262 128 300 106 346M176 222C210 270 240 320 300 350" stroke="#F6EBDC" stroke-width="25"/>
|
||||
<path d="M176 222C140 190 116 160 92 112M176 222C150 262 128 300 106 346M176 222C210 270 240 320 300 350" stroke="#EAD8C2" stroke-width="2" stroke-dasharray="1 9"/>
|
||||
</g>
|
||||
|
||||
<!-- 花坛小点 -->
|
||||
<g>
|
||||
<circle cx="30" cy="40" r="11" fill="#B6D49F"/><circle cx="26" cy="37" r="2.4" fill="#F7A9B7"/><circle cx="34" cy="42" r="2.4" fill="#FFD27A"/><circle cx="29" cy="45" r="2" fill="#fff"/>
|
||||
<circle cx="190" cy="30" r="9" fill="#B6D49F"/><circle cx="187" cy="28" r="2.2" fill="#FFD27A"/><circle cx="193" cy="33" r="2.2" fill="#F7A9B7"/>
|
||||
<circle cx="330" cy="400" r="12" fill="#A9CC92"/><circle cx="326" cy="396" r="2.5" fill="#F7A9B7"/><circle cx="335" cy="402" r="2.5" fill="#fff"/><circle cx="329" cy="406" r="2.2" fill="#FFD27A"/>
|
||||
<circle cx="24" cy="420" r="10" fill="#A9CC92"/><circle cx="21" cy="417" r="2.2" fill="#fff"/><circle cx="27" cy="422" r="2.2" fill="#F7A9B7"/>
|
||||
<circle cx="336" cy="30" r="13" fill="#A9CC92" filter="url(#sh2)"/><circle cx="332" cy="26" r="5" fill="#BEDCA8"/>
|
||||
<circle cx="226" cy="410" r="10" fill="#A9CC92" filter="url(#sh2)"/><circle cx="223" cy="407" r="4" fill="#BEDCA8"/>
|
||||
</g>
|
||||
|
||||
<!-- 中心喷泉 -->
|
||||
<g>
|
||||
<circle cx="176" cy="222" r="62" fill="#F1E2CF" stroke="#E3CDB2" stroke-width="2"/>
|
||||
<circle cx="176" cy="222" r="52" fill="none" stroke="#E9D6BF" stroke-width="12" stroke-dasharray="9 3"/>
|
||||
<circle cx="176" cy="222" r="38" fill="#EBDAC4" filter="url(#sh2)"/>
|
||||
<circle cx="176" cy="222" r="33" fill="url(#water)"/>
|
||||
<circle class="rip" cx="176" cy="222" r="28" fill="none" stroke="#fff" stroke-width="1.4" opacity=".8"/>
|
||||
<circle class="rip r2" cx="176" cy="222" r="28" fill="none" stroke="#fff" stroke-width="1.4" opacity=".8"/>
|
||||
<circle class="rip r3" cx="176" cy="222" r="28" fill="none" stroke="#fff" stroke-width="1.4" opacity=".8"/>
|
||||
<circle cx="176" cy="222" r="10" fill="#F2E5D4" stroke="#E0CBB0" stroke-width="1.5"/>
|
||||
<circle cx="176" cy="222" r="4.5" fill="#CDEBEE"/>
|
||||
<circle cx="174.5" cy="220.5" r="1.6" fill="#fff"/>
|
||||
</g>
|
||||
<!-- 鸽子 -->
|
||||
<g class="bird"><ellipse cx="236" cy="252" rx="5" ry="3.4" fill="#C9C3C0"/><circle cx="240.5" cy="250.6" r="2" fill="#A9A19D"/><path d="M242.4 250.6l1.6.4-1.6.6z" fill="#E59A5B"/></g>
|
||||
<g class="bird" style="animation-delay:1.3s"><ellipse cx="226" cy="262" rx="4.6" ry="3.2" fill="#D6D0CC"/><circle cx="222" cy="260.6" r="1.9" fill="#B2AAA6"/><path d="M220.2 260.6l-1.5.4 1.5.6z" fill="#E59A5B"/></g>
|
||||
|
||||
<!-- 家庭婚姻亭(八角亭俯视) -->
|
||||
<g>
|
||||
<polygon points="92,58 130,74 146,112 130,150 92,166 54,150 38,112 54,74" fill="#EEDCCB" stroke="#E2CBB3" stroke-width="2" transform="translate(0 2)"/>
|
||||
<g filter="url(#sh)">
|
||||
<polygon points="92,66 124,79 137,112 124,145 92,158 60,145 47,112 60,79" fill="url(#roof)"/>
|
||||
</g>
|
||||
<g stroke="#DC7487" stroke-width="1.6" opacity=".8">
|
||||
<path d="M92 112L92 66M92 112L124 79M92 112L137 112M92 112L124 145M92 112L92 158M92 112L60 145M92 112L47 112M92 112L60 79"/>
|
||||
</g>
|
||||
<polygon points="92,66 124,79 137,112 124,145 92,158 60,145 47,112 60,79" fill="none" stroke="#FCE3E7" stroke-width="2.5" stroke-linejoin="round"/>
|
||||
<polygon points="92,90 107.5,96.5 114,112 107.5,127.5 92,134 76.5,127.5 70,112 76.5,96.5" fill="#F8B4C0" opacity=".55"/>
|
||||
<circle cx="92" cy="112" r="5" fill="#F5D07A" stroke="#E2A94A" stroke-width="1.5"/>
|
||||
<g fill="#F5D07A"><circle cx="92" cy="66" r="2.2"/><circle cx="124" cy="79" r="2.2"/><circle cx="137" cy="112" r="2.2"/><circle cx="124" cy="145" r="2.2"/><circle cx="92" cy="158" r="2.2"/><circle cx="60" cy="145" r="2.2"/><circle cx="47" cy="112" r="2.2"/><circle cx="60" cy="79" r="2.2"/></g>
|
||||
</g>
|
||||
|
||||
<!-- 职场长椅:木平台 + 遮阳伞 + 两张长椅 + 路灯 -->
|
||||
<g>
|
||||
<rect x="246" y="150" width="96" height="106" rx="10" fill="url(#deck)" stroke="#D8B994" stroke-width="2"/>
|
||||
<!-- 长椅 1(上) -->
|
||||
<g filter="url(#sh2)">
|
||||
<rect x="258" y="158" width="72" height="16" rx="3" fill="#C99A6E"/>
|
||||
<rect x="258" y="158" width="72" height="5" rx="2" fill="#9E7150"/>
|
||||
<path d="M258 167.5H330M258 171.5H330" stroke="#B5875E" stroke-width="1"/>
|
||||
</g>
|
||||
<!-- 长椅 2(下) -->
|
||||
<g filter="url(#sh2)">
|
||||
<rect x="258" y="232" width="72" height="16" rx="3" fill="#C99A6E"/>
|
||||
<rect x="258" y="243" width="72" height="5" rx="2" fill="#9E7150"/>
|
||||
<path d="M258 236.5H330M258 240.5H330" stroke="#B5875E" stroke-width="1"/>
|
||||
</g>
|
||||
<!-- 遮阳伞 -->
|
||||
<g filter="url(#sh)">
|
||||
<circle cx="294" cy="203" r="26" fill="#fff"/>
|
||||
<path d="M294 203L294 177A26 26 0 0 1 312.4 184.6ZM294 203L320 203A26 26 0 0 1 312.4 221.4ZM294 203L294 229A26 26 0 0 1 275.6 221.4ZM294 203L268 203A26 26 0 0 1 275.6 184.6Z" fill="#8EB1DD"/>
|
||||
<circle cx="294" cy="203" r="26" fill="none" stroke="#6E95C8" stroke-width="1.5"/>
|
||||
<circle cx="294" cy="203" r="3" fill="#3A72B8"/>
|
||||
</g>
|
||||
<!-- 路灯 -->
|
||||
<circle cx="338" cy="148" r="16" fill="url(#glow)"/>
|
||||
<circle cx="338" cy="148" r="4.5" fill="#FFF6D8" stroke="#C9B48A" stroke-width="1.5"/>
|
||||
<!-- 盆栽 -->
|
||||
<circle cx="252" cy="262" r="8" fill="#B88B66" filter="url(#sh2)"/><circle cx="252" cy="262" r="6.5" fill="#8FC08F"/><circle cx="250" cy="260" r="2.5" fill="#A9D3A3"/>
|
||||
</g>
|
||||
|
||||
<!-- 经验树下:环形长椅 + 大树 -->
|
||||
<g>
|
||||
<ellipse cx="112" cy="362" rx="66" ry="60" fill="#5D7F57" opacity=".14"/>
|
||||
<circle cx="104" cy="352" r="55" fill="none" stroke="#C69C73" stroke-width="9" stroke-dasharray="7 2"/>
|
||||
<circle cx="104" cy="352" r="59.5" fill="none" stroke="#A97E58" stroke-width="1.2"/>
|
||||
<g class="leaf" filter="url(#sh)">
|
||||
<circle cx="104" cy="352" r="44" fill="#7FB394"/>
|
||||
<circle cx="80" cy="336" r="22" fill="#8CC0A0"/>
|
||||
<circle cx="124" cy="334" r="20" fill="#8CC0A0"/>
|
||||
<circle cx="118" cy="374" r="22" fill="#78AC8D"/>
|
||||
<circle cx="84" cy="372" r="18" fill="#86BA9A"/>
|
||||
<circle cx="98" cy="344" r="18" fill="#9DCDAF"/>
|
||||
<circle cx="90" cy="336" r="8" fill="#B4DCC2"/>
|
||||
<circle cx="120" cy="330" r="6" fill="#B4DCC2"/>
|
||||
<circle cx="112" cy="366" r="5" fill="#A7D3B6"/>
|
||||
</g>
|
||||
<!-- 小灌木 -->
|
||||
<circle cx="196" cy="326" r="10" fill="#9BC48C" filter="url(#sh2)"/><circle cx="193" cy="323" r="4" fill="#B5D8A6"/>
|
||||
</g>
|
||||
|
||||
<!-- 路灯们 -->
|
||||
<circle cx="140" cy="178" r="13" fill="url(#glow)"/><circle cx="140" cy="178" r="3.8" fill="#FFF6D8" stroke="#C9B48A" stroke-width="1.4"/>
|
||||
<circle cx="222" cy="300" r="13" fill="url(#glow)"/><circle cx="222" cy="300" r="3.8" fill="#FFF6D8" stroke="#C9B48A" stroke-width="1.4"/>
|
||||
</svg>
|
||||
|
||||
<!-- 热区 -->
|
||||
<button class="zone z-family" data-cat="family" style="--zc:var(--fam);left:26.2%;top:25.5%;width:30%;aspect-ratio:1" aria-label="家庭婚姻亭"><i class="halo"></i></button>
|
||||
<button class="zone z-work" data-cat="work" style="--zc:var(--work);left:83.8%;top:46%;width:33%;aspect-ratio:1" aria-label="职场长椅"><i class="halo"></i></button>
|
||||
<button class="zone z-baby" data-cat="baby" style="--zc:var(--baby);left:29.6%;top:80%;width:36%;aspect-ratio:1" aria-label="经验树下"><i class="halo"></i></button>
|
||||
<button class="zone z-all" data-cat="" style="left:50.1%;top:50.5%;width:20%;aspect-ratio:1" aria-label="全部"></button>
|
||||
|
||||
<!-- 招牌 -->
|
||||
<div class="sign s-family" style="--zc:var(--fam);left:26.2%;top:25.5%"><b>家庭婚姻亭</b><small id="cnt-family"></small></div>
|
||||
<div class="sign s-work" style="--zc:var(--work);left:83.8%;top:37.6%"><b>职场长椅</b><small id="cnt-work"></small></div>
|
||||
<div class="sign s-baby" style="--zc:var(--baby);left:29.6%;top:80%"><b>经验树下</b><small id="cnt-baby"></small></div>
|
||||
<div class="sign s-all" style="--zc:var(--brand);left:50.1%;top:50.5%"><b style="font-size:11.5px;padding:2px 8px">全部</b></div>
|
||||
|
||||
<div id="moms"></div>
|
||||
|
||||
<!-- 投稿信箱 -->
|
||||
<button class="box" id="mailbox" style="left:80.5%;top:12.5%" aria-label="投稿信箱">
|
||||
<span class="mb">
|
||||
<svg viewBox="0 0 46 62">
|
||||
<ellipse cx="23" cy="59" rx="16" ry="3" fill="rgba(90,50,20,.22)"/>
|
||||
<rect x="20" y="38" width="6" height="21" rx="1.5" fill="#8C5B3E"/>
|
||||
<path d="M6 18C6 9 13 4 23 4S40 9 40 18V40H6Z" fill="#F4593C"/>
|
||||
<path d="M6 18C6 9 13 4 23 4S40 9 40 18V22H6Z" fill="#FF7A58"/>
|
||||
<rect x="12" y="25" width="22" height="3.5" rx="1.75" fill="#B9361F"/>
|
||||
<rect x="15" y="20.5" width="16" height="9" rx="1" fill="#FFF7EA" transform="rotate(-6 23 25)"/>
|
||||
<path d="M15.5 21.2L23 26l7.5-5.8" stroke="#F0B9A6" stroke-width="1" fill="none" transform="rotate(-6 23 25)"/>
|
||||
<rect x="12" y="25" width="22" height="2" fill="#B9361F" opacity=".0"/>
|
||||
<text x="23" y="37" text-anchor="middle" font-size="7" font-weight="800" fill="#fff" font-family="sans-serif">投稿</text>
|
||||
<rect x="40" y="10" width="2.5" height="18" rx="1" fill="#C9472C"/>
|
||||
<path d="M42.5 10H50V16H42.5Z" fill="#FFD25E"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="tag">投稿信箱<small>选中得 ¥30+500兜豆</small></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="posts" id="posts"></div>
|
||||
|
||||
<div class="sec">
|
||||
<div class="sec-h"><h3 id="tpH"></h3><span class="live"><span class="stack" id="tpStack"></span></span></div>
|
||||
<div class="tps" id="tps"></div>
|
||||
<button class="more hide" id="more"></button>
|
||||
</div>
|
||||
|
||||
<div class="sec">
|
||||
<div class="sec-h"><h3 id="ntH"></h3><span class="live"><span class="dot"></span><span id="ntLive"></span></span></div>
|
||||
<div class="nts" id="nts"></div>
|
||||
</div>
|
||||
|
||||
<div class="foot">示例占位内容 · 数字仅作演示</div>
|
||||
</div>
|
||||
|
||||
<script src="../../guangchang/topics.js"></script>
|
||||
<script src="../../guangchang/data.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var $ = function (s) { return document.querySelector(s); };
|
||||
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
|
||||
var H = location.hash;
|
||||
var CAT = {
|
||||
family: { name: '家庭婚姻亭', short: '家庭婚姻', col: '#E0566F', tl: '#FFEDF1', ti: '#C23A55' },
|
||||
work: { name: '职场长椅', short: '职场', col: '#3A72B8', tl: '#E9F1FB', ti: '#2F64A8' },
|
||||
baby: { name: '经验树下', short: '经验', col: '#2E8A7C', tl: '#E3F3EF', ti: '#21705F' }
|
||||
};
|
||||
var ORDER = ['family', 'work', 'baby'];
|
||||
var cur = '';
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); };
|
||||
var hs = function (s) { var x = 7; for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
|
||||
var POOL = [];
|
||||
for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i);
|
||||
for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
|
||||
var av = function (name) { return '../../assets/img/mom/' + POOL[hs(name || '妈妈') % POOL.length] + '.jpg'; };
|
||||
var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : String(n).replace(/\B(?=(\d{3})+$)/g, ','); };
|
||||
var go = function (q) { location.href = '../../guangchang/' + q + H; };
|
||||
|
||||
/* 话题按分类 + 笔记(带 话题id-序号) */
|
||||
var BY = { family: [], work: [], baby: [] };
|
||||
T.forEach(function (t) { if (BY[t.cat]) BY[t.cat].push(t); });
|
||||
var NOTES = { family: [], work: [], baby: [] };
|
||||
T.forEach(function (t) {
|
||||
var d = D[t.id]; if (!d || !BY[t.cat]) return;
|
||||
d.notes.forEach(function (n, k) { NOTES[t.cat].push({ n: n, t: t, id: t.id + '-' + (k + 1), k: k }); });
|
||||
});
|
||||
/* 每类:带照片的排前面一些,并按 序号 轮流穿插不同话题 */
|
||||
ORDER.forEach(function (c) {
|
||||
NOTES[c].sort(function (a, b) { return (a.k - b.k) || ((b.n.photo ? 1 : 0) - (a.n.photo ? 1 : 0)) || (hs(a.id) % 97 - hs(b.id) % 97); });
|
||||
});
|
||||
var talkOf = function (c) { return BY[c].reduce(function (s, t) { return s + t.talk; }, 0); };
|
||||
|
||||
/* 统计 */
|
||||
var all = 0;
|
||||
ORDER.forEach(function (c) { var n = talkOf(c); all += n; $('#cnt-' + c).textContent = fmt(n) + ' 人在聊'; });
|
||||
$('#nowN').textContent = fmt(all);
|
||||
var d0 = new Date(Date.now() + (new Date().getTimezoneOffset() + 480) * 6e4), hh = d0.getHours(); /* 一律按北京时间 */
|
||||
$('#clock').textContent = (hh < 10 ? '0' : '') + hh + ':' + (d0.getMinutes() < 10 ? '0' : '') + d0.getMinutes();
|
||||
$('#tod').textContent = hh < 5 ? '深夜' : hh < 9 ? '清晨' : hh < 12 ? '上午' : hh < 14 ? '中午' : hh < 18 ? '午后' : hh < 20 ? '傍晚' : '夜里';
|
||||
if (hh >= 18 || hh < 5) $('#wxs').textContent = '晚风 · 微凉';
|
||||
|
||||
/* ---------- 地图上的妈妈和气泡 ---------- */
|
||||
/* 坐标:map 宽 351 高 440 的百分比 */
|
||||
var P = function (x, y) { return 'left:' + (x / 351 * 100).toFixed(2) + '%;top:' + (y / 440 * 100).toFixed(2) + '%'; };
|
||||
var SPOTS = {
|
||||
family: { moms: [[42, 176, 0], [80, 186, 1], [150, 148, 0], [30, 70, 1]], bub: { x: 20, y: 54, cls: 'tl', w: 150 } },
|
||||
work: { moms: [[254, 202, 1], [334, 212, 0], [300, 244, 0]], bub: { x: 194, y: 262, cls: 'br', w: 150 } },
|
||||
baby: { moms: [[192, 380, 0], [56, 408, 1], [150, 410, 1]], bub: { x: 178, y: 360, cls: 'tl', w: 150 } }
|
||||
};
|
||||
var BUBIX = { family: 0, work: 0, baby: 0 };
|
||||
var momsHTML = '';
|
||||
ORDER.forEach(function (c) {
|
||||
var s = SPOTS[c], ns = NOTES[c];
|
||||
s.moms.forEach(function (m, j) {
|
||||
var a = ns[(j * 5 + 2) % ns.length].n.author;
|
||||
momsHTML += '<span class="mom' + (m[2] ? ' sm' : '') + ' m-' + c + '" style="' + P(m[0], m[1]) + '"><i style="background-image:url(' + av(a) + ');animation-delay:' + (-(j * 0.9 + ORDER.indexOf(c) * 0.5)).toFixed(1) + 's"></i></span>';
|
||||
});
|
||||
var b = s.bub;
|
||||
/* 气泡锚点:tl = 尾巴在左下,框在锚点右上方;tr = 尾巴在右下 */
|
||||
var st = 'left:' + (b.x / 351 * 100).toFixed(2) + '%;' + (b.cls === 'br' ? 'top:' + (b.y / 440 * 100).toFixed(2) + '%' : 'bottom:' + ((440 - b.y) / 440 * 100).toFixed(2) + '%');
|
||||
momsHTML += '<div class="bub ' + b.cls + ' b-' + c + '" style="--zc:' + CAT[c].col + ';' + st + ';width:' + b.w + 'px"><span></span></div>';
|
||||
});
|
||||
$('#moms').innerHTML = momsHTML;
|
||||
function setBub(c) {
|
||||
var list = BY[c], t = list[BUBIX[c] % list.length];
|
||||
var el = $('.b-' + c + ' span');
|
||||
el.innerHTML = '<em>#</em>' + esc(t.name);
|
||||
}
|
||||
ORDER.forEach(setBub);
|
||||
var tick = 0;
|
||||
setInterval(function () {
|
||||
var c = ORDER[tick++ % 3];
|
||||
if (cur && c !== cur) c = cur;
|
||||
var b = $('.b-' + c); b.classList.add('out');
|
||||
setTimeout(function () { BUBIX[c]++; setBub(c); b.classList.remove('out'); }, 320);
|
||||
}, 2200);
|
||||
|
||||
/* ---------- 路牌 ---------- */
|
||||
$('#posts').innerHTML = [['', '全部', '#F4593C']].concat(ORDER.map(function (c) { return [c, CAT[c].short, CAT[c].col]; })).map(function (x) {
|
||||
return '<button data-cat="' + x[0] + '" style="--zc:' + x[2] + '"><i></i>' + x[1] + '</button>';
|
||||
}).join('');
|
||||
|
||||
/* ---------- 列表 ---------- */
|
||||
var expanded = false;
|
||||
function topicRow(t) {
|
||||
var c = CAT[t.cat], d = D[t.id];
|
||||
var who = d ? d.notes.slice(0, 3).map(function (n) { return '<i style="background-image:url(' + av(n.author) + ')"></i>'; }).join('') : '';
|
||||
return '<button class="tp" data-t="' + t.id + '" style="--tl:' + c.tl + ';--ti:' + c.ti + '">' +
|
||||
'<span class="ph">' + (t.ph ? '<img loading="lazy" src="../../' + t.ph + '" alt="">' : '') + '<b>' + esc(t.g) + '</b></span>' +
|
||||
'<span class="tx"><span class="nm">' + esc(t.name) + '</span>' +
|
||||
'<span class="mt">' + (cur ? '' : '<span class="k">' + c.short + '</span>') + (t.hot ? '<span class="hot">热聊</span>' : '') +
|
||||
'<span class="stack">' + who + '</span><span>' + fmt(t.talk) + ' 人在聊</span></span></span>' +
|
||||
'<span class="go"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round"><path d="M9 5l7 7-7 7"/></svg></span></button>';
|
||||
}
|
||||
function noteCard(o) {
|
||||
var n = o.n, t = o.t, c = CAT[t.cat];
|
||||
var vis = n.photo ? '<span class="pic"><img loading="lazy" src="../../guangchang/' + n.photo + '" alt=""></span>'
|
||||
: '<span class="cv" style="--c1:' + t.c[0] + ';--c2:' + t.c[1] + '"><span class="wm">' + esc(t.g) + '</span><b>' + esc(n.cover) + '</b><small>' + esc(n.coverSub || '') + '</small></span>';
|
||||
return '<button class="nt" data-t="' + t.id + '" data-n="' + o.id + '" style="--tl:' + c.tl + ';--ti:' + c.ti + '">' + vis +
|
||||
'<span class="bd"><span class="tg"># ' + esc(t.name) + '</span><h4>' + esc(n.title) + '</h4><p>' + esc((n.body || '').replace(/\n/g, ' ')) + '</p>' +
|
||||
'<span class="ft"><i style="background-image:url(' + av(n.author) + ')"></i><span class="au">' + esc(n.author) + '</span><span class="st">· ' + esc(n.stage) + '</span>' +
|
||||
'<span class="lk"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z"/></svg>' + fmt(n.likes) + '</span></span></span></button>';
|
||||
}
|
||||
var MAIL = '<button class="card-mail" id="mailcard"><span class="tx"><b>给广场写一封信</b><span>你的故事被选中,送 <em>¥30 现金 + 500 兜豆</em></span></span><span class="stamp"><div><b>¥30</b><small>+500兜豆</small></div></span></button>';
|
||||
|
||||
function render() {
|
||||
var map = $('#map');
|
||||
map.className = 'map f-' + (cur || 'all');
|
||||
ORDER.forEach(function (c) {
|
||||
var dim = cur && c !== cur;
|
||||
document.querySelectorAll('.m-' + c + ',.b-' + c).forEach(function (el) { el.classList.toggle('dim', !!dim); });
|
||||
});
|
||||
document.querySelectorAll('#posts button').forEach(function (b) { b.classList.toggle('on', b.dataset.cat === cur); });
|
||||
|
||||
var col = cur ? CAT[cur].col : '#F4593C';
|
||||
document.documentElement.style.setProperty('--zc', col);
|
||||
var tops;
|
||||
if (cur) tops = BY[cur].slice().sort(function (a, b) { return b.hot - a.hot || b.talk - a.talk; });
|
||||
else { tops = []; for (var k = 0; k < 10; k++) ORDER.forEach(function (c) { var l = BY[c].slice().sort(function (a, b) { return b.hot - a.hot || b.talk - a.talk; }); if (l[k]) tops.push(l[k]); }); }
|
||||
var lim = expanded ? tops.length : 4;
|
||||
$('#tpH').innerHTML = cur ? '此刻在<em>' + CAT[cur].name + '</em>聊' : '此刻<em>广场上</em>在聊';
|
||||
var tl = (cur ? BY[cur] : T).slice(0, 4);
|
||||
$('#tpStack').innerHTML = tl.map(function (t) { return '<i style="background-image:url(' + av(t.id + t.name) + ')"></i>'; }).join('');
|
||||
$('#tps').innerHTML = tops.slice(0, lim).map(topicRow).join('');
|
||||
var mb = $('#more');
|
||||
mb.classList.toggle('hide', tops.length <= 4);
|
||||
mb.textContent = expanded ? '收起' : '这个角落还有 ' + (tops.length - 4) + ' 个话题';
|
||||
|
||||
var ns;
|
||||
if (cur) ns = NOTES[cur].slice(0, 18);
|
||||
else { ns = []; for (k = 0; ns.length < 21; k++) { var any = false; ORDER.forEach(function (c) { if (NOTES[c][k]) { ns.push(NOTES[c][k]); any = true; } }); if (!any) break; } }
|
||||
$('#ntH').innerHTML = cur ? '坐在' + CAT[cur].short + '角落的分享' : '大家刚写下的';
|
||||
$('#ntLive').textContent = fmt(cur ? Math.round(talkOf(cur) / 37) : Math.round(all / 37)) + ' 人正在看';
|
||||
var h = ns.map(noteCard);
|
||||
h.splice(Math.min(3, h.length), 0, MAIL);
|
||||
$('#nts').innerHTML = h.join('');
|
||||
}
|
||||
function setCat(c) {
|
||||
if (c === cur) c = c ? '' : c;
|
||||
cur = c; expanded = false; render();
|
||||
if (cur) { BUBIX[cur]++; setBub(cur); }
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
var z = e.target.closest('[data-cat]');
|
||||
if (z) { setCat(z.dataset.cat); return; }
|
||||
var n = e.target.closest('[data-n]');
|
||||
if (n) { go('?t=' + n.dataset.t + '&n=' + n.dataset.n); return; }
|
||||
var t = e.target.closest('[data-t]');
|
||||
if (t) { go('?t=' + t.dataset.t); return; }
|
||||
if (e.target.closest('#more')) { expanded = !expanded; render(); return; }
|
||||
if (e.target.closest('#mailbox,#mailcard')) { go(cur ? '?c=' + cur : ''); return; }
|
||||
});
|
||||
$('#mine').addEventListener('click', function () { go('?mine=1'); });
|
||||
$('#back').addEventListener('click', function () { history.length > 1 ? history.back() : location.href = '../../' + location.hash; });
|
||||
|
||||
var sc = $('#sc');
|
||||
sc.addEventListener('scroll', function () { $('#top').classList.toggle('on', sc.scrollTop > 4); }, { passive: true });
|
||||
|
||||
/* 禁止下拉回弹:往上找能朝该方向滚的容器,找不到才拦 */
|
||||
var sx = 0, sy = 0;
|
||||
document.addEventListener('touchstart', function (e) { if (e.touches.length !== 1) return; sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
|
||||
document.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
|
||||
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
|
||||
if (Math.abs(dy) <= Math.abs(dx)) return;
|
||||
var el = e.target;
|
||||
while (el && el !== document.body && el !== document.documentElement) {
|
||||
if (el.nodeType === 1) {
|
||||
var oy = getComputedStyle(el).overflowY;
|
||||
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
|
||||
if (dy > 0 && el.scrollTop > 0) return;
|
||||
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
|
||||
}
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
if (e.cancelable) e.preventDefault();
|
||||
}, { passive: false });
|
||||
|
||||
render();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
346
demo/gc-v3/index.html
Normal file
346
demo/gc-v3/index.html
Normal file
@@ -0,0 +1,346 @@
|
||||
<!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,viewport-fit=cover">
|
||||
<title>孕妈广场 · 留言墙</title>
|
||||
<!-- 效果稿 V3 · 留言墙(软木板便签):仅演示列表页视觉,点话题/笔记跳现版广场详情。数据读 guangchang/topics.js + data.js -->
|
||||
<style>
|
||||
:root{
|
||||
--brand:#F4593C;--ink:#3A2A1E;--ink2:#6E5846;
|
||||
--fam:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
|
||||
--hand:"Kaiti SC","STKaiti","KaiTi","BiauKai","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
|
||||
}
|
||||
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
|
||||
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Segoe UI",Roboto,sans-serif;
|
||||
color:var(--ink);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5;-webkit-text-size-adjust:100%;background:#C99D70}
|
||||
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
|
||||
|
||||
/* ---------- 软木板:唯一滚动容器 ---------- */
|
||||
.cork{background-color:#CFA273;
|
||||
background-image:
|
||||
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .35 0 0 0 0 .2 0 0 0 0 .08 0 0 0 1.6 -.55'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E"),
|
||||
radial-gradient(rgba(255,236,200,.35) 1px,transparent 1.6px),
|
||||
radial-gradient(rgba(110,60,25,.28) 1.2px,transparent 1.8px);
|
||||
background-size:180px 180px,13px 11px,9px 12px;
|
||||
background-position:0 0,3px 5px,0 0}
|
||||
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none}
|
||||
#sc::-webkit-scrollbar{display:none}
|
||||
#sc::before{content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
|
||||
background:radial-gradient(120% 70% at 50% 30%,rgba(255,230,190,.18),rgba(70,35,10,.22) 100%)}
|
||||
|
||||
/* ---------- 顶部:木框横梁 + 标签夹 ---------- */
|
||||
.top{position:sticky;top:0;z-index:30;padding-top:env(safe-area-inset-top)}
|
||||
.rail{position:relative;height:50px;display:flex;align-items:center;padding:0 8px;
|
||||
background:linear-gradient(180deg,#9A6A43,#80542F 70%,#6E4627);
|
||||
box-shadow:inset 0 1px 0 rgba(255,220,180,.35),inset 0 -2px 0 rgba(0,0,0,.18),0 3px 6px rgba(60,30,10,.35)}
|
||||
.rail::before{content:"";position:absolute;inset:0;opacity:.35;pointer-events:none;
|
||||
background:repeating-linear-gradient(178deg,rgba(255,220,170,.0) 0 5px,rgba(255,220,170,.18) 6px,rgba(60,30,10,.0) 7px 11px,rgba(60,30,10,.25) 12px 13px)}
|
||||
.bk{position:relative;width:36px;height:36px;display:grid;place-items:center;border-radius:50%;color:#FFF3E2}
|
||||
.bk:active{background:rgba(0,0,0,.15)}
|
||||
.bk svg{width:22px;height:22px}
|
||||
.ttl{position:relative;flex:1;display:flex;justify-content:center}
|
||||
.ttl b{display:inline-block;padding:4px 14px 3px;background:#F7EEDC;color:#5A3A22;font-size:17px;font-weight:900;letter-spacing:2px;
|
||||
transform:rotate(-1.2deg);box-shadow:0 2px 3px rgba(0,0,0,.3);border-radius:1px}
|
||||
.ttl b::after{content:"";position:absolute}
|
||||
.vtag{position:relative;width:60px;text-align:right;font-size:11px;line-height:1.2;color:rgba(255,240,220,.7);white-space:nowrap}
|
||||
.bk{margin-right:24px}
|
||||
|
||||
.tabs{position:relative;display:flex;gap:8px;padding:12px 12px 6px;justify-content:space-between}
|
||||
.tabs::before{content:"";position:absolute;left:0;right:0;top:0;height:6px;background:linear-gradient(rgba(50,25,8,.35),transparent)}
|
||||
.tab{position:relative;flex:1;min-width:0;height:44px;margin-top:6px;border-radius:2px 2px 4px 4px;background:#F6EEDD;color:#6A5240;
|
||||
font-size:14px;font-weight:800;display:flex;align-items:center;justify-content:center;gap:4px;
|
||||
box-shadow:0 1px 1px rgba(0,0,0,.15),0 6px 8px -4px rgba(60,30,10,.45);transition:transform .18s,background .18s,color .18s}
|
||||
.tab:nth-child(1){transform:rotate(-1.5deg)}
|
||||
.tab:nth-child(2){transform:rotate(1deg)}
|
||||
.tab:nth-child(3){transform:rotate(-.8deg)}
|
||||
.tab:nth-child(4){transform:rotate(1.4deg)}
|
||||
.tab i{font-style:normal;width:8px;height:8px;border-radius:50%;background:var(--tc);flex:none}
|
||||
.tab.on{background:var(--tc);color:#fff;transform:translateY(3px) rotate(0) scale(1.04)}
|
||||
.tab.on i{background:#fff}
|
||||
/* 黑色长尾夹 */
|
||||
.tab .clip{position:absolute;top:-10px;left:50%;width:26px;height:12px;margin-left:-13px;border-radius:3px 3px 1px 1px;
|
||||
background:linear-gradient(#4A4A4E,#1F1F22);box-shadow:0 2px 2px rgba(0,0,0,.35)}
|
||||
.tab .clip::before{content:"";position:absolute;left:5px;right:5px;top:-7px;height:10px;border:2px solid #A9ABB0;border-bottom:0;border-radius:6px 6px 0 0}
|
||||
.tab.on .clip{background:linear-gradient(#F27A5A,#C9452B)}
|
||||
|
||||
/* ---------- 墙面 ---------- */
|
||||
main{position:relative;z-index:1;padding:8px 12px calc(30px + env(safe-area-inset-bottom))}
|
||||
.hint{display:flex;justify-content:center;margin:6px 0 16px}
|
||||
.hint span{display:inline-block;padding:5px 12px;background:rgba(255,248,235,.85);font-family:var(--hand);font-size:14px;color:#6A4A30;
|
||||
transform:rotate(-.8deg);box-shadow:0 2px 4px rgba(60,30,10,.25)}
|
||||
.hint em{font-style:normal;color:var(--brand);font-weight:800}
|
||||
.wall{display:flex;gap:14px;align-items:flex-start}
|
||||
.col{flex:1;min-width:0;display:flex;flex-direction:column;gap:22px}
|
||||
.col:nth-child(2){padding-top:18px}
|
||||
|
||||
.it{position:relative;display:block;width:100%;text-align:left;color:var(--ink);transform:rotate(var(--r,0deg));transition:transform .15s}
|
||||
.it:active{transform:rotate(0) scale(.97)}
|
||||
|
||||
/* 便签纸:话题 */
|
||||
.note{padding:20px 13px 12px;min-height:150px;background:linear-gradient(170deg,var(--n1),var(--n2));border-radius:1px 1px 2px 14px/1px 1px 2px 10px;
|
||||
box-shadow:0 1px 1px rgba(0,0,0,.12),0 10px 14px -8px rgba(55,25,5,.55),inset 0 -14px 18px -14px rgba(120,70,20,.18);overflow:hidden}
|
||||
.note::after{content:"";position:absolute;right:0;bottom:0;width:26px;height:22px;
|
||||
background:linear-gradient(135deg,rgba(0,0,0,0) 48%,rgba(90,50,20,.18) 50%,rgba(255,255,255,.55) 60%,var(--n2) 100%)}
|
||||
.note .wm{position:absolute;right:6px;bottom:4px;font-size:64px;line-height:1;font-weight:900;color:var(--k);opacity:.08;font-family:var(--hand)}
|
||||
.note .lb{position:relative;display:inline-block;font-size:11px;font-weight:800;color:var(--k);padding:0 6px;border:1.5px solid var(--k);border-radius:3px;line-height:17px;opacity:.9}
|
||||
.note h3{position:relative;margin:8px 0 12px;font-size:15px;line-height:1.45;font-weight:900;color:#3A2618;letter-spacing:.2px}
|
||||
.note h3::before{content:"# ";color:var(--k)}
|
||||
.note .mt{position:relative;font-size:11px;color:#7A6250;display:flex;align-items:center;gap:6px}
|
||||
.note .mt b{color:var(--k);font-weight:800}
|
||||
.note .join{position:relative;display:inline-block;margin-top:8px;font-family:var(--hand);font-size:14px;color:var(--k);border-bottom:1.5px dashed var(--k);line-height:1.3}
|
||||
.hot{position:absolute;top:10px;right:10px;width:32px;height:32px;border-radius:50%;border:2px solid rgba(214,58,40,.75);color:rgba(214,58,40,.85);
|
||||
font-size:12px;font-weight:900;display:grid;place-items:center;transform:rotate(14deg);font-family:var(--hand)}
|
||||
.hot::before{content:"";position:absolute;inset:2px;border:1px dashed rgba(214,58,40,.55);border-radius:50%}
|
||||
|
||||
/* 胶带(半透明 + 锯齿边) */
|
||||
.tape{position:absolute;z-index:2;top:-9px;left:50%;width:62px;height:20px;margin-left:-31px;transform:rotate(var(--tr,-4deg));
|
||||
background:var(--tp,rgba(255,252,240,.55));box-shadow:0 1px 2px rgba(0,0,0,.12);
|
||||
-webkit-clip-path:polygon(0 8%,4% 0,8% 10%,12% 0,16% 8%,20% 0,80% 0,84% 9%,88% 0,92% 8%,96% 0,100% 10%,100% 92%,96% 100%,92% 90%,88% 100%,84% 92%,80% 100%,20% 100%,16% 90%,12% 100%,8% 92%,4% 100%,0 90%);
|
||||
clip-path:polygon(0 8%,4% 0,8% 10%,12% 0,16% 8%,20% 0,80% 0,84% 9%,88% 0,92% 8%,96% 0,100% 10%,100% 92%,96% 100%,92% 90%,88% 100%,84% 92%,80% 100%,20% 100%,16% 90%,12% 100%,8% 92%,4% 100%,0 90%)}
|
||||
.tape.w1{--tp:repeating-linear-gradient(45deg,rgba(255,180,190,.6) 0 6px,rgba(255,255,255,.45) 6px 12px)}
|
||||
.tape.w2{--tp:repeating-linear-gradient(90deg,rgba(150,200,240,.55) 0 4px,rgba(255,255,255,.4) 4px 8px)}
|
||||
.tape.w3{--tp:rgba(170,225,205,.6)}
|
||||
.tape.cn{top:-6px;left:-10px;margin:0;width:46px;height:16px;--tr:-38deg}
|
||||
|
||||
/* 图钉 */
|
||||
.pin{position:absolute;z-index:3;top:-7px;left:50%;width:16px;height:16px;margin-left:-8px;border-radius:50%;
|
||||
background:radial-gradient(circle at 34% 30%,rgba(255,255,255,.9) 0 2px,var(--pc,#E2483A) 3.5px,var(--pd,#9B2418) 100%);
|
||||
box-shadow:3px 4px 3px -1px rgba(40,15,0,.45)}
|
||||
.pin.b{--pc:#3F7FD0;--pd:#1D4A86}.pin.g{--pc:#36A08F;--pd:#17594E}.pin.y{--pc:#F2B632;--pd:#A8740C}
|
||||
|
||||
/* 拍立得 */
|
||||
.pola{background:#FCFAF5;padding:8px 8px 10px;border-radius:2px;
|
||||
box-shadow:0 1px 1px rgba(0,0,0,.14),0 12px 16px -8px rgba(55,25,5,.55)}
|
||||
.pola .ph{position:relative;aspect-ratio:4/5;overflow:hidden;background:#E8DFD2}
|
||||
.pola .ph img{width:100%;height:100%;object-fit:cover;display:block;filter:saturate(.92) contrast(1.02)}
|
||||
.pola .ph::after{content:"";position:absolute;inset:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06),inset 0 0 18px rgba(80,50,20,.18)}
|
||||
.pola .cap{margin:8px 2px 0;font-family:var(--hand);font-size:15px;line-height:1.4;color:#2E2118;font-weight:700;
|
||||
display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.by{display:flex;align-items:center;gap:6px;margin:8px 2px 0;font-size:11px;color:#8A7564;min-width:0}
|
||||
.by img{width:18px;height:18px;border-radius:50%;object-fit:cover;flex:none}
|
||||
.by .nm{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.by .lk{flex:none;display:flex;align-items:center;gap:2px}
|
||||
.by .lk svg{width:12px;height:12px}
|
||||
.ctag{position:absolute;z-index:2;left:14px;top:14px;font-size:11px;font-weight:800;color:#fff;padding:0 6px;line-height:18px;border-radius:2px;background:var(--k);box-shadow:0 1px 2px rgba(0,0,0,.25)}
|
||||
|
||||
/* 横格卡片:无图笔记 */
|
||||
.card{background:#FFFDF7;padding:18px 12px 12px 22px;border-radius:2px;
|
||||
background-image:linear-gradient(90deg,transparent 14px,rgba(224,86,111,.45) 14px,rgba(224,86,111,.45) 15px,transparent 15px),
|
||||
repeating-linear-gradient(180deg,transparent 0 23px,rgba(70,120,190,.18) 23px 24px);
|
||||
background-position:0 0,0 10px;
|
||||
box-shadow:0 1px 1px rgba(0,0,0,.12),0 10px 14px -8px rgba(55,25,5,.5)}
|
||||
.card .big{font-family:var(--hand);font-size:19px;font-weight:800;line-height:24px;color:var(--k)}
|
||||
.card .sub{font-family:var(--hand);font-size:14px;line-height:24px;color:#5E4A3A}
|
||||
.card .tt{margin-top:6px;font-size:13px;line-height:1.5;color:#3A2A1E;font-weight:600;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||||
|
||||
/* 投稿:一叠空白便签 */
|
||||
.stack{position:relative;margin:8px 4px 6px 2px;text-align:left}
|
||||
.stack .sh{position:absolute;inset:0;background:#FFE58A;border-radius:1px;box-shadow:0 8px 10px -6px rgba(55,25,5,.5)}
|
||||
.stack .sh.a{transform:rotate(5deg) translate(5px,4px);background:#FFD7A8}
|
||||
.stack .sh.b{transform:rotate(-3.5deg) translate(-3px,3px);background:#FFF0B0}
|
||||
.stack .tp{position:relative;padding:22px 12px 12px;background:linear-gradient(170deg,#FFF6C4,#FFE98E);transform:rotate(-1deg);
|
||||
box-shadow:0 1px 1px rgba(0,0,0,.12),0 10px 14px -8px rgba(55,25,5,.55);
|
||||
background-image:linear-gradient(170deg,#FFF6C4,#FFE98E)}
|
||||
.stack .ln{height:22px;border-bottom:1.5px dashed rgba(150,100,30,.35)}
|
||||
.stack .wr{font-family:var(--hand);font-size:19px;font-weight:800;color:#5A3A1A;line-height:26px;display:flex;align-items:center;gap:6px}
|
||||
.stack .wr svg{width:20px;height:20px;color:var(--brand);flex:none}
|
||||
.stack .rw{margin-top:8px;font-size:12px;color:#7A5A3A;line-height:1.5}
|
||||
.stack .rw b{display:block;font-size:17px;color:var(--brand);font-weight:900;letter-spacing:.3px;line-height:1.35}
|
||||
.stack .go{display:inline-flex;align-items:center;margin-top:8px;padding:0 10px;height:26px;border-radius:13px;background:var(--brand);color:#fff;font-size:12px;font-weight:800;box-shadow:0 2px 4px rgba(200,60,30,.35)}
|
||||
|
||||
.more{display:block;margin:26px auto 4px;padding:9px 18px;background:#F7EEDC;color:#5A3A22;font-size:14px;font-weight:800;transform:rotate(-1deg);box-shadow:0 6px 10px -5px rgba(55,25,5,.55)}
|
||||
.foot{margin-top:18px;text-align:center;font-size:11px;color:rgba(60,30,10,.65)}
|
||||
|
||||
/* 投稿规则便签弹层 */
|
||||
.mask{position:fixed;inset:0;z-index:50;background:rgba(40,20,5,.45);display:none;align-items:center;justify-content:center;padding:24px}
|
||||
.mask.show{display:flex}
|
||||
.rule{position:relative;width:100%;max-width:320px;padding:28px 20px 20px;background:linear-gradient(170deg,#FFF8D6,#FFEDA6);transform:rotate(-1deg);box-shadow:0 18px 30px -10px rgba(0,0,0,.5)}
|
||||
.rule h3{margin:0 0 6px;font-family:var(--hand);font-size:22px;color:#4A2E14}
|
||||
.rule .rb{font-size:13px;color:#7A5A3A}.rule .rb b{color:var(--brand);font-size:20px;font-weight:900}
|
||||
.rule ol{margin:12px 0 16px;padding-left:20px;font-size:14px;line-height:1.7;color:#4A3828}
|
||||
.rule .ok{display:block;width:100%;height:42px;border-radius:21px;background:var(--brand);color:#fff;font-size:15px;font-weight:800}
|
||||
.rule .x{position:absolute;right:8px;top:8px;width:32px;height:32px;font-size:20px;color:#8A6A4A}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="sc" class="cork">
|
||||
<header class="top cork">
|
||||
<div class="rail">
|
||||
<button class="bk" id="back" type="button" aria-label="返回"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
|
||||
<div class="ttl"><b>孕妈广场</b></div>
|
||||
<div class="vtag">效果稿<br>V3·留言墙</div>
|
||||
</div>
|
||||
<nav class="tabs" id="tabs"></nav>
|
||||
</header>
|
||||
<main>
|
||||
<div class="hint"><span id="hint"></span></div>
|
||||
<div class="wall" id="wall"><div class="col"></div><div class="col"></div></div>
|
||||
<button class="more hide" id="more" type="button">再往下翻一面墙</button>
|
||||
<div class="foot">墙上内容为示例占位 · 篇数、在聊、点赞均为演示数字</div>
|
||||
</main>
|
||||
</div>
|
||||
<div class="mask" id="mask">
|
||||
<div class="rule">
|
||||
<span class="tape" style="--tr:3deg"></span>
|
||||
<button class="x" id="rx" type="button" aria-label="关闭">×</button>
|
||||
<h3>写一张贴上来</h3>
|
||||
<div class="rb">投稿被选中,每篇奖励 <b>¥30</b> 现金 + <b>500</b> 兜豆</div>
|
||||
<ol><li>挑一张你有话说的话题便签</li><li>写下你的真实经历,配图更好</li><li>编辑挑中后贴上墙,奖励发给你</li></ol>
|
||||
<button class="ok" id="rgo" type="button">去写我的故事</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../../guangchang/topics.js"></script>
|
||||
<script src="../../guangchang/data.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var $ = function (s) { return document.querySelector(s); };
|
||||
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); };
|
||||
var hs = function (s) { var x = 7; s = String(s); for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
|
||||
var AV = []; for (var i = 1; i <= 22; i++) AV.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) AV.push('p' + (i < 10 ? '0' : '') + i);
|
||||
var avSrc = function (n) { return '../../assets/img/mom/' + AV[hs(n) % AV.length] + '.jpg'; };
|
||||
var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1) + '万' : String(n); };
|
||||
|
||||
var CATS = [['', '全部', '#F4593C'], ['family', '家庭婚姻', '#E0566F'], ['work', '职场', '#3A72B8'], ['baby', '经验', '#2E8A7C']];
|
||||
var CN = { family: '家庭婚姻', work: '职场', baby: '经验' };
|
||||
var K = { family: '#C23A55', work: '#2F64A8', baby: '#21705F' };
|
||||
var PAPER = {
|
||||
family: [['#FFE3E8', '#FFC9D4'], ['#FFF1C2', '#FFE08A'], ['#FFE6D6', '#FFCDB0']],
|
||||
work: [['#E2EEFC', '#C3D9F4'], ['#FFF4C6', '#FFE495'], ['#E8E6FA', '#D1CDF2']],
|
||||
baby: [['#DDF4EC', '#BDE6D8'], ['#F4F7C8', '#E5EC9C'], ['#FFF1C2', '#FFE08A']]
|
||||
};
|
||||
var PINS = ['', 'b', 'g', 'y'], TAPES = ['', 'w1', 'w2', 'w3'];
|
||||
var heart = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 20s-7-4.4-9.2-9A5 5 0 0 1 12 6.2 5 5 0 0 1 21.2 11C19 15.6 12 20 12 20z"/></svg>';
|
||||
|
||||
var cat = new URLSearchParams(location.search).get('c') || '';
|
||||
if (!CN[cat]) cat = '';
|
||||
var LIMIT = 28, shown = LIMIT, ITEMS = [];
|
||||
|
||||
function go(t, n) {
|
||||
location.href = '../../guangchang/?t=' + encodeURIComponent(t) + (n ? '&n=' + encodeURIComponent(n) : '') + location.hash;
|
||||
}
|
||||
$('#back').onclick = function () { if (history.length > 1) history.back(); else location.href = '../../' + location.hash; };
|
||||
|
||||
function renderTabs() {
|
||||
$('#tabs').innerHTML = CATS.map(function (c) {
|
||||
return '<button type="button" class="tab' + (c[0] === cat ? ' on' : '') + '" data-c="' + c[0] + '" style="--tc:' + c[2] + '"><span class="clip"></span>' + (c[0] ? '<i></i>' : '') + c[1] + '</button>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
/* 墙上元素顺序:热门话题先贴;每个话题后面钉 1 张它的笔记(有照片→拍立得,无照片→横格卡),第二轮再补剩下的笔记 */
|
||||
function build() {
|
||||
var list = T.filter(function (t) { return !cat || t.cat === cat; });
|
||||
if (!cat) { /* 全部:三类轮流排,热门在前 */
|
||||
var by = ['family', 'work', 'baby'].map(function (c) { return list.filter(function (t) { return t.cat === c; }).sort(function (a, b) { return b.hot - a.hot; }); });
|
||||
list = []; for (var r = 0; r < 20; r++) by.forEach(function (a) { if (a[r]) list.push(a[r]); });
|
||||
} else list = list.slice().sort(function (a, b) { return b.hot - a.hot; });
|
||||
var out = [{ k: 'stack' }], rest = [];
|
||||
list.forEach(function (t) {
|
||||
var ns = ((D[t.id] || {}).notes || []).map(function (n, i) { return { k: 'n', t: t, n: n, i: i }; });
|
||||
ns.sort(function (a, b) { return (b.n.photo ? 1 : 0) - (a.n.photo ? 1 : 0); });
|
||||
out.push({ k: 't', t: t });
|
||||
if (ns[0]) out.push(ns[0]);
|
||||
rest = rest.concat(ns.slice(1));
|
||||
});
|
||||
/* 剩下的笔记:拍立得和横格卡交替钉,墙面不单调 */
|
||||
var byL = function (a, b) { return b.n.likes - a.n.likes; };
|
||||
var ph = rest.filter(function (o) { return o.n.photo; }).sort(byL), tx = rest.filter(function (o) { return !o.n.photo; }).sort(byL), mix = [];
|
||||
while (ph.length || tx.length) { if (tx.length) mix.push(tx.shift()); if (ph.length) mix.push(ph.shift()); }
|
||||
/* 话题便签 + 首篇 为主线,每 3 张插一张补充笔记,横格卡不会全挤到墙底 */
|
||||
var res = [out.shift()], j = 0;
|
||||
while (out.length) { res.push(out.shift()); if (++j % 3 === 0 && mix.length) res.push(mix.shift()); }
|
||||
return res.concat(mix);
|
||||
}
|
||||
|
||||
function rot(seed, amp) { return ((hs(seed) % 1000) / 1000 * 2 - 1) * amp; }
|
||||
|
||||
function html(o, idx) {
|
||||
if (o.k === 'stack') {
|
||||
return '<button type="button" class="it stack" data-w="1"><span class="sh a"></span><span class="sh b"></span><div class="tp">' +
|
||||
'<span class="pin"></span><div class="wr"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20l4-1 11-11-3-3L5 16z"/><path d="M14 6l3 3"/></svg>写一张贴上来</div>' +
|
||||
'<div class="ln"></div><div class="rw">被选中奖励<b>¥30 + 500 兜豆</b></div><span class="go">怎么参与 ›</span></div></button>';
|
||||
}
|
||||
var t = o.t, k = K[t.cat];
|
||||
if (o.k === 't') {
|
||||
var p = PAPER[t.cat][hs(t.id) % 3];
|
||||
var tp = TAPES[hs(t.id + 'tp') % 4];
|
||||
return '<button type="button" class="it note" data-t="' + t.id + '" style="--r:' + rot(t.id, 2.6).toFixed(2) + 'deg;--n1:' + p[0] + ';--n2:' + p[1] + ';--k:' + k + '">' +
|
||||
'<span class="tape ' + tp + '" style="--tr:' + rot(t.id + 'r', 6).toFixed(1) + 'deg"></span>' +
|
||||
'<span class="wm">' + esc(t.g) + '</span>' + (t.hot ? '<span class="hot">热</span>' : '') +
|
||||
'<span class="lb">' + CN[t.cat] + '</span><h3>' + esc(t.name) + '</h3>' +
|
||||
'<div class="mt"><span><b>' + t.n + '</b> 篇</span><span>·</span><span><b>' + fmt(t.talk) + '</b> 人在聊</span></div>' +
|
||||
'<span class="join">+ 我也说两句</span></button>';
|
||||
}
|
||||
var n = o.n, nid = t.id + '-' + (o.i + 1), pin = PINS[hs(nid) % 4];
|
||||
var by = '<div class="by"><img loading="lazy" src="' + avSrc(n.author) + '" alt=""><span class="nm">' + esc(n.author) + '</span><span class="lk">' + heart + fmt(n.likes) + '</span></div>';
|
||||
if (n.photo) {
|
||||
return '<button type="button" class="it pola" data-t="' + t.id + '" data-n="' + nid + '" style="--r:' + rot(nid, 3).toFixed(2) + 'deg;--k:' + k + '">' +
|
||||
'<span class="pin ' + pin + '"></span><div class="ph"><img loading="lazy" src="../../guangchang/' + esc(n.photo) + '" alt=""></div>' +
|
||||
'<span class="ctag">' + CN[t.cat] + '</span><div class="cap">' + esc(n.title) + '</div>' + by + '</button>';
|
||||
}
|
||||
return '<button type="button" class="it card" data-t="' + t.id + '" data-n="' + nid + '" style="--r:' + rot(nid, 2.4).toFixed(2) + 'deg;--k:' + k + '">' +
|
||||
'<span class="tape cn ' + TAPES[hs(nid) % 4] + '"></span>' +
|
||||
'<div class="big">' + esc(n.cover || '') + '</div>' + (n.coverSub ? '<div class="sub">' + esc(n.coverSub) + '</div>' : '') +
|
||||
'<div class="tt">' + esc(n.title) + '</div>' + by + '</button>';
|
||||
}
|
||||
|
||||
function renderWall(reset) {
|
||||
var cols = document.querySelectorAll('#wall .col');
|
||||
if (reset) { cols[0].innerHTML = cols[1].innerHTML = ''; ITEMS = build(); shown = Math.min(LIMIT, ITEMS.length); }
|
||||
var start = reset ? 0 : +($('#wall').dataset.n || 0);
|
||||
for (var i = start; i < shown; i++) {
|
||||
var c = i === 0 ? cols[0] : (cols[0].offsetHeight <= cols[1].offsetHeight + 18 ? cols[0] : cols[1]);
|
||||
c.insertAdjacentHTML('beforeend', html(ITEMS[i], i));
|
||||
}
|
||||
$('#wall').dataset.n = shown;
|
||||
$('#more').classList.toggle('hide', shown >= ITEMS.length);
|
||||
$('#more').style.display = shown >= ITEMS.length ? 'none' : '';
|
||||
var nt = T.filter(function (t) { return !cat || t.cat === cat; }).length;
|
||||
$('#hint').innerHTML = (cat ? '「' + CN[cat] + '」' : '墙上') + '贴着 <em>' + nt + '</em> 个话题 · 挑一张聊聊';
|
||||
}
|
||||
|
||||
$('#tabs').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('[data-c]'); if (!b || b.dataset.c === cat) return;
|
||||
cat = b.dataset.c; renderTabs(); renderWall(true); $('#sc').scrollTop = 0;
|
||||
var q = new URLSearchParams(location.search); if (cat) q.set('c', cat); else q.delete('c');
|
||||
var s = q.toString(); history.replaceState(history.state, '', location.pathname + (s ? '?' + s : '') + location.hash);
|
||||
});
|
||||
$('#wall').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('.it'); if (!b) return;
|
||||
if (b.dataset.w) { $('#mask').classList.add('show'); return; }
|
||||
go(b.dataset.t, b.dataset.n || '');
|
||||
});
|
||||
$('#more').onclick = function () { shown = Math.min(ITEMS.length, shown + LIMIT); renderWall(false); };
|
||||
$('#rx').onclick = function () { $('#mask').classList.remove('show'); };
|
||||
$('#mask').addEventListener('click', function (e) { if (e.target === this) this.classList.remove('show'); });
|
||||
$('#rgo').onclick = function () { location.href = '../../guangchang/' + location.search.replace(/[?&]c=[^&]*/, '').replace(/^&/, '?') + location.hash; };
|
||||
|
||||
renderTabs(); renderWall(true);
|
||||
|
||||
/* 禁止下拉回弹:往上找能朝该方向滚的容器,找不到才拦 */
|
||||
var sx = 0, sy = 0;
|
||||
document.addEventListener('touchstart', function (e) { sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
|
||||
document.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
|
||||
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
|
||||
if (Math.abs(dy) <= Math.abs(dx)) return;
|
||||
var el = e.target;
|
||||
while (el && el !== document.body && el !== document.documentElement) {
|
||||
if (el.nodeType === 1) {
|
||||
var oy = getComputedStyle(el).overflowY;
|
||||
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
|
||||
if (dy > 0 && el.scrollTop > 0) return;
|
||||
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
|
||||
}
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
if (e.cancelable) e.preventDefault();
|
||||
}, { passive: false });
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
346
demo/gc-v4/index.html
Normal file
346
demo/gc-v4/index.html
Normal file
@@ -0,0 +1,346 @@
|
||||
<!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,viewport-fit=cover">
|
||||
<title>孕妈广场</title>
|
||||
<!-- 效果稿 V4 · 聊天广场:每个话题是一个「聊天室」,直接露出 2~3 条气泡;分类 = 顶部频道胶囊;投稿 = 底部输入条。演示页,不接后端。 -->
|
||||
<style>
|
||||
:root{
|
||||
--brand:#F4593C;--bg:#F5F6F8;--card:#fff;--ink:#1F2329;--ink2:#5B6170;--ink3:#9AA0AC;--line:#ECEDF1;
|
||||
--bub:#F3F4F7;--safe-t:env(safe-area-inset-top);--safe-b:env(safe-area-inset-bottom);
|
||||
}
|
||||
.k-family{--kf:#E0566F;--kl:#FDECEF}
|
||||
.k-work{--kf:#3A72B8;--kl:#E9F0FA}
|
||||
.k-baby{--kf:#2E8A7C;--kl:#E4F3F0}
|
||||
.k-all{--kf:#F4593C;--kl:#FEEDE8}
|
||||
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
|
||||
html,body{height:100%;overflow:hidden;background:var(--bg)}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Segoe UI",Roboto,sans-serif;color:var(--ink);font-size:14px;-webkit-font-smoothing:antialiased}
|
||||
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
|
||||
img{display:block}
|
||||
#sc{position:fixed;inset:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
|
||||
|
||||
/* ---------- 顶部 ---------- */
|
||||
.top{position:sticky;top:0;z-index:20;padding-top:var(--safe-t);background:rgba(255,255,255,.88);-webkit-backdrop-filter:blur(16px) saturate(170%);backdrop-filter:blur(16px) saturate(170%);transition:box-shadow .2s}
|
||||
.top.on{box-shadow:0 1px 0 var(--line),0 6px 18px rgba(30,35,45,.05)}
|
||||
.nav{height:46px;display:flex;align-items:center;padding:0 12px 0 6px;position:relative}
|
||||
.back{width:38px;height:38px;display:flex;align-items:center;justify-content:center;border-radius:50%}
|
||||
.back:active{background:rgba(0,0,0,.05)}
|
||||
.nav h1{font-size:17px;font-weight:700;margin-left:2px;letter-spacing:.5px}
|
||||
.nav .ver{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:11px;color:#B5BAC4;letter-spacing:.3px}
|
||||
/* 频道胶囊 */
|
||||
.chs{display:flex;gap:8px;padding:2px 14px 10px;overflow-x:auto;scrollbar-width:none}
|
||||
.chs::-webkit-scrollbar{display:none}
|
||||
.ch{flex:none;height:32px;padding:0 14px 0 11px;border-radius:16px;background:#F1F2F5;color:var(--ink2);font-size:14px;font-weight:600;display:flex;align-items:center;gap:3px;transition:background .2s,color .2s}
|
||||
.ch i{font-style:normal;font-weight:800;color:var(--kf);opacity:.85}
|
||||
.ch small{font-size:11px;font-weight:500;color:var(--ink3);margin-left:3px}
|
||||
.ch.on{background:var(--kf);color:#fff;box-shadow:0 4px 12px -4px var(--kf)}
|
||||
.ch.on i,.ch.on small{color:rgba(255,255,255,.85);opacity:1}
|
||||
|
||||
/* ---------- 此刻在线 ---------- */
|
||||
.live{margin:12px 14px 4px;padding:14px 14px 13px;border-radius:18px;background:#fff;position:relative;overflow:hidden}
|
||||
.live::before{content:"";position:absolute;right:-30px;top:-40px;width:150px;height:150px;border-radius:50%;background:radial-gradient(circle,rgba(244,89,60,.10),rgba(244,89,60,0) 70%)}
|
||||
.lv-h{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink2);position:relative}
|
||||
.dot{width:8px;height:8px;border-radius:50%;background:#2BC266;position:relative;flex:none}
|
||||
.dot::after{content:"";position:absolute;inset:-4px;border-radius:50%;background:#2BC266;opacity:.35;animation:pulse 1.8s ease-out infinite}
|
||||
@keyframes pulse{0%{transform:scale(.4);opacity:.5}100%{transform:scale(1.4);opacity:0}}
|
||||
.lv-h b{font-size:20px;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:.3px}
|
||||
.lv-h .u{color:var(--ink)}
|
||||
.lv-row{display:flex;align-items:flex-end;gap:6px;justify-content:space-between;margin-top:12px;overflow:hidden;position:relative}
|
||||
.sp{flex:none;width:48px;display:flex;flex-direction:column;align-items:center;gap:5px}
|
||||
.sp .av{width:44px;height:44px;border-radius:50%;object-fit:cover;background:#eee;border:2px solid #fff;box-shadow:0 0 0 2px #EFEFF2}
|
||||
.sp.talk .av{box-shadow:0 0 0 2px #2BC266}
|
||||
.sp span{font-size:11px;color:var(--ink3);max-width:52px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.sp .wv{position:absolute;margin:30px 0 0 30px;width:18px;height:18px;border-radius:50%;background:#2BC266;border:2px solid #fff;display:flex;align-items:center;justify-content:center;gap:1.5px}
|
||||
.sp .wv i{width:2px;height:6px;border-radius:1px;background:#fff;animation:wv .9s ease-in-out infinite}
|
||||
.sp .wv i:nth-child(2){animation-delay:.15s}.sp .wv i:nth-child(3){animation-delay:.3s}
|
||||
@keyframes wv{0%,100%{transform:scaleY(.45)}50%{transform:scaleY(1.15)}}
|
||||
.sp{position:relative}
|
||||
.lv-tk{margin-top:12px;height:20px;overflow:hidden;font-size:12px;color:var(--ink3);position:relative}
|
||||
.lv-tk div{height:20px;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:transform .5s}
|
||||
.lv-tk b{color:var(--ink2);font-weight:600}
|
||||
|
||||
/* ---------- 分区标题 ---------- */
|
||||
.sec{display:flex;align-items:baseline;justify-content:space-between;padding:16px 18px 8px}
|
||||
.sec h2{font-size:16px;font-weight:700}
|
||||
.sec span{font-size:12px;color:var(--ink3)}
|
||||
|
||||
/* ---------- 聊天室卡片 ---------- */
|
||||
.feed{padding:0 12px}
|
||||
.room{background:#fff;border-radius:20px;margin-bottom:12px;padding:14px 14px 0;position:relative;overflow:hidden}
|
||||
.room:active{transform:scale(.995)}
|
||||
.rh{display:flex;gap:10px;align-items:flex-start;padding-bottom:12px;border-bottom:1px solid var(--line)}
|
||||
.rh .ic{flex:none;width:40px;height:40px;border-radius:13px;background:var(--kl);color:var(--kf);display:flex;align-items:center;justify-content:center;font-size:19px;font-weight:800;position:relative}
|
||||
.rh .ic em{position:absolute;right:-3px;top:-3px;font-style:normal;font-size:10px;line-height:15px;height:15px;padding:0 4px;border-radius:8px;background:var(--brand);color:#fff;font-weight:700;border:1.5px solid #fff}
|
||||
.rh .tt{flex:1;min-width:0}
|
||||
.rh h3{font-size:15px;font-weight:700;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||||
.rh .mt{margin-top:3px;font-size:12px;color:var(--ink3);display:flex;align-items:center;gap:6px;white-space:nowrap}
|
||||
.rh .mt .chn{color:var(--kf);font-weight:600}
|
||||
.rh .mt .on{display:inline-flex;align-items:center;gap:4px}
|
||||
.rh .mt .on::before{content:"";width:6px;height:6px;border-radius:50%;background:#2BC266}
|
||||
|
||||
.msgs{padding:12px 0 4px}
|
||||
.m{display:flex;gap:9px;margin-bottom:12px}
|
||||
.m .av{flex:none;width:34px;height:34px;border-radius:50%;object-fit:cover;background:#eee}
|
||||
.m .bd{min-width:0;flex:1;display:flex;flex-direction:column;align-items:flex-start}
|
||||
.m .who{font-size:12px;color:var(--ink3);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
|
||||
.m .who b{color:var(--ink2);font-weight:600;margin-right:6px}
|
||||
.m .who .wk{display:inline-block;font-size:11px;line-height:16px;padding:0 6px;border-radius:8px;background:var(--kl);color:var(--kf);font-weight:600}
|
||||
.bb{position:relative;max-width:92%;background:var(--bub);border-radius:4px 16px 16px 16px;padding:9px 12px;font-size:14px;line-height:1.55;color:var(--ink)}
|
||||
.bb .q{font-weight:700;display:block;margin-bottom:2px}
|
||||
.bb .s{color:var(--ink2);display:-webkit-box;-webkit-line-clamp:var(--cl,2);-webkit-box-orient:vertical;overflow:hidden}
|
||||
.bb.rp{font-size:14px}
|
||||
.bb.rp .at{color:var(--kf);font-weight:600;margin-right:3px}
|
||||
.pic{position:relative;margin-top:6px;width:108px;height:144px;border-radius:4px 14px 14px 14px;overflow:hidden;background:#EDEEF1}
|
||||
.pic img{width:100%;height:100%;object-fit:cover}
|
||||
.pic::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px rgba(0,0,0,.04)}
|
||||
.lk{margin-top:5px;font-size:11px;color:var(--ink3);display:flex;align-items:center;gap:3px}
|
||||
.lk svg{width:12px;height:12px}
|
||||
|
||||
.rf{display:flex;align-items:center;justify-content:space-between;padding:10px 0 13px;border-top:1px dashed var(--line)}
|
||||
.typing{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--ink3);min-width:0}
|
||||
.stack{display:flex;flex:none}
|
||||
.stack img{width:20px;height:20px;border-radius:50%;object-fit:cover;border:1.5px solid #fff;margin-left:-6px;background:#eee}
|
||||
.stack img:first-child{margin-left:0}
|
||||
.typing .tx{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.typing .tx b{color:var(--ink2);font-weight:600}
|
||||
.dots{display:inline-flex;gap:2px;margin-left:2px;vertical-align:middle}
|
||||
.dots i{width:3px;height:3px;border-radius:50%;background:var(--ink3);animation:db 1.2s infinite}
|
||||
.dots i:nth-child(2){animation-delay:.2s}.dots i:nth-child(3){animation-delay:.4s}
|
||||
@keyframes db{0%,60%,100%{opacity:.25}30%{opacity:1}}
|
||||
.go{flex:none;height:30px;padding:0 12px;border-radius:15px;background:var(--kl);color:var(--kf);font-size:13px;font-weight:700;display:flex;align-items:center;gap:2px}
|
||||
.go svg{width:12px;height:12px}
|
||||
|
||||
.foot{padding:6px 0 20px;text-align:center;font-size:11px;color:#B5BAC4}
|
||||
.pad{height:calc(84px + var(--safe-b))}
|
||||
|
||||
/* ---------- 底部输入条 ---------- */
|
||||
.bar{position:fixed;left:0;right:0;bottom:0;z-index:30;padding:8px 12px calc(8px + var(--safe-b));background:rgba(255,255,255,.92);-webkit-backdrop-filter:blur(16px) saturate(170%);backdrop-filter:blur(16px) saturate(170%);box-shadow:0 -1px 0 var(--line)}
|
||||
.ipt{display:flex;align-items:center;gap:8px;height:44px}
|
||||
.ipt .me{flex:none;width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,#FFD9CF,#FFB8A6);display:flex;align-items:center;justify-content:center;color:#fff}
|
||||
.ipt .me svg{width:18px;height:18px}
|
||||
.field{flex:1;min-width:0;height:40px;border-radius:20px;background:#F1F2F5;display:flex;align-items:center;padding:0 6px 0 14px;gap:6px;text-align:left}
|
||||
.field .ph{flex:1;min-width:0;font-size:13.5px;color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.field .ph em{font-style:normal;color:var(--brand);font-weight:700}
|
||||
.field .cur{width:1.5px;height:16px;background:var(--brand);animation:blink 1s steps(1) infinite;flex:none;margin-right:-2px}
|
||||
@keyframes blink{50%{opacity:0}}
|
||||
.send{flex:none;height:30px;padding:0 13px;border-radius:15px;background:var(--brand);color:#fff;font-size:13px;font-weight:700;display:flex;align-items:center}
|
||||
|
||||
/* ---------- 弹层 ---------- */
|
||||
.mask{position:fixed;inset:0;z-index:50;background:rgba(20,22,28,.42);opacity:0;pointer-events:none;transition:opacity .25s}
|
||||
.mask.on{opacity:1;pointer-events:auto}
|
||||
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:51;background:#fff;border-radius:22px 22px 0 0;padding:10px 18px calc(18px + var(--safe-b));transform:translateY(105%);transition:transform .3s cubic-bezier(.2,.8,.2,1)}
|
||||
.sheet.on{transform:none}
|
||||
.sheet .gb{width:36px;height:4px;border-radius:2px;background:#E1E3E8;margin:0 auto 14px}
|
||||
.sheet h3{font-size:17px;font-weight:700;text-align:center}
|
||||
.rw{margin:14px 0;padding:14px;border-radius:16px;background:#FFF3EF;display:flex;align-items:center;gap:12px}
|
||||
.rw b{font-size:24px;color:var(--brand);font-weight:800;white-space:nowrap}
|
||||
.rw b small{font-size:14px;font-weight:700;margin:0 2px}
|
||||
.rw span{font-size:12px;color:var(--ink2);line-height:1.5}
|
||||
.sheet ol{padding-left:18px;font-size:13px;color:var(--ink2);line-height:1.8}
|
||||
.sheet .btn{margin-top:16px;width:100%;height:46px;border-radius:23px;background:var(--brand);color:#fff;font-size:15px;font-weight:700}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="sc">
|
||||
<header class="top" id="top">
|
||||
<div class="nav">
|
||||
<button class="back" id="back" type="button" aria-label="返回"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#1F2329" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
|
||||
<h1>孕妈广场</h1>
|
||||
<span class="ver">效果稿 V4 · 聊天广场</span>
|
||||
</div>
|
||||
<nav class="chs" id="chs"></nav>
|
||||
</header>
|
||||
|
||||
<section class="live">
|
||||
<div class="lv-h"><span class="dot"></span>此刻在线 <b id="onl">12,486</b> <span class="u">位孕妈</span></div>
|
||||
<div class="lv-row" id="spk"></div>
|
||||
<div class="lv-tk" id="tk"></div>
|
||||
</section>
|
||||
|
||||
<div class="sec"><h2 id="secT">大家正在聊</h2><span id="secN"></span></div>
|
||||
<main class="feed" id="feed"></main>
|
||||
<div class="foot">话题与内容为示例占位</div>
|
||||
<div class="pad"></div>
|
||||
</div>
|
||||
|
||||
<div class="bar">
|
||||
<div class="ipt">
|
||||
<button class="field" id="post" type="button"><span class="cur"></span><span class="ph">说说你的故事,被选中 <em>¥30+500 兜豆</em></span><span class="send">投稿</span></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mask" id="mask"></div>
|
||||
<div class="sheet" id="sheet">
|
||||
<div class="gb"></div>
|
||||
<h3>说说你的故事</h3>
|
||||
<div class="rw"><b>¥<small></small>30<small>+</small>500</b><span>投稿被选中,每篇奖励 30 元现金 + 500 兜豆</span></div>
|
||||
<ol>
|
||||
<li>挑一个话题,写下你自己的真实经历</li>
|
||||
<li>提交后进入审核,通过即展示在广场</li>
|
||||
<li>被选中的稿件,工作人员会尽快发放奖励</li>
|
||||
</ol>
|
||||
<button class="btn" id="goPost" type="button">去投稿</button>
|
||||
</div>
|
||||
|
||||
<script src="../../guangchang/topics.js"></script>
|
||||
<script src="../../guangchang/data.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
|
||||
var $ = function (s) { return document.querySelector(s); };
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); };
|
||||
var hs = function (s) { var x = 7; s = String(s); for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
|
||||
var POOL = [];
|
||||
for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i);
|
||||
for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
|
||||
var av = function (name) { return '../../assets/img/mom/' + POOL[hs(name) % POOL.length] + '.jpg'; };
|
||||
var fmt = function (n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ','); };
|
||||
var first = function (b) { var s = String(b || '').split('\n')[0]; var m = s.match(/^[^。!?!?]*[。!?!?]/); s = m ? m[0] : s; return s.length > 60 ? s.slice(0, 58) + '…' : s; };
|
||||
var CH = [['all', '全部'], ['family', '家庭婚姻'], ['work', '职场'], ['baby', '经验']];
|
||||
var CHN = { family: '家庭婚姻', work: '职场', baby: '经验' };
|
||||
var cur = 'all';
|
||||
var heart = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 21s-7.5-4.6-9.6-9.2C.9 8.4 3 4.5 6.7 4.5c2.1 0 3.6 1.1 4.3 2.4h2c.7-1.3 2.2-2.4 4.3-2.4 3.7 0 5.8 3.9 4.3 7.3C19.5 16.4 12 21 12 21z"/></svg>';
|
||||
var arrow = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5l7 7-7 7"/></svg>';
|
||||
|
||||
var detail = function (tid, idx) { return '../../guangchang/?t=' + tid + (idx ? '&n=' + tid + '-' + idx : '') + location.hash; };
|
||||
|
||||
/* 频道 */
|
||||
function renderCh() {
|
||||
$('#chs').innerHTML = CH.map(function (c) {
|
||||
return '<button type="button" class="ch k-' + c[0] + (cur === c[0] ? ' on' : '') + '" data-c="' + c[0] + '"><i>#</i>' + c[1] + '</button>';
|
||||
}).join('');
|
||||
}
|
||||
$('#chs').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('.ch'); if (!b || b.dataset.c === cur) return;
|
||||
cur = b.dataset.c; renderCh(); renderFeed(); renderLive();
|
||||
var top = $('.sec').offsetTop - $('#top').offsetHeight;
|
||||
if ($('#sc').scrollTop > top) $('#sc').scrollTop = top;
|
||||
});
|
||||
|
||||
/* 列表:全部 = 三块轮流排、热门在前 */
|
||||
function list() {
|
||||
var by = { family: [], work: [], baby: [] };
|
||||
T.forEach(function (t) { (by[t.cat] = by[t.cat] || []).push(t); });
|
||||
Object.keys(by).forEach(function (k) { by[k].sort(function (a, b) { return b.hot - a.hot || b.talk - a.talk; }); });
|
||||
if (cur !== 'all') return by[cur] || [];
|
||||
var out = [], ks = ['family', 'work', 'baby'], mx = Math.max(by.family.length, by.work.length, by.baby.length);
|
||||
for (var i = 0; i < mx; i++) ks.forEach(function (k) { if (by[k][i]) out.push(by[k][i]); });
|
||||
return out;
|
||||
}
|
||||
|
||||
function msg(name, stage, inner, tid, idx) {
|
||||
return '<div class="m" data-t="' + tid + '"' + (idx ? ' data-n="' + idx + '"' : '') + '>' +
|
||||
'<img class="av" loading="lazy" src="' + av(name) + '" alt="">' +
|
||||
'<div class="bd"><div class="who"><b>' + esc(name) + '</b>' + (stage ? '<span class="wk">' + esc(stage.replace(/\s+/g, '')) + '</span>' : '') + '</div>' + inner + '</div></div>';
|
||||
}
|
||||
|
||||
function room(t) {
|
||||
var d = D[t.id] || { notes: [], comments: [] }, ns = d.notes || [], h = '';
|
||||
/* 第一条:带照片的笔记优先,文字气泡 + 图片消息 */
|
||||
var order = ns.map(function (n, i) { return i; }).sort(function (a, b) { return (ns[b].photo ? 1 : 0) - (ns[a].photo ? 1 : 0); });
|
||||
var a = order[0], b = order[1];
|
||||
if (ns[a]) {
|
||||
var n = ns[a];
|
||||
h += msg(n.author, n.stage,
|
||||
'<div class="bb"><span class="q">' + esc(n.title) + '</span><span class="s">' + esc(first(n.body)) + '</span></div>' +
|
||||
(n.photo ? '<div class="pic"><img loading="lazy" src="../../guangchang/' + n.photo + '" alt=""></div>' : '') +
|
||||
'<div class="lk">' + heart + fmt(n.likes) + ' 人抱抱</div>', t.id, a + 1);
|
||||
}
|
||||
/* 第二条:一句评论回复,像群里接话 */
|
||||
var cm = (d.comments || [])[hs(t.id) % Math.max(1, (d.comments || []).length)];
|
||||
if (cm && ns[a]) {
|
||||
h += msg(cm.n, cm.s, '<div class="bb rp"><span class="at">@' + esc(ns[a].author) + '</span>' + esc(cm.t) + '</div>', t.id, a + 1);
|
||||
}
|
||||
/* 第三条:另一篇笔记 */
|
||||
if (ns[b]) {
|
||||
var m = ns[b];
|
||||
h += msg(m.author, m.stage, '<div class="bb" style="--cl:1"><span class="q">' + esc(m.title) + '</span><span class="s">' + esc(first(m.body)) + '</span></div>', t.id, b + 1);
|
||||
}
|
||||
var tp = (d.comments || []).slice(0, 3).map(function (c) { return c.n; });
|
||||
var who = tp[(hs(t.id) >> 3) % Math.max(1, tp.length)] || '有人';
|
||||
return '<article class="room k-' + t.cat + '" data-t="' + t.id + '">' +
|
||||
'<div class="rh"><span class="ic">' + esc(t.g) + (t.hot ? '<em>热</em>' : '') + '</span>' +
|
||||
'<div class="tt"><h3>' + esc(t.name) + '</h3><div class="mt"><span class="chn"># ' + CHN[t.cat] + '</span><span class="on">' + fmt(Math.round(t.talk / 9)) + ' 人在线</span><span>' + fmt(t.n) + ' 篇</span></div></div></div>' +
|
||||
'<div class="msgs">' + h + '</div>' +
|
||||
'<div class="rf"><div class="typing"><span class="stack">' + tp.map(function (n) { return '<img loading="lazy" src="' + av(n) + '" alt="">'; }).join('') + '</span>' +
|
||||
'<span class="tx">还有 <b>' + fmt(t.talk) + '</b> 人在聊<span class="dots"><i></i><i></i><i></i></span></span></div>' +
|
||||
'<span class="go">进去听听' + arrow + '</span></div></article>';
|
||||
}
|
||||
|
||||
function renderFeed() {
|
||||
var L = list();
|
||||
$('#feed').innerHTML = L.map(room).join('');
|
||||
$('#secT').textContent = cur === 'all' ? '大家正在聊' : '# ' + CHN[cur] + ' 频道';
|
||||
$('#secN').textContent = L.length + ' 个聊天室';
|
||||
}
|
||||
$('#feed').addEventListener('click', function (e) {
|
||||
var r = e.target.closest('.room'); if (!r) return;
|
||||
var m = e.target.closest('.m');
|
||||
location.href = detail(r.dataset.t, m && m.dataset.n);
|
||||
});
|
||||
|
||||
/* 此刻在线:正在说话的头像 + 滚动播报 */
|
||||
var tkTimer = null;
|
||||
function renderLive() {
|
||||
var L = list(), seen = {}, sp = [];
|
||||
L.forEach(function (t) { (D[t.id] && D[t.id].notes || []).forEach(function (n) { if (!seen[n.author] && sp.length < 7) { seen[n.author] = 1; sp.push({ n: n.author, t: t }); } }); });
|
||||
sp = sp.slice(0, 6);
|
||||
$('#spk').innerHTML = sp.map(function (s, i) {
|
||||
return '<button type="button" class="sp' + (i < 3 ? ' talk' : '') + '" data-t="' + s.t.id + '"><img class="av" src="' + av(s.n) + '" alt="">' +
|
||||
(i < 3 ? '<span class="wv"><i></i><i></i><i></i></span>' : '') + '<span>' + esc(s.n) + '</span></button>';
|
||||
}).join('');
|
||||
var base = cur === 'all' ? 12486 : { family: 5210, work: 3874, baby: 3402 }[cur];
|
||||
$('#onl').textContent = fmt(base);
|
||||
var lines = [];
|
||||
L.slice(0, 8).forEach(function (t) { var c = (D[t.id] && D[t.id].comments || [])[0]; if (c) lines.push('<b>' + esc(c.n) + '</b> 在「' + esc(t.name) + '」里说:' + esc(c.t)); });
|
||||
var tk = $('#tk'), k = 0;
|
||||
tk.innerHTML = '<div>' + (lines[0] || '') + '</div>';
|
||||
clearInterval(tkTimer);
|
||||
tkTimer = setInterval(function () {
|
||||
k = (k + 1) % lines.length;
|
||||
var d = document.createElement('div'); d.innerHTML = lines[k];
|
||||
tk.appendChild(d);
|
||||
[].forEach.call(tk.children, function (c) { c.style.transform = 'translateY(-20px)'; });
|
||||
setTimeout(function () { if (tk.children.length > 1) tk.removeChild(tk.children[0]); [].forEach.call(tk.children, function (c) { c.style.transition = 'none'; c.style.transform = 'none'; c.offsetHeight; c.style.transition = ''; }); }, 520);
|
||||
}, 3200);
|
||||
}
|
||||
$('#spk').addEventListener('click', function (e) { var b = e.target.closest('.sp'); if (b) location.href = detail(b.dataset.t); });
|
||||
|
||||
/* 投稿 */
|
||||
var openS = function (on) { $('#mask').classList.toggle('on', on); $('#sheet').classList.toggle('on', on); };
|
||||
$('#post').addEventListener('click', function () { openS(true); });
|
||||
$('#mask').addEventListener('click', function () { openS(false); });
|
||||
$('#goPost').addEventListener('click', function () { location.href = '../../guangchang/' + location.hash; });
|
||||
|
||||
$('#back').addEventListener('click', function () { history.length > 1 ? history.back() : location.href = '../../' + location.hash; });
|
||||
var sc = $('#sc');
|
||||
sc.addEventListener('scroll', function () { $('#top').classList.toggle('on', sc.scrollTop > 4); }, { passive: true });
|
||||
|
||||
/* 禁止下拉回弹:从手指下往上找还能朝该方向滚的容器,找不到才拦 */
|
||||
var sx = 0, sy = 0;
|
||||
document.addEventListener('touchstart', function (e) { if (e.touches.length !== 1) return; sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
|
||||
document.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
|
||||
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
|
||||
if (Math.abs(dy) <= Math.abs(dx)) return;
|
||||
var el = e.target;
|
||||
while (el && el !== document.body && el !== document.documentElement) {
|
||||
if (el.nodeType === 1) {
|
||||
var oy = getComputedStyle(el).overflowY;
|
||||
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
|
||||
if (dy > 0 && el.scrollTop > 0) return;
|
||||
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
|
||||
}
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
if (e.cancelable) e.preventDefault();
|
||||
}, { passive: false });
|
||||
|
||||
renderCh(); renderFeed(); renderLive();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
436
demo/gc-v5/index.html
Normal file
436
demo/gc-v5/index.html
Normal file
@@ -0,0 +1,436 @@
|
||||
<!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,viewport-fit=cover">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<title>孕妈广场 · 效果稿 V5</title>
|
||||
<!-- 效果稿 V5 · 今日广场:今日一问 + 故事卡堆 + 话题榜。演示页,独立文件,不接后端。 -->
|
||||
<style>
|
||||
:root{
|
||||
--brand:#F4593C;--brand-2:#FF8A5B;--ink:#231B18;--ink-2:#5E534E;--muted:#9A8C86;--line:#EFE6E1;
|
||||
--bg:#FBF7F4;--card:#fff;
|
||||
--family:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
|
||||
}
|
||||
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
|
||||
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
|
||||
body{background:var(--bg);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC","Source Han Sans SC","Segoe UI",Roboto,sans-serif;
|
||||
font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
|
||||
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
|
||||
a{color:inherit;text-decoration:none}
|
||||
.ic{width:16px;height:16px;flex:none;display:inline-block;vertical-align:middle}
|
||||
|
||||
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;background:var(--bg)}
|
||||
#sc::-webkit-scrollbar{display:none}
|
||||
|
||||
/* ---------- 顶栏 ---------- */
|
||||
.top{position:sticky;top:0;z-index:30;padding-top:env(safe-area-inset-top);background:rgba(251,247,244,.88);-webkit-backdrop-filter:blur(14px) saturate(160%);backdrop-filter:blur(14px) saturate(160%);transition:box-shadow .2s}
|
||||
.top.on{box-shadow:0 1px 0 var(--line)}
|
||||
.nav{position:relative;display:flex;align-items:center;height:48px;padding:0 8px}
|
||||
.nav .bk{width:38px;height:38px;display:grid;place-items:center;border-radius:50%}
|
||||
.nav .bk:active{background:rgba(0,0,0,.05)}
|
||||
.nav .bk .ic{width:22px;height:22px}
|
||||
.nav .tt{margin-left:2px;display:flex;align-items:baseline;gap:8px;min-width:0}
|
||||
.nav .tt b{font-size:18px;font-weight:900;letter-spacing:.5px}
|
||||
.nav .tt small{font-size:12px;font-weight:700;color:var(--muted);white-space:nowrap}
|
||||
.ver{position:absolute;right:12px;max-width:40%;white-space:nowrap;top:50%;transform:translateY(-50%);font-size:11px;color:#BBADA6;letter-spacing:.3px}
|
||||
|
||||
/* ---------- 区块标题(编号 + 标题,做节奏) ---------- */
|
||||
.sh{display:flex;align-items:flex-end;gap:8px;margin:26px 18px 12px}
|
||||
.sh .no{font-size:12px;font-weight:900;color:var(--brand);letter-spacing:1px;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif;padding-bottom:3px}
|
||||
.sh h2{margin:0;font-size:20px;font-weight:900;letter-spacing:.5px;line-height:1.2}
|
||||
.sh small{margin-left:auto;font-size:12px;font-weight:600;color:var(--muted);white-space:nowrap;padding-bottom:2px}
|
||||
|
||||
/* ---------- 01 今日一问 ---------- */
|
||||
.q{position:relative;margin:6px 14px 0;padding:20px 18px 18px;border-radius:26px;overflow:hidden;color:#fff;
|
||||
background:radial-gradient(180px 160px at 108% -10%,rgba(255,175,120,.55),transparent 70%),radial-gradient(200px 150px at -10% 110%,rgba(244,89,60,.45),transparent 70%),linear-gradient(160deg,#3A2A25,#231B18 70%);
|
||||
box-shadow:0 18px 34px -20px rgba(35,27,24,.75)}
|
||||
.q .wm{position:absolute;right:-6px;bottom:-34px;font-size:150px;font-weight:900;line-height:1;color:rgba(255,255,255,.05);pointer-events:none}
|
||||
.q .hd{display:flex;align-items:center;gap:8px}
|
||||
.q .tag{display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 10px;border-radius:99px;background:var(--brand);font-size:12px;font-weight:800;letter-spacing:.5px}
|
||||
.q .tag i{width:6px;height:6px;border-radius:50%;background:#fff;animation:blink 1.6s infinite}
|
||||
@keyframes blink{50%{opacity:.25}}
|
||||
.q .dt{font-size:12px;color:rgba(255,255,255,.6);font-weight:600}
|
||||
.q .cat{margin-left:auto;font-size:12px;font-weight:700;color:rgba(255,255,255,.75)}
|
||||
.q h3{position:relative;margin:14px 0 4px;font-size:23px;line-height:1.35;font-weight:900;letter-spacing:.3px}
|
||||
.q .sub{position:relative;margin:0;font-size:13px;color:rgba(255,255,255,.66)}
|
||||
.q .ops{position:relative;display:flex;flex-direction:column;gap:10px;margin-top:16px}
|
||||
.op{position:relative;display:flex;align-items:center;gap:10px;min-height:50px;padding:0 14px;border-radius:16px;overflow:hidden;text-align:left;
|
||||
background:rgba(255,255,255,.1);border:1.5px solid rgba(255,255,255,.16);font-size:15px;font-weight:800;transition:transform .15s}
|
||||
.op:active{transform:scale(.98)}
|
||||
.op .bar{position:absolute;left:0;top:0;bottom:0;width:0;background:rgba(255,255,255,.12);transition:width .7s cubic-bezier(.2,.8,.2,1)}
|
||||
.op .lt{position:relative;width:24px;height:24px;flex:none;display:grid;place-items:center;border-radius:8px;background:rgba(255,255,255,.16);font-size:12px;font-weight:900}
|
||||
.op .tx{position:relative;flex:1;min-width:0;line-height:1.35;padding:12px 0}
|
||||
.op .pc{position:relative;font-size:16px;font-weight:900;opacity:0;transition:opacity .4s .3s;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif}
|
||||
.q.done .op .pc{opacity:1}
|
||||
.q.done .op.me{border-color:#FFB08F}
|
||||
.q.done .op.me .bar{background:linear-gradient(90deg,#F4593C,#FF8A5B)}
|
||||
.q.done .op.me .lt{background:#fff;color:var(--brand)}
|
||||
.q .ft{position:relative;display:flex;align-items:center;gap:10px;margin-top:16px;min-height:34px}
|
||||
.q .avs{display:flex}
|
||||
.q .avs img{width:26px;height:26px;border-radius:50%;object-fit:cover;border:2px solid #2E221E;margin-left:-8px}
|
||||
.q .avs img:first-child{margin-left:0}
|
||||
.q .ft small{font-size:12px;color:rgba(255,255,255,.7);flex:1;min-width:0}
|
||||
.q .go{display:none;align-items:center;gap:3px;height:34px;padding:0 14px;border-radius:99px;background:#fff;color:var(--ink);font-size:13px;font-weight:900;white-space:nowrap}
|
||||
.q.done .go{display:inline-flex;animation:pop .35s}
|
||||
.q .go .ic{width:14px;height:14px;color:var(--brand)}
|
||||
@keyframes pop{from{transform:scale(.85);opacity:0}}
|
||||
|
||||
/* ---------- 02 故事卡堆 ---------- */
|
||||
.stk-wrap{position:relative;margin:0 14px}
|
||||
.stk{position:relative;height:440px;touch-action:pan-y;user-select:none;-webkit-user-select:none}
|
||||
.sc{position:absolute;left:0;right:0;top:0;height:410px;border-radius:26px;overflow:hidden;background:#E9DED8;
|
||||
box-shadow:0 18px 30px -18px rgba(60,35,25,.55);transform-origin:50% 100%;will-change:transform;transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .35s}
|
||||
.sc img.ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none}
|
||||
.sc .sh2{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.28) 0,rgba(0,0,0,0) 26%,rgba(0,0,0,0) 46%,rgba(20,10,6,.82) 100%)}
|
||||
.sc .kt{position:absolute;left:14px;top:14px;display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 10px;border-radius:99px;background:rgba(255,255,255,.92);font-size:12px;font-weight:800}
|
||||
.sc .kt i{width:7px;height:7px;border-radius:50%}
|
||||
.sc .lk{position:absolute;right:14px;top:14px;display:inline-flex;align-items:center;gap:4px;height:26px;padding:0 10px;border-radius:99px;background:rgba(0,0,0,.32);color:#fff;font-size:12px;font-weight:700;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
|
||||
.sc .lk .ic{width:13px;height:13px}
|
||||
.sc .bt{position:absolute;left:0;right:0;bottom:0;padding:0 18px 18px;color:#fff}
|
||||
.sc .tp{font-size:12px;font-weight:700;color:rgba(255,255,255,.75);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||
.sc h4{margin:6px 0 12px;font-size:20px;line-height:1.38;font-weight:900;letter-spacing:.2px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-shadow:0 1px 8px rgba(0,0,0,.25)}
|
||||
.sc .au{display:flex;align-items:center;gap:9px}
|
||||
.sc .au img{width:32px;height:32px;border-radius:50%;object-fit:cover;border:2px solid rgba(255,255,255,.85)}
|
||||
.sc .au b{font-size:14px;font-weight:800}
|
||||
.sc .au span{display:inline-flex;align-items:center;height:22px;padding:0 8px;border-radius:99px;background:rgba(255,255,255,.2);font-size:12px;font-weight:700;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
|
||||
.sc .au .rd{margin-left:auto;display:inline-flex;align-items:center;gap:2px;font-size:12.5px;font-weight:800;color:#FFD9C9}
|
||||
.sc .au .rd .ic{width:13px;height:13px}
|
||||
/* 最后一张:轮到你了 */
|
||||
.sc.you{background:radial-gradient(220px 180px at 100% 0,rgba(255,255,255,.35),transparent 70%),radial-gradient(240px 200px at 0 100%,rgba(255,206,120,.4),transparent 70%),linear-gradient(155deg,#FF8A5B,#F4593C 55%,#E2402F);color:#fff}
|
||||
.you .in{position:absolute;inset:0;display:flex;flex-direction:column;padding:24px 22px 22px}
|
||||
.you .big{font-size:40px;font-weight:900;line-height:1.1;letter-spacing:1px;margin-top:10px}
|
||||
.you .lede{margin:12px 0 0;font-size:14.5px;line-height:1.6;color:rgba(255,255,255,.92)}
|
||||
.you .rw{margin-top:auto;padding:14px 16px;border-radius:18px;background:rgba(255,255,255,.18);border:1px dashed rgba(255,255,255,.55)}
|
||||
.you .rw small{display:block;font-size:12px;font-weight:700;opacity:.9}
|
||||
.you .rw b{display:block;margin-top:2px;font-size:18px;font-weight:900;white-space:nowrap}
|
||||
.you .rw b em{font-style:normal;font-size:24px;color:#FFF3B8;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif}
|
||||
.you .cta{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:12px;height:48px;border-radius:99px;background:#fff;color:#E2402F;font-size:16px;font-weight:900}
|
||||
.you .pen{position:absolute;right:18px;top:20px;width:58px;height:58px;border-radius:18px;background:rgba(255,255,255,.2);display:grid;place-items:center;transform:rotate(8deg)}
|
||||
.you .pen .ic{width:30px;height:30px}
|
||||
.you .k{font-size:12px;font-weight:800;letter-spacing:2px;opacity:.85}
|
||||
/* 卡堆下方控制条 */
|
||||
.stk-ctl{display:flex;align-items:center;gap:10px;margin:2px 4px 0}
|
||||
.stk-ctl .pg{font-size:13px;font-weight:800;color:var(--ink-2);font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif;min-width:52px}
|
||||
.stk-ctl .pg b{color:var(--brand);font-size:18px}
|
||||
.stk-ctl .tr{flex:1;height:4px;border-radius:99px;background:#EDE2DC;overflow:hidden}
|
||||
.stk-ctl .tr i{display:block;height:100%;width:0;border-radius:99px;background:linear-gradient(90deg,#FF8A5B,#F4593C);transition:width .35s}
|
||||
.stk-ctl button{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;background:#fff;box-shadow:0 4px 12px -6px rgba(90,50,30,.35);color:var(--ink)}
|
||||
.stk-ctl button:active{transform:scale(.94)}
|
||||
.stk-ctl button:disabled{opacity:.35}
|
||||
.stk-ctl button .ic{width:18px;height:18px}
|
||||
.hint{margin:8px 4px 0;font-size:12px;color:var(--muted);text-align:center}
|
||||
|
||||
/* ---------- 03 话题榜 ---------- */
|
||||
.tabs{position:sticky;top:calc(48px + env(safe-area-inset-top));z-index:20;display:flex;gap:8px;padding:10px 14px;background:rgba(251,247,244,.92);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);overflow-x:auto}
|
||||
.tabs::-webkit-scrollbar{display:none}
|
||||
.tabs button{flex:none;display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 15px;border-radius:99px;background:#fff;border:1.5px solid var(--line);font-size:14px;font-weight:800;color:var(--ink-2);transition:all .2s}
|
||||
.tabs button i{width:8px;height:8px;border-radius:50%;background:var(--k)}
|
||||
.tabs button.on{background:var(--k);border-color:var(--k);color:#fff}
|
||||
.tabs button.on i{background:#fff}
|
||||
.rank{margin:4px 14px 0;padding:6px 0;border-radius:24px;background:#fff;box-shadow:0 10px 26px -20px rgba(90,50,30,.5)}
|
||||
.rk{display:flex;align-items:center;gap:12px;padding:12px 16px;position:relative}
|
||||
.rk + .rk:before{content:"";position:absolute;left:60px;right:16px;top:0;height:1px;background:var(--line)}
|
||||
.rk:active{background:#FBF5F2}
|
||||
.rk .n{width:30px;flex:none;text-align:center;font-size:22px;font-weight:900;font-style:italic;color:#CDBFB8;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif;line-height:1}
|
||||
.rk.t1 .n,.rk.t2 .n,.rk.t3 .n{color:var(--brand)}
|
||||
.rk.t1 .n{font-size:28px}
|
||||
.rk .bd{flex:1;min-width:0}
|
||||
.rk .nm{display:flex;align-items:center;gap:6px}
|
||||
.rk .nm b{font-size:15px;font-weight:800;line-height:1.4;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;min-width:0}
|
||||
.rk .kc{flex:none;font-size:11px;font-weight:800;color:var(--k);line-height:1}
|
||||
.rk .hot{flex:none;height:18px;padding:0 5px;border-radius:5px;background:#FFE7DF;color:var(--brand);font-size:11px;font-weight:900;line-height:18px}
|
||||
.rk .mt{display:flex;align-items:center;gap:8px;margin-top:7px}
|
||||
.rk .hb{flex:1;height:6px;border-radius:99px;background:#F4ECE8;overflow:hidden}
|
||||
.rk .hb i{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--k2),var(--k));width:0;transition:width .8s cubic-bezier(.2,.8,.2,1)}
|
||||
.rk .tk{flex:none;font-size:12px;font-weight:700;color:var(--muted);min-width:66px;text-align:right}
|
||||
.rk .tk em{font-style:normal;color:var(--ink-2);font-weight:900}
|
||||
.rk .th{width:52px;height:52px;flex:none;border-radius:12px;object-fit:cover;background:#EEE}
|
||||
.rk-ft{display:flex;align-items:center;justify-content:center;gap:4px;margin:12px 14px 0;height:44px;border-radius:16px;border:1.5px dashed #E6D7D0;font-size:13px;font-weight:700;color:var(--ink-2)}
|
||||
|
||||
.foot{margin:22px 18px 0;padding-bottom:calc(30px + env(safe-area-inset-bottom));text-align:center;font-size:11px;color:#BBADA6;line-height:1.7}
|
||||
|
||||
/* 小弹层:投稿说明 */
|
||||
.mask{position:fixed;inset:0;z-index:50;background:rgba(20,12,8,.45);opacity:0;pointer-events:none;transition:opacity .25s}
|
||||
.mask.on{opacity:1;pointer-events:auto}
|
||||
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:51;padding:22px 20px calc(22px + env(safe-area-inset-bottom));border-radius:24px 24px 0 0;background:#fff;transform:translateY(105%);transition:transform .3s cubic-bezier(.2,.8,.2,1)}
|
||||
.sheet.on{transform:none}
|
||||
.sheet h3{margin:0;font-size:19px;font-weight:900}
|
||||
.sheet p{margin:8px 0 0;font-size:14px;color:var(--ink-2);line-height:1.65}
|
||||
.sheet .rb{margin-top:14px;padding:14px;border-radius:16px;background:#FFF1EB;text-align:center}
|
||||
.sheet .rb small{display:block;font-size:12px;color:#B5634C;font-weight:700}
|
||||
.sheet .rb b{font-size:18px;font-weight:900;color:var(--ink)}
|
||||
.sheet .rb em{font-style:normal;color:var(--brand);font-size:22px}
|
||||
.sheet .pk{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
|
||||
.sheet .pk a{display:inline-flex;align-items:center;height:32px;padding:0 12px;border-radius:99px;background:#F7F1EE;font-size:13px;font-weight:700;color:var(--ink-2);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.sheet .bt2{display:flex;align-items:center;justify-content:center;margin-top:16px;height:48px;border-radius:99px;background:linear-gradient(135deg,#FF8A5B,#F4593C);color:#fff;font-size:16px;font-weight:900}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
|
||||
<symbol id="i-back" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
||||
<symbol id="i-right" viewBox="0 0 24 24"><path d="M9 5l7 7-7 7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
||||
<symbol id="i-left" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
||||
<symbol id="i-heart" viewBox="0 0 24 24"><path d="M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z" fill="currentColor"/></symbol>
|
||||
<symbol id="i-pen" viewBox="0 0 24 24"><path d="M4 20l4-1 10-10-3-3L5 16l-1 4zM14 7l3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
||||
<symbol id="i-redo" viewBox="0 0 24 24"><path d="M4 12a8 8 0 1 0 2.3-5.6M4 4v4h4" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
||||
</svg>
|
||||
|
||||
<div id="sc">
|
||||
<header class="top" id="top">
|
||||
<div class="nav">
|
||||
<button class="bk" id="back" type="button" aria-label="返回"><svg class="ic"><use href="#i-back"/></svg></button>
|
||||
<div class="tt"><b>孕妈广场</b><small id="today"></small></div>
|
||||
<span class="ver">效果稿 V5 · 今日广场</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 01 今日一问 -->
|
||||
<section class="q" id="q"></section>
|
||||
|
||||
<!-- 02 故事卡堆 -->
|
||||
<div class="sh"><span class="no">02</span><h2>她们的故事</h2><small>左右滑,看下一张</small></div>
|
||||
<div class="stk-wrap">
|
||||
<div class="stk" id="stk"></div>
|
||||
<div class="stk-ctl">
|
||||
<span class="pg" id="pg"></span>
|
||||
<span class="tr"><i id="tr"></i></span>
|
||||
<button type="button" id="prev" aria-label="上一张"><svg class="ic"><use href="#i-left"/></svg></button>
|
||||
<button type="button" id="next" aria-label="下一张"><svg class="ic"><use href="#i-right"/></svg></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 03 话题榜 -->
|
||||
<div class="sh"><span class="no">03</span><h2>话题榜</h2><small id="rkSub">按在聊人数</small></div>
|
||||
<nav class="tabs" id="tabs" role="tablist"></nav>
|
||||
<div class="rank" id="rank"></div>
|
||||
<a class="rk-ft" id="rkMore">进入广场看全部话题<svg class="ic" style="width:13px;height:13px"><use href="#i-right"/></svg></a>
|
||||
|
||||
<div class="foot">篇数、在聊人数、投票比例均为示例占位<br>效果稿 V5 · 今日广场</div>
|
||||
</div>
|
||||
|
||||
<div class="mask" id="mask"></div>
|
||||
<div class="sheet" id="sheet"></div>
|
||||
|
||||
<script src="../../guangchang/topics.js"></script>
|
||||
<script src="../../guangchang/data.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
'use strict';
|
||||
var $ = function (s) { return document.querySelector(s); };
|
||||
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
|
||||
var TBY = {}; T.forEach(function (t) { TBY[t.id] = t; });
|
||||
var HASH = location.hash || '';
|
||||
var CAT = { family: { name: '家庭婚姻', k: '#E0566F', k2: '#F7A3B2' }, work: { name: '职场', k: '#3A72B8', k2: '#9CC0EA' }, baby: { name: '经验', k: '#2E8A7C', k2: '#93D3C7' } };
|
||||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); };
|
||||
var hs = function (s) { var x = 7; s = String(s); for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
|
||||
var AV = []; for (var i = 1; i <= 22; i++) AV.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) AV.push('p' + (i < 10 ? '0' : '') + i);
|
||||
var avSrc = function (name) { return '../../assets/img/mom/' + AV[hs(name) % AV.length] + '.jpg'; };
|
||||
var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
|
||||
var topicUrl = function (id) { return '../../guangchang/?t=' + id + HASH; };
|
||||
var noteUrl = function (id, k) { return '../../guangchang/?t=' + id + '&n=' + id + '-' + k + HASH; };
|
||||
|
||||
/* 返回 */
|
||||
$('#back').addEventListener('click', function () { history.length > 1 ? history.back() : (location.href = '../../' + location.hash); });
|
||||
var now = new Date();
|
||||
$('#today').textContent = (now.getMonth() + 1) + '月' + now.getDate() + '日';
|
||||
$('#sc').addEventListener('scroll', function () { $('#top').classList.toggle('on', this.scrollTop > 4); }, { passive: true });
|
||||
|
||||
/* ================= 01 今日一问:按日期从精选题里轮一个 ================= */
|
||||
var QS = [
|
||||
{ t: 'f02', q: '长辈按老经验叮嘱你时,你通常会?', a: '笑着应下,转头照自己的来', b: '当场讲道理,说清楚更省心' },
|
||||
{ t: 'w01', q: '怀孕的事,你是什么时候告诉领导的?', a: '过了 12 周、稳了再说', b: '一确认就说,早安排早轻松' },
|
||||
{ t: 'm10', q: '他觉得你在家养胎很轻松,你会?', a: '列给他看,我一天都在忙什么', b: '算了,懒得解释' },
|
||||
{ t: 'b03', q: '刷孕期内容越刷越慌,你会?', a: '卸载 / 屏蔽,眼不见心不慌', b: '继续看,只是换成靠谱来源' },
|
||||
{ t: 'f09', q: '过节亲戚围着肚子问东问西,你会?', a: '笑笑带过,熬过这顿饭', b: '找个理由,早点溜回房间' },
|
||||
{ t: 'w02', q: '请产检假,你会提前多久开口?', a: '提前一周,正式发邮件', b: '前一天口头说一声就行' },
|
||||
{ t: 'm06', q: '孕期最打动你的,是哪一种在意?', a: '一份用心挑的礼物', b: '一盆泡好的洗脚水' }
|
||||
];
|
||||
var dayIdx = Math.floor((now - new Date(now.getFullYear(), 0, 0)) / 864e5);
|
||||
var Q = QS[dayIdx % QS.length], QT = TBY[Q.t] || T[0];
|
||||
var pa = 38 + hs(Q.t + 'v') % 27; /* 占位比例 38~64 */
|
||||
var votes = 1200 + hs(Q.q) % 3800;
|
||||
var VK = 'gcv5-vote-' + Q.t + '-' + dayIdx;
|
||||
function renderQ() {
|
||||
var cat = CAT[QT.cat];
|
||||
var avs = [0, 1, 2, 3].map(function (k) { return '<img loading="lazy" src="' + avSrc(Q.t + k) + '" alt="">'; }).join('');
|
||||
$('#q').innerHTML = '<span class="wm">' + esc(QT.g) + '</span>' +
|
||||
'<div class="hd"><span class="tag"><i></i>今日一问</span><span class="dt">01</span><span class="cat">#' + cat.name + '</span></div>' +
|
||||
'<h3>' + esc(Q.q) + '</h3><p class="sub">来自话题「' + esc(QT.name) + '」</p>' +
|
||||
'<div class="ops">' +
|
||||
'<button class="op" type="button" data-v="a"><span class="bar"></span><span class="lt">A</span><span class="tx">' + esc(Q.a) + '</span><span class="pc">' + pa + '%</span></button>' +
|
||||
'<button class="op" type="button" data-v="b"><span class="bar"></span><span class="lt">B</span><span class="tx">' + esc(Q.b) + '</span><span class="pc">' + (100 - pa) + '%</span></button>' +
|
||||
'</div>' +
|
||||
'<div class="ft"><span class="avs">' + avs + '</span><small id="qn">' + fmt(votes) + ' 位妈妈已表态,你呢?</small>' +
|
||||
'<a class="go" href="' + topicUrl(QT.id) + '">看看大家怎么说<svg class="ic"><use href="#i-right"/></svg></a></div>';
|
||||
var saved = null; try { saved = localStorage.getItem(VK); } catch (e) {}
|
||||
if (saved) vote(saved, true);
|
||||
}
|
||||
function vote(v, quiet) {
|
||||
var q = $('#q'); if (q.classList.contains('done')) return;
|
||||
q.classList.add('done');
|
||||
var A = pa, B = 100 - pa;
|
||||
q.querySelectorAll('.op').forEach(function (b) {
|
||||
var me = b.dataset.v === v; b.classList.toggle('me', me);
|
||||
setTimeout(function () { b.querySelector('.bar').style.width = (b.dataset.v === 'a' ? A : B) + '%'; }, quiet ? 0 : 30);
|
||||
});
|
||||
$('#qn').textContent = (v === 'a' ? A : B) + '% 的妈妈和你想的一样';
|
||||
if (!quiet) try { localStorage.setItem(VK, v); } catch (e) {}
|
||||
}
|
||||
renderQ();
|
||||
$('#q').addEventListener('click', function (e) { var b = e.target.closest('.op'); if (b) vote(b.dataset.v); });
|
||||
|
||||
/* ================= 02 故事卡堆:带真实照片的笔记,按分类轮流排 ================= */
|
||||
var POOL = { family: [], work: [], baby: [] };
|
||||
T.forEach(function (t) {
|
||||
var d = D[t.id]; if (!d || !d.notes) return;
|
||||
d.notes.forEach(function (n, k) { if (n.photo) POOL[t.cat].push({ t: t, n: n, k: k + 1 }); });
|
||||
});
|
||||
var STORIES = [], order = ['family', 'work', 'baby'], guard = 0;
|
||||
while (STORIES.length < 12 && guard++ < 60) order.forEach(function (c) { var p = POOL[c]; if (p.length && STORIES.length < 12) STORIES.push(p.splice(hs(c + guard) % p.length, 1)[0]); });
|
||||
var TOTAL = STORIES.length + 1; /* +1:最后一张「轮到你了」 */
|
||||
var cur = 0;
|
||||
function storyHTML(s) {
|
||||
var c = CAT[s.t.cat];
|
||||
return '<img class="ph" loading="lazy" src="../../guangchang/' + esc(s.n.photo) + '" alt="">' +
|
||||
'<div class="sh2"></div>' +
|
||||
'<span class="kt"><i style="background:' + c.k + '"></i>' + c.name + '</span>' +
|
||||
'<span class="lk"><svg class="ic"><use href="#i-heart"/></svg>' + fmt(s.n.likes || 0) + '</span>' +
|
||||
'<div class="bt"><div class="tp"># ' + esc(s.t.name) + '</div><h4>' + esc(s.n.title) + '</h4>' +
|
||||
'<div class="au"><img loading="lazy" src="' + avSrc(s.n.author) + '" alt=""><b>' + esc(s.n.author) + '</b><span>' + esc(s.n.stage || '') + '</span>' +
|
||||
'<em class="rd">读全文<svg class="ic"><use href="#i-right"/></svg></em></div></div>';
|
||||
}
|
||||
var YOU = '<div class="in"><span class="pen"><svg class="ic"><use href="#i-pen"/></svg></span>' +
|
||||
'<span class="k">STORY ' + TOTAL + ' / ' + TOTAL + '</span><div class="big">轮到你了</div>' +
|
||||
'<p class="lede">看完她们的故事,<br>你也有一段想说的经历吗?<br>挑一个话题,写下来就好。</p>' +
|
||||
'<div class="rw"><small>投稿被选中,每篇奖励</small><b><em>¥30</em> 现金 + <em>500</em> 兜豆</b></div>' +
|
||||
'<button class="cta" type="button" data-join="1"><svg class="ic"><use href="#i-pen"/></svg>写我的故事</button></div>';
|
||||
var stk = $('#stk'), cards = [];
|
||||
STORIES.forEach(function (s, i) {
|
||||
var el = document.createElement('a'); el.className = 'sc'; el.href = noteUrl(s.t.id, s.k); el.draggable = false;
|
||||
el.innerHTML = storyHTML(s); stk.appendChild(el); cards.push(el);
|
||||
});
|
||||
var you = document.createElement('div'); you.className = 'sc you'; you.innerHTML = YOU; stk.appendChild(you); cards.push(you);
|
||||
|
||||
function layout(dx) {
|
||||
cards.forEach(function (el, i) {
|
||||
var d = i - cur, tf, op = 1, z = 100 - Math.abs(d);
|
||||
if (d < 0) { tf = 'translate3d(-130%,0,0) rotate(-14deg)'; op = 0; }
|
||||
else if (d === 0) { tf = 'translate3d(' + (dx || 0) + 'px,0,0) rotate(' + ((dx || 0) / 22) + 'deg)'; }
|
||||
else if (d <= 2) {
|
||||
var p = dx ? Math.min(Math.abs(dx) / 160, 1) : 0, dd = d - p;
|
||||
tf = 'translate3d(0,' + (dd * 14) + 'px,0) scale(' + (1 - dd * 0.05) + ')';
|
||||
op = d === 2 ? 0.9 : 1;
|
||||
} else { tf = 'translate3d(0,28px,0) scale(.9)'; op = 0; }
|
||||
el.style.transform = tf; el.style.opacity = op; el.style.zIndex = z;
|
||||
el.style.pointerEvents = d === 0 ? 'auto' : 'none';
|
||||
});
|
||||
$('#pg').innerHTML = '<b>' + (cur + 1) + '</b> / ' + TOTAL;
|
||||
$('#tr').style.width = ((cur + 1) / TOTAL * 100) + '%';
|
||||
$('#prev').disabled = cur === 0; $('#next').disabled = cur === TOTAL - 1;
|
||||
}
|
||||
function go(n) { cur = Math.max(0, Math.min(TOTAL - 1, n)); layout(0); }
|
||||
layout(0);
|
||||
$('#prev').addEventListener('click', function () { go(cur - 1); });
|
||||
$('#next').addEventListener('click', function () { go(cur + 1); });
|
||||
|
||||
/* 拖拽滑卡(触摸 + 鼠标),水平位移大才算滑,否则当点击 */
|
||||
var drag = null, moved = false;
|
||||
function pt(e) { var t = e.touches ? e.touches[0] : e; return { x: t.clientX, y: t.clientY }; }
|
||||
function onDown(e) { if (e.target.closest('[data-join]')) return; var p = pt(e); drag = { x: p.x, y: p.y, dx: 0, lock: '' }; moved = false; }
|
||||
function onMove(e) {
|
||||
if (!drag) return; var p = pt(e), dx = p.x - drag.x, dy = p.y - drag.y;
|
||||
if (!drag.lock && (Math.abs(dx) > 6 || Math.abs(dy) > 6)) drag.lock = Math.abs(dx) > Math.abs(dy) ? 'x' : 'y';
|
||||
if (drag.lock !== 'x') return;
|
||||
if (e.cancelable) e.preventDefault();
|
||||
moved = true; drag.dx = dx;
|
||||
cards[cur].style.transition = 'none'; layout(dx);
|
||||
}
|
||||
function onUp() {
|
||||
if (!drag) return; var dx = drag.dx; drag = null;
|
||||
cards[cur].style.transition = '';
|
||||
if (dx < -70 && cur < TOTAL - 1) go(cur + 1);
|
||||
else if (dx > 70 && cur > 0) go(cur - 1);
|
||||
else layout(0);
|
||||
}
|
||||
stk.addEventListener('touchstart', onDown, { passive: true });
|
||||
stk.addEventListener('touchmove', onMove, { passive: false });
|
||||
stk.addEventListener('touchend', onUp); stk.addEventListener('touchcancel', onUp);
|
||||
stk.addEventListener('mousedown', function (e) { e.preventDefault(); onDown(e); });
|
||||
window.addEventListener('mousemove', onMove); window.addEventListener('mouseup', onUp);
|
||||
stk.addEventListener('click', function (e) {
|
||||
if (moved) { e.preventDefault(); moved = false; return; }
|
||||
if (e.target.closest('[data-join]')) { e.preventDefault(); openJoin(); }
|
||||
});
|
||||
|
||||
/* 投稿说明弹层 */
|
||||
function openJoin() {
|
||||
var hot = T.filter(function (t) { return t.hot; }).slice(0, 6);
|
||||
$('#sheet').innerHTML = '<h3>写下你的孕期故事</h3><p>选一个你有感触的话题,真实经历就好,不用写得很长。</p>' +
|
||||
'<div class="rb"><small>投稿被选中,每篇奖励</small><b><em>¥30</em> 现金 + <em>500</em> 兜豆</b></div>' +
|
||||
'<div class="pk">' + hot.map(function (t) { return '<a href="' + topicUrl(t.id) + '"># ' + esc(t.name) + '</a>'; }).join('') + '</div>' +
|
||||
'<a class="bt2" href="../../guangchang/' + HASH + '">去广场投稿</a>';
|
||||
$('#mask').classList.add('on'); $('#sheet').classList.add('on');
|
||||
}
|
||||
$('#mask').addEventListener('click', function () { $('#mask').classList.remove('on'); $('#sheet').classList.remove('on'); });
|
||||
|
||||
/* ================= 03 话题榜 ================= */
|
||||
var catF = 'all';
|
||||
var TABS = [['all', '全部', '#F4593C'], ['family', '家庭婚姻', CAT.family.k], ['work', '职场', CAT.work.k], ['baby', '经验', CAT.baby.k]];
|
||||
function renderTabs() {
|
||||
$('#tabs').innerHTML = TABS.map(function (x) {
|
||||
return '<button type="button" role="tab" data-c="' + x[0] + '" style="--k:' + x[2] + '" class="' + (catF === x[0] ? 'on' : '') + '" aria-selected="' + (catF === x[0]) + '"><i></i>' + x[1] + '</button>';
|
||||
}).join('');
|
||||
}
|
||||
function renderRank() {
|
||||
var byTalk = function (a, b) { return b.talk - a.talk; }, list;
|
||||
if (catF === 'all') { /* 全部:各分类各取前几名再合排,避免整榜都是一个分类 */
|
||||
var q = { family: 4, work: 3, baby: 3 }; list = [];
|
||||
Object.keys(q).forEach(function (c) { list = list.concat(T.filter(function (t) { return t.cat === c; }).sort(byTalk).slice(0, q[c])); });
|
||||
list.sort(byTalk);
|
||||
} else list = T.filter(function (t) { return t.cat === catF; }).sort(byTalk).slice(0, 10);
|
||||
var max = list.length ? list[0].talk : 1;
|
||||
$('#rank').innerHTML = list.map(function (t, i) {
|
||||
var c = CAT[t.cat];
|
||||
return '<a class="rk t' + (i + 1) + '" href="' + topicUrl(t.id) + '" style="--k:' + c.k + ';--k2:' + c.k2 + '">' +
|
||||
'<span class="n">' + (i + 1) + '</span>' +
|
||||
'<span class="bd"><span class="nm"><b>' + esc(t.name) + '</b></span>' +
|
||||
'<span class="mt">' + (catF === 'all' ? '<span class="kc">' + c.name + '</span>' : '') + (t.hot ? '<span class="hot">热</span>' : '') + '<span class="hb"><i data-w="' + Math.max(12, Math.round(t.talk / max * 100)) + '"></i></span><span class="tk"><em>' + fmt(t.talk) + '</em> 在聊</span></span></span>' +
|
||||
(t.ph ? '<img class="th" loading="lazy" src="../../' + esc(t.ph) + '" alt="">' : '') + '</a>';
|
||||
}).join('');
|
||||
$('#rkSub').textContent = (catF === 'all' ? '全部话题' : CAT[catF].name) + ' · 按在聊人数';
|
||||
requestAnimationFrame(function () { requestAnimationFrame(function () {
|
||||
document.querySelectorAll('#rank .hb i').forEach(function (b) { b.style.width = b.dataset.w + '%'; });
|
||||
}); });
|
||||
}
|
||||
renderTabs(); renderRank();
|
||||
$('#rkMore').href = '../../guangchang/' + HASH;
|
||||
$('#tabs').addEventListener('click', function (e) {
|
||||
var b = e.target.closest('button[data-c]'); if (!b || b.dataset.c === catF) return;
|
||||
catF = b.dataset.c; renderTabs(); renderRank();
|
||||
});
|
||||
|
||||
/* ================= 禁止下拉回弹 ================= */
|
||||
var sx = 0, sy = 0;
|
||||
document.addEventListener('touchstart', function (e) { if (e.touches.length === 1) { sx = e.touches[0].clientX; sy = e.touches[0].clientY; } }, { passive: true });
|
||||
document.addEventListener('touchmove', function (e) {
|
||||
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
|
||||
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
|
||||
if (Math.abs(dy) <= Math.abs(dx)) return;
|
||||
var el = e.target;
|
||||
while (el && el !== document.body && el !== document.documentElement) {
|
||||
if (el.nodeType === 1) {
|
||||
var oy = getComputedStyle(el).overflowY;
|
||||
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
|
||||
if (dy > 0 && el.scrollTop > 0) return;
|
||||
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
|
||||
}
|
||||
}
|
||||
el = el.parentNode;
|
||||
}
|
||||
if (e.cancelable) e.preventDefault();
|
||||
}, { passive: false });
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
43
demo/gc/index.html
Normal file
43
demo/gc/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!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,viewport-fit=cover">
|
||||
<title>孕妈广场 · 五版效果稿</title>
|
||||
<!-- 11-01 用户:「孕妈广场这个页面重新做一版…做五版,效果图给我带链接的,点击可以直接查看」。演示汇总页,图是各版首屏长截图,点图/按钮进对应演示页(带上 hash 身份) -->
|
||||
<style>
|
||||
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
|
||||
body{margin:0;background:#F6F1EC;font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;color:#2B2320}
|
||||
header{padding:calc(22px + env(safe-area-inset-top)) 18px 8px}
|
||||
h1{margin:0;font-size:22px;font-weight:900}
|
||||
header p{margin:6px 0 0;font-size:13px;color:#8A7570}
|
||||
.list{display:grid;gap:22px;padding:14px 14px 40px;max-width:900px;margin:0 auto}
|
||||
@media(min-width:760px){.list{grid-template-columns:repeat(2,1fr)}}
|
||||
.it{background:#fff;border-radius:20px;overflow:hidden;box-shadow:0 10px 30px -18px rgba(120,70,50,.45)}
|
||||
.hd{display:flex;align-items:center;gap:10px;padding:14px 16px}
|
||||
.hd b{flex:none;width:34px;height:34px;border-radius:11px;background:#F4593C;color:#fff;display:grid;place-items:center;font-size:15px;font-weight:900}
|
||||
.hd div{flex:1;min-width:0}
|
||||
.hd h2{margin:0;font-size:16px;font-weight:900}
|
||||
.hd small{display:block;font-size:12px;color:#8A7570;margin-top:2px;line-height:1.45}
|
||||
.pic{display:block;height:560px;overflow:hidden;border-top:1px solid #F1E7E1;border-bottom:1px solid #F1E7E1;position:relative}
|
||||
.pic img{width:100%;display:block}
|
||||
.pic::after{content:"";position:absolute;left:0;right:0;bottom:0;height:70px;background:linear-gradient(transparent,#fff)}
|
||||
.go{display:flex;align-items:center;justify-content:center;height:46px;margin:12px 16px 16px;border-radius:14px;background:#2B2320;color:#fff;font-size:14.5px;font-weight:800;text-decoration:none}
|
||||
</style></head><body>
|
||||
<header><h1>孕妈广场 · 五版效果稿</h1><p>点图片或按钮直接打开那一版,可以切分类、点进文章看看。</p></header>
|
||||
<div class="list" id="list"></div>
|
||||
<script>
|
||||
var V = [
|
||||
['孕妈周刊', '整页像一本当期杂志:封面故事、本期目录、专栏图文混排,投稿是「征稿启事」'],
|
||||
['广场地图', '俯视小广场插画,三个分类是三个角落,妈妈们站着聊天;投稿是广场上的信箱'],
|
||||
['留言墙', '软木板上的便签和拍立得,话题是彩色便签,照片笔记是相片;投稿是一叠空白便签'],
|
||||
['聊天广场', '每个话题像一个聊天室,直接看到大家在说什么;底部输入条就是投稿入口'],
|
||||
['今日广场', '今日一问投票 + 左右滑的故事卡堆 + 话题榜;卡堆最后一张「轮到你了」投稿']
|
||||
];
|
||||
var h = location.hash;
|
||||
document.getElementById('list').innerHTML = V.map(function (v, i) {
|
||||
var u = '../gc-v' + (i + 1) + '/' + h;
|
||||
return '<div class="it"><div class="hd"><b>V' + (i + 1) + '</b><div><h2>' + v[0] + '</h2><small>' + v[1] + '</small></div></div>' +
|
||||
'<a class="pic" href="' + u + '"><img src="v' + (i + 1) + '.jpg?2" alt="' + v[0] + '" loading="lazy"></a>' +
|
||||
'<a class="go" href="' + u + '">打开 V' + (i + 1) + ' ' + v[0] + '</a></div>';
|
||||
}).join('');
|
||||
</script>
|
||||
</body></html>
|
||||
BIN
demo/gc/v1.jpg
Normal file
BIN
demo/gc/v1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
BIN
demo/gc/v2.jpg
Normal file
BIN
demo/gc/v2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
BIN
demo/gc/v3.jpg
Normal file
BIN
demo/gc/v3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 171 KiB |
BIN
demo/gc/v4.jpg
Normal file
BIN
demo/gc/v4.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
BIN
demo/gc/v5.jpg
Normal file
BIN
demo/gc/v5.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 138 KiB |
Reference in New Issue
Block a user