681 lines
46 KiB
HTML
681 lines
46 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
|
||
<meta name="format-detection" content="telephone=no">
|
||
<title>孕妈广场</title>
|
||
<!-- 孕妈广场(2026-11-01 第一版,占位内容,纯前端;mama-box 首页「孕妈广场」横滑卡点进来)
|
||
用户原话:「点进去之后变成小红书那种瀑布流,每一个话题都是那样的。先整理出来 15 个话题,先做占位放上。点击详情页的时候可以点赞和评论。」
|
||
· 话题表 topics.js(与首页共用);笔记 / 评论池 data.js(每话题 7 条笔记 + 10 条评论池,评论按笔记 id 确定性抽 3~8 条)。
|
||
· URL:?t=话题id 进对应话题,&n=笔记id 直接打开详情;切 tab 只用 replaceState 改 query,**hash 原样保留**(身份 #openid 在里面)。
|
||
· 点赞 / 收藏 / 评论 / 评论点赞只存本机 localStorage「mmbox.gc.v1」,按 openid 分开;正式版接后端时整块替换 store。
|
||
· 返回:详情层 → history.back() 关层;列表 → 有站内历史就 history.back(),没有就回 ../(保留身份,去掉 t/n)。
|
||
· 禁止下拉回弹:固定外壳 + 容器滚动 + touchmove 拦截(同首页那段:往上找能朝该方向滚的容器,找不到才拦)。 -->
|
||
<style>
|
||
:root{
|
||
--brand:#F4593C;--ink:#2B2320;--ink-2:#6B615B;--muted:#9A8380;--line:#F1E7E1;
|
||
--bg:#F8F3EF;--peach:#FFEDE6;--btn:linear-gradient(135deg,#F77B55,#EE5A3E);
|
||
--safe-b:env(safe-area-inset-bottom);
|
||
}
|
||
*{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","Segoe UI",Roboto,sans-serif;
|
||
color:var(--ink);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5;-webkit-text-size-adjust:100%}
|
||
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
|
||
.ic{width:16px;height:16px;flex:none;display:inline-block;vertical-align:middle}
|
||
.hide{display:none!important}
|
||
|
||
/* ---------- 外壳:唯一的滚动容器 ---------- */
|
||
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;
|
||
background:radial-gradient(220px 180px at 100% 0,rgba(255,196,214,.45),rgba(255,196,214,0) 70%),radial-gradient(240px 200px at 0 40px,rgba(255,206,170,.45),rgba(255,206,170,0) 70%),var(--bg)}
|
||
#sc::-webkit-scrollbar{display:none}
|
||
.top{position:sticky;top:0;z-index:20;padding-top:env(safe-area-inset-top);background:rgba(248,243,239,.9);-webkit-backdrop-filter:blur(14px) saturate(160%);backdrop-filter:blur(14px) saturate(160%);transition:box-shadow .2s}
|
||
.top.on{box-shadow:0 4px 14px rgba(160,110,90,.10)}
|
||
.nav{display:flex;align-items:center;gap:6px;height:46px;padding:0 10px}
|
||
.nav .bk{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;color:var(--ink)}
|
||
.nav .bk:active{background:rgba(0,0,0,.05)}
|
||
.nav .bk .ic{width:22px;height:22px}
|
||
.nav h1{flex:1;margin:0;text-align:center;font-size:17px;font-weight:900;letter-spacing:.5px}
|
||
.nav h1 span{background:linear-gradient(transparent 60%,#FFD0DC 60%,#FFD0DC 92%,transparent 92%);padding:0 3px}
|
||
.nav .sp{width:36px}
|
||
|
||
/* ---------- 一级分类:全部 / 家庭关系 / 宝妈经验(11-01 第二版:原先右侧小分段太不显眼) ---------- */
|
||
.cats{display:flex;gap:8px;padding:4px 12px 10px}
|
||
.cats button{flex:1;min-width:0;height:42px;display:flex;align-items:center;justify-content:center;gap:6px;border-radius:14px;background:#fff;border:1.5px solid #F1E2DA;
|
||
font-size:15px;font-weight:800;color:#6E5A55;letter-spacing:.3px;box-shadow:0 2px 8px rgba(170,110,90,.06);transition:background .18s,color .18s,border-color .18s,box-shadow .18s}
|
||
.cats button .ci2{width:22px;height:22px;flex:none;display:grid;place-items:center;border-radius:8px;background:var(--cb);color:var(--cf)}
|
||
.cats button .ci2 .ic{width:14px;height:14px}
|
||
.cats button small{font-size:11px;font-weight:700;color:#B09A94;margin-left:-2px}
|
||
.cats button.on{background:var(--cf);border-color:var(--cf);color:#fff;box-shadow:0 6px 14px -6px var(--cf)}
|
||
.cats button.on .ci2{background:rgba(255,255,255,.22);color:#fff}
|
||
.cats button.on small{color:rgba(255,255,255,.8)}
|
||
.cats button:active{transform:scale(.97)}
|
||
.cats .c-all{--cf:#F4593C;--cb:#FFEDE6}
|
||
.cats .c-family{--cf:#E0566F;--cb:#FFE6EB}
|
||
.cats .c-exp{--cf:#2E8A7C;--cb:#DDF2EE}
|
||
.tabs{display:flex;gap:6px;padding:0 12px 10px;overflow-x:auto;overflow-y:hidden;scroll-behavior:smooth;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
|
||
.tabs::-webkit-scrollbar{display:none}
|
||
.tabs::after{content:"";flex:none;width:6px}
|
||
.tabs button{flex:none;height:30px;padding:0 13px;border-radius:99px;background:rgba(255,255,255,.75);border:1px solid #F0E2DA;font-size:13px;font-weight:600;color:#7A6663;white-space:nowrap;transition:background .15s,color .15s}
|
||
.tabs button.on{background:#2F2424;border-color:#2F2424;color:#fff;font-weight:800}
|
||
.tabs.k-family button.on{background:#FFE6EB;border-color:#F3A9B7;color:#C23A55}
|
||
.tabs.k-exp button.on{background:#DDF2EE;border-color:#93CFC4;color:#21705F}
|
||
.tabs.k-family button.on .hb,.tabs.k-exp button.on .hb{background:#FF5A3C}
|
||
.tabs button .hb{display:inline-block;margin-left:3px;padding:0 4px;border-radius:5px;background:#FF5A3C;color:#fff;font-size:9.5px;font-weight:800;line-height:15px;vertical-align:1px}
|
||
.tabs button.on .hb{background:#FF7A5C}
|
||
|
||
/* ---------- 话题头卡 ---------- */
|
||
.th{position:relative;margin:4px 12px 2px;padding:16px 16px 14px;border-radius:22px;overflow:hidden;
|
||
background:linear-gradient(150deg,var(--c1),var(--c2));color:var(--tk);box-shadow:0 12px 26px -16px var(--tk)}
|
||
.th .tg{position:absolute;right:-6px;top:-10px;font-size:110px;font-weight:900;line-height:1;color:#fff;opacity:.5;font-family:"STKaiti","KaiTi","Kaiti SC",serif;pointer-events:none}
|
||
.th .tc{display:inline-flex;align-items:center;height:20px;padding:0 8px;border-radius:7px;background:rgba(255,255,255,.65);font-size:11px;font-weight:800;letter-spacing:.5px}
|
||
.th .tc.k-family{background:#E0566F;color:#fff}
|
||
.th .tc.k-exp{background:#2E8A7C;color:#fff}
|
||
.th h2{position:relative;margin:8px 0 4px;font-size:21px;font-weight:900;line-height:1.3;color:#2A1E1E;letter-spacing:.3px}
|
||
.th h2 em{font-style:normal;color:var(--tk);margin-right:2px}
|
||
.th p{position:relative;margin:0;max-width:270px;font-size:12.5px;line-height:1.6;color:#5E4E4A}
|
||
.th .tf{position:relative;display:flex;align-items:center;gap:10px;margin-top:12px}
|
||
.th .ts{flex:1;display:flex;align-items:center;gap:7px;font-size:12px;color:#6E5C57}
|
||
.th .ts b{color:var(--tk);font-weight:900;font-variant-numeric:tabular-nums}
|
||
.th .avs{display:flex}
|
||
.th .avs img{width:20px;height:20px;border-radius:50%;object-fit:cover;border:1.5px solid rgba(255,255,255,.9);margin-left:-6px;background:#FFE3D3}
|
||
.th .avs img:first-child{margin-left:0}
|
||
.th .join{flex:none;height:32px;padding:0 14px;border-radius:99px;background:#fff;color:var(--tk);font-size:13px;font-weight:800;box-shadow:0 4px 10px rgba(0,0,0,.08);display:inline-flex;align-items:center;gap:4px}
|
||
.th .join .ic{width:14px;height:14px}
|
||
/* 未选具体话题时的一句引导 */
|
||
.intro{display:flex;align-items:center;gap:8px;margin:2px 14px 0;font-size:12px;color:var(--muted)}
|
||
.intro b{color:var(--ink);font-weight:800}
|
||
|
||
/* ---------- 瀑布流 ---------- */
|
||
.wf{display:flex;align-items:flex-start;gap:8px;padding:10px 12px 0}
|
||
.wf .col{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px}
|
||
.nc{display:block;width:100%;text-align:left;border-radius:14px;overflow:hidden;background:#fff;box-shadow:0 3px 12px rgba(170,110,90,.08);animation:ncIn .35s ease both}
|
||
.nc:active{transform:scale(.985)}
|
||
@keyframes ncIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
|
||
.nc .cvw{position:relative}
|
||
.nc .nb{padding:8px 9px 9px}
|
||
.nc h3{margin:0;font-size:13.5px;font-weight:700;line-height:1.45;color:#2A2220;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
||
.nc .nf{display:flex;align-items:center;gap:5px;margin-top:7px}
|
||
.nc .nf img{width:18px;height:18px;border-radius:50%;object-fit:cover;flex:none;background:#FFE3D3}
|
||
.nc .nf .nm{flex:1;min-width:0;font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.lk{flex:none;display:inline-flex;align-items:center;gap:2px;min-width:44px;justify-content:flex-end;height:22px;font-size:11.5px;color:var(--muted);font-variant-numeric:tabular-nums}
|
||
.lk .ic{width:15px;height:15px}
|
||
.lk.on{color:#F0453A}
|
||
.lk.pop .ic{animation:pop .35s ease}
|
||
@keyframes pop{40%{transform:scale(1.35)}}
|
||
.nc .ttag{position:absolute;left:7px;top:7px;z-index:2;height:18px;padding:0 6px;border-radius:6px;background:rgba(40,28,26,.38);color:#fff;font-size:10px;font-weight:700;line-height:18px;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);max-width:82%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.nc .ttag.k-family{background:rgba(214,74,100,.82)}
|
||
.nc .ttag.k-exp{background:rgba(38,128,114,.82)}
|
||
|
||
.end{padding:22px 0 calc(26px + var(--safe-b));text-align:center}
|
||
.end b{display:block;font-size:12px;font-weight:600;color:#C2ABA4;letter-spacing:2px}
|
||
.end small{display:block;margin-top:8px;font-size:10.5px;color:#CDBBB5;opacity:.85}
|
||
|
||
/* ---------- 封面(em 计:卡片 1em≈13px,详情放大) ---------- */
|
||
.cv{position:relative;width:100%;overflow:hidden;font-size:13px;color:var(--tk);isolation:isolate}
|
||
.cv .t1{position:relative;z-index:1;font-weight:900;line-height:1.25;letter-spacing:.04em;word-break:break-all}
|
||
.cv .t2{position:relative;z-index:1;font-weight:700;opacity:.82;line-height:1.4}
|
||
.cv i{font-style:normal}
|
||
/* s0 渐变 + 荧光笔 */
|
||
.cv.s0{background:linear-gradient(160deg,var(--c1),var(--c2));display:flex;flex-direction:column;justify-content:center;padding:0 1.2em}
|
||
.cv.s0 .t1{font-size:1.75em;color:#2A1E1E}
|
||
.cv.s0 .t1 span{background:linear-gradient(transparent 58%,rgba(255,255,255,.85) 58%,rgba(255,255,255,.85) 90%,transparent 90%)}
|
||
.cv.s0 .t2{margin-top:.7em;font-size:.95em}
|
||
.cv.s0 .dc{position:absolute;right:-1.6em;top:-1.6em;width:6em;height:6em;border-radius:50%;background:rgba(255,255,255,.35)}
|
||
.cv.s0 .dc2{position:absolute;left:1.2em;bottom:1.1em;width:2.4em;height:.32em;border-radius:1em;background:var(--tk);opacity:.5}
|
||
/* s1 便签纸 + 胶带 */
|
||
.cv.s1{background:radial-gradient(circle,rgba(255,255,255,.55) 1.2px,transparent 1.6px) 0 0/14px 14px,var(--c2);display:grid;place-items:center;padding:1.3em 1em}
|
||
.cv.s1 .pp{position:relative;width:100%;padding:1.3em .9em 1em;background:#FFFDF8;border-radius:.3em;box-shadow:0 .5em 1em -.4em rgba(80,40,30,.35);transform:rotate(-2.5deg)}
|
||
.cv.s1 .pp::before{content:"";position:absolute;left:50%;top:-.6em;width:4em;height:1.2em;margin-left:-2em;background:rgba(255,255,255,.65);border:1px solid rgba(0,0,0,.04);transform:rotate(3deg)}
|
||
.cv.s1 .t1{font-size:1.45em;color:#3A2C28}
|
||
.cv.s1 .t2{margin-top:.5em;font-size:.88em;color:var(--tk)}
|
||
/* s2 深色大引号 */
|
||
.cv.s2{background:radial-gradient(9em 7em at 100% 0,rgba(255,255,255,.18),transparent 70%),linear-gradient(160deg,var(--tk),#2E2230);color:#FFF4EA;display:flex;flex-direction:column;justify-content:flex-end;padding:1.1em 1.1em 1.2em}
|
||
.cv.s2 .q{position:absolute;right:.45em;top:-.15em;font-size:5.5em;font-weight:900;line-height:1;color:var(--c2);opacity:.75;font-family:Georgia,serif}
|
||
.cv.s2 .t1{font-size:1.6em}
|
||
.cv.s2 .t2{margin-top:.55em;font-size:.9em;color:var(--c2);opacity:1}
|
||
/* s3 横线本 */
|
||
.cv.s3{background:repeating-linear-gradient(180deg,transparent 0,transparent 1.75em,rgba(170,140,120,.22) 1.75em,rgba(170,140,120,.22) calc(1.75em + 1px)),#FFFCF6;padding:1.2em 1em 1em 1.9em;display:flex;flex-direction:column;justify-content:center}
|
||
.cv.s3::before{content:"";position:absolute;left:1.15em;top:0;bottom:0;width:1.5px;background:rgba(240,110,100,.45)}
|
||
.cv.s3 .t1{font-size:1.5em;color:#2F2424}
|
||
.cv.s3 .t1 span{background:linear-gradient(transparent 55%,var(--c2) 55%,var(--c2) 92%,transparent 92%)}
|
||
.cv.s3 .t2{margin-top:.7em;font-size:.9em;color:var(--tk)}
|
||
.cv.s3 .ck{display:flex;gap:.35em;margin-top:.8em}
|
||
.cv.s3 .ck i{width:.95em;height:.95em;border-radius:.25em;border:1.5px solid var(--tk);opacity:.6}
|
||
.cv.s3 .ck i:first-child{background:var(--tk)}
|
||
/* s4 大圆 + 水印字 */
|
||
.cv.s4{background:var(--c1);display:flex;flex-direction:column;justify-content:flex-end;padding:1em 1.1em 1.1em}
|
||
.cv.s4 .bc{position:absolute;right:-1.4em;top:-1.2em;width:8.4em;height:8.4em;border-radius:50%;background:linear-gradient(150deg,var(--c2),rgba(255,255,255,.4));display:grid;place-items:center}
|
||
.cv.s4 .bc b{font-size:4em;font-weight:900;color:#fff;opacity:.8;font-family:"STKaiti","KaiTi","Kaiti SC",serif;transform:translate(-.08em,.06em)}
|
||
.cv.s4 .t1{font-size:1.6em;color:#2A1E1E}
|
||
.cv.s4 .t2{margin-top:.45em;font-size:.9em}
|
||
/* s5 方格纸 + 印章 */
|
||
.cv.s5{background:linear-gradient(rgba(170,140,120,.13) 1px,transparent 1px) 0 0/1.2em 1.2em,linear-gradient(90deg,rgba(170,140,120,.13) 1px,transparent 1px) 0 0/1.2em 1.2em,#FFF9F3;display:flex;flex-direction:column;justify-content:center;padding:1em 1.1em}
|
||
.cv.s5 .st{align-self:flex-start;margin-bottom:.7em;padding:.2em .6em;border-radius:.4em;background:var(--tk);color:#fff;font-size:.8em;font-weight:800;letter-spacing:.08em;transform:rotate(-3deg)}
|
||
.cv.s5 .t1{font-size:1.55em;color:#2F2424}
|
||
.cv.s5 .t2{margin-top:.55em;font-size:.88em}
|
||
.cv.s5 .sm{position:absolute;right:.8em;bottom:.8em;width:3.2em;height:3.2em;border-radius:50%;border:2px solid var(--tk);color:var(--tk);display:grid;place-items:center;font-size:.8em;font-weight:900;opacity:.55;transform:rotate(-14deg)}
|
||
|
||
/* ---------- 详情层 ---------- */
|
||
#dt{position:fixed;inset:0;z-index:40;background:#fff;transform:translateX(100%);transition:transform .32s cubic-bezier(.2,.8,.2,1);display:flex;flex-direction:column}
|
||
#dt.show{transform:none}
|
||
#dt .dnav{flex:none;display:flex;align-items:center;gap:8px;height:calc(50px + env(safe-area-inset-top));padding:env(safe-area-inset-top) 12px 0 6px;background:#fff;border-bottom:1px solid transparent;transition:border-color .2s}
|
||
#dt .dnav.on{border-color:var(--line)}
|
||
#dt .dnav .bk{width:36px;height:36px;display:grid;place-items:center;border-radius:50%}
|
||
#dt .dnav .bk .ic{width:22px;height:22px}
|
||
#dt .dnav img{width:30px;height:30px;border-radius:50%;object-fit:cover;background:#FFE3D3}
|
||
#dt .dnav .who{flex:1;min-width:0;display:flex;flex-direction:column;line-height:1.25}
|
||
#dt .dnav .who b{font-size:14px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
#dt .dnav .who small{font-size:11px;color:var(--muted)}
|
||
#dt .dnav .fo{flex:none;height:28px;padding:0 13px;border-radius:99px;border:1.5px solid #F4593C;color:#F4593C;font-size:12.5px;font-weight:800}
|
||
#dt .dnav .fo.on{border-color:#E5DAD5;color:var(--muted)}
|
||
#dsc{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none}
|
||
#dsc::-webkit-scrollbar{display:none}
|
||
.dcv .cv{font-size:26px}
|
||
.dbody{padding:16px 18px 6px}
|
||
.dbody h2{margin:0;font-size:19px;font-weight:900;line-height:1.45;letter-spacing:.2px}
|
||
.dbody .tx{margin-top:10px;font-size:15px;line-height:1.85;color:#3A302C;letter-spacing:.2px}
|
||
.dbody .tx p{margin:0 0 14px}
|
||
.dbody .tx p.li{margin:-6px 0 14px;padding-left:1.3em;text-indent:-1.3em}
|
||
.dbody .tx p.li+p.li{margin-top:-10px}
|
||
.dbody .tgs{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
|
||
.dbody .tgs button{height:24px;padding:0 9px;border-radius:99px;background:var(--peach);color:#D9583C;font-size:12.5px;font-weight:700}
|
||
.dbody .tm{margin-top:12px;font-size:12px;color:#B8A49E}
|
||
.cm{margin-top:8px;padding:14px 18px 20px;border-top:8px solid #F8F3EF}
|
||
.cm-h{display:flex;align-items:baseline;gap:6px;font-size:15px;font-weight:900}
|
||
.cm-h small{font-size:12.5px;font-weight:500;color:var(--muted)}
|
||
.cm-in{display:flex;align-items:center;gap:8px;margin-top:12px}
|
||
.cm-in .me{width:30px;height:30px;border-radius:50%;flex:none;display:grid;place-items:center;background:linear-gradient(140deg,#FFC9B5,#F59A7F);color:#fff;font-size:12px;font-weight:800}
|
||
.cm-in button{flex:1;height:34px;padding:0 14px;border-radius:99px;background:#F5EEEA;text-align:left;font-size:13px;color:#B3A19B}
|
||
.ci{display:flex;gap:10px;padding:14px 0 12px;border-bottom:1px solid #F5EDE8}
|
||
.ci:last-child{border-bottom:0}
|
||
.ci>img,.ci>.me{width:32px;height:32px;border-radius:50%;object-fit:cover;flex:none;background:#FFE3D3}
|
||
.ci>.me{display:grid;place-items:center;background:linear-gradient(140deg,#FFC9B5,#F59A7F);color:#fff;font-size:12px;font-weight:800}
|
||
.ci.mine{animation:ncIn .35s ease both}
|
||
.ci-b{flex:1;min-width:0}
|
||
.ci-n{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--muted)}
|
||
.ci-n b{color:#7A6A64;font-weight:700}
|
||
.ci-n .au{height:16px;padding:0 5px;border-radius:4px;background:#F4593C;color:#fff;font-size:10px;font-weight:800;line-height:16px}
|
||
.ci-n .mt{height:16px;padding:0 5px;border-radius:4px;background:#FFE7E0;color:#EC4D33;font-size:10px;font-weight:800;line-height:16px}
|
||
.ci-n .lk{margin-left:auto}
|
||
.ci-t{margin:3px 0 0;font-size:14.5px;line-height:1.65;color:#2F2624;word-break:break-word}
|
||
.ci-s{margin-top:3px;font-size:11.5px;color:#B8A49E}
|
||
.rp{margin-top:8px;padding:8px 10px;border-radius:10px;background:#F8F3EF;font-size:13px;line-height:1.65;color:#3A302C}
|
||
.rp p{margin:0 0 4px}
|
||
.rp p:last-child{margin-bottom:0}
|
||
.rp b{font-weight:700;color:#7A6A64}
|
||
.rp .au{display:inline-block;height:15px;margin:0 3px 0 -1px;padding:0 4px;border-radius:4px;background:#F4593C;color:#fff;font-size:9.5px;font-weight:800;line-height:15px;vertical-align:1px}
|
||
.cm-end{padding:18px 0 6px;text-align:center;font-size:12px;color:#C9B7B1}
|
||
|
||
.bar{flex:none;display:flex;align-items:center;gap:6px;padding:8px 10px calc(8px + var(--safe-b)) 14px;background:#fff;border-top:1px solid var(--line)}
|
||
.bar .ip{flex:1;min-width:0;display:flex;align-items:center;gap:6px;height:38px;padding:0 6px 0 14px;border-radius:99px;background:#F5EEEA}
|
||
.bar .ip .ic{width:15px;height:15px;color:#B3A19B}
|
||
.bar input{flex:1;min-width:0;height:100%;border:0;background:none;outline:none;font:inherit;font-size:14px;color:var(--ink)}
|
||
.bar input::placeholder{color:#B3A19B}
|
||
.bar .send{flex:none;height:28px;padding:0 12px;border-radius:99px;background:var(--btn);color:#fff;font-size:13px;font-weight:800}
|
||
.bar .send:disabled{opacity:.4}
|
||
.bar .ib{flex:none;display:flex;align-items:center;gap:3px;height:38px;padding:0 6px;font-size:13px;color:#5E504C;font-variant-numeric:tabular-nums}
|
||
.bar .ib .ic{width:23px;height:23px}
|
||
.bar .ib.on.lv{color:#F0453A}
|
||
.bar .ib.on.fv{color:#F2A516}
|
||
.bar .ib.pop .ic{animation:pop .35s ease}
|
||
.bar.typing .ib{display:none}
|
||
.bar:not(.typing) .send{display:none}
|
||
|
||
.toast{position:fixed;left:50%;top:44%;z-index:80;max-width:280px;padding:10px 16px;border-radius:12px;background:rgba(40,30,28,.86);color:#fff;font-size:13.5px;line-height:1.6;text-align:center;transform:translate(-50%,8px);opacity:0;pointer-events:none;transition:opacity .2s,transform .2s}
|
||
.toast.show{opacity:1;transform:translate(-50%,0)}
|
||
</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-heart" viewBox="0 0 24 24"><path d="M12 20.3s-7.6-4.6-9.2-9.4C1.7 7.6 3.9 4.5 7.2 4.5c2 0 3.6 1.1 4.8 2.8 1.2-1.7 2.8-2.8 4.8-2.8 3.3 0 5.5 3.1 4.4 6.4-1.6 4.8-9.2 9.4-9.2 9.4z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></symbol>
|
||
<symbol id="i-heart-f" viewBox="0 0 24 24"><path d="M12 20.3s-7.6-4.6-9.2-9.4C1.7 7.6 3.9 4.5 7.2 4.5c2 0 3.6 1.1 4.8 2.8 1.2-1.7 2.8-2.8 4.8-2.8 3.3 0 5.5 3.1 4.4 6.4-1.6 4.8-9.2 9.4-9.2 9.4z" fill="currentColor"/></symbol>
|
||
<symbol id="i-star" viewBox="0 0 24 24"><path d="M12 3.6l2.6 5.3 5.8.8-4.2 4.1 1 5.8L12 16.9l-5.2 2.7 1-5.8-4.2-4.1 5.8-.8z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></symbol>
|
||
<symbol id="i-star-f" viewBox="0 0 24 24"><path d="M12 3.6l2.6 5.3 5.8.8-4.2 4.1 1 5.8L12 16.9l-5.2 2.7 1-5.8-4.2-4.1 5.8-.8z" fill="currentColor"/></symbol>
|
||
<symbol id="i-chat" viewBox="0 0 24 24"><path d="M4.5 18.8V7.6A3 3 0 017.5 4.6h9a3 3 0 013 3v6a3 3 0 01-3 3H8.8z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></symbol>
|
||
<symbol id="i-pen" viewBox="0 0 24 24"><path d="M4 20h4L19 9l-4-4L4 16z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
||
<symbol id="i-grid" viewBox="0 0 24 24"><path d="M4.5 4.5h6v6h-6zM13.5 4.5h6v6h-6zM4.5 13.5h6v6h-6zM13.5 13.5h6v6h-6z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
|
||
<symbol id="i-home" viewBox="0 0 24 24"><path d="M3.8 11.2L12 4.3l8.2 6.9M6.2 9.4v10h11.6v-10" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 17.6s-2.9-1.7-2.9-3.6c0-1 .8-1.7 1.6-1.7.6 0 1 .3 1.3.8.3-.5.7-.8 1.3-.8.8 0 1.6.7 1.6 1.7 0 1.9-2.9 3.6-2.9 3.6z" fill="currentColor"/></symbol>
|
||
<symbol id="i-bulb" viewBox="0 0 24 24"><path d="M9 17.5h6M9.8 20.5h4.4M12 3.5a6 6 0 00-3.6 10.8c.5.4.8 1 .8 1.6v1.6h5.6v-1.6c0-.6.3-1.2.8-1.6A6 6 0 0012 3.5z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
|
||
<symbol id="i-plus" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></symbol>
|
||
</svg>
|
||
|
||
<div id="sc">
|
||
<div 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>
|
||
<h1><span>孕妈广场</span></h1>
|
||
<span class="sp"></span>
|
||
</div>
|
||
<div class="cats" id="cats" role="tablist" aria-label="分类"></div>
|
||
<div class="tabs" id="tabs" role="tablist"></div>
|
||
</div>
|
||
<div id="head"></div>
|
||
<div class="wf" id="wf"><div class="col"></div><div class="col"></div></div>
|
||
<div class="end"><b>— 到底啦 —</b><small>内容为示例占位,正式版将替换为妈妈们的真实分享</small></div>
|
||
</div>
|
||
|
||
<div id="dt" aria-hidden="true">
|
||
<div class="dnav" id="dnav">
|
||
<button class="bk" id="dback" type="button" aria-label="返回"><svg class="ic"><use href="#i-back"/></svg></button>
|
||
<img id="dav" alt="">
|
||
<span class="who"><b id="dnm"></b><small id="dst"></small></span>
|
||
<button class="fo" id="dfo" type="button">关注</button>
|
||
</div>
|
||
<div id="dsc"></div>
|
||
<div class="bar" id="bar">
|
||
<label class="ip"><svg class="ic"><use href="#i-pen"/></svg><input id="cin" type="text" maxlength="200" placeholder="说点什么…" enterkeyhint="send"><button class="send" id="csend" type="button" disabled>发送</button></label>
|
||
<button class="ib lv" id="blk" type="button" aria-label="点赞"><svg class="ic"><use href="#i-heart"/></svg><span></span></button>
|
||
<button class="ib fv" id="bfv" type="button" aria-label="收藏"><svg class="ic"><use href="#i-star"/></svg><span></span></button>
|
||
<button class="ib" id="bcm" type="button" aria-label="评论"><svg class="ic"><use href="#i-chat"/></svg><span></span></button>
|
||
</div>
|
||
</div>
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<script src="topics.js?v=26110112"></script>
|
||
<script src="data.js?v=26110112"></script>
|
||
<script>
|
||
(function () {
|
||
'use strict';
|
||
var $ = function (s, c) { return (c || document).querySelector(s); };
|
||
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
|
||
var TBY = {}; T.forEach(function (t) { TBY[t.id] = t; });
|
||
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; }); };
|
||
var seed = function (t) { var x = 7; t = String(t); for (var i = 0; i < t.length; i++) x = (x * 31 + t.charCodeAt(i)) | 0; return Math.abs(x); };
|
||
var kfmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
|
||
/* 点赞 / 收藏 / 评论数:一万以内写实数,点一下能看见 +1 */
|
||
var cfmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : String(n); };
|
||
function rng(s) { var x = seed(s) || 1; return function () { x = (x * 1103515245 + 12345) & 0x7fffffff; return x / 0x7fffffff; }; }
|
||
|
||
/* ---------- 身份:同首页 hashParam,hash 优先、query 兜底 ---------- */
|
||
function param(name) {
|
||
try {
|
||
var h = (location.hash.slice(1) || '') + '&' + (location.search.slice(1) || '');
|
||
var m = h.match(new RegExp('(?:^|[&#])' + name + '=([^&#]*)'));
|
||
return m ? decodeURIComponent(m[1]).split('?')[0] : '';
|
||
} catch (e) { return ''; }
|
||
}
|
||
var OPENID = param('openid');
|
||
var MYNAME = param('nickname') || '孕妈'; /* 授权回填的昵称在 hash 里;没有就叫「孕妈」,后面另挂「我」标 */
|
||
|
||
/* ---------- 头像:沿用首页 assets/img/mom/ 写实头像 ---------- */
|
||
var AV = ['m01','m02','m03','m04','m05','m06','m07','m08','m09','m10','m11','m12','m13','m14','m15','m16','m17','m18','m19','m20','m21','m22',
|
||
'p01','p02','p03','p04','p05','p06','p07','p08','p09','p10','p11','p12','p13','p14','s01','s02','s03','s04','s05','s06','s07','s08','s09','s10',
|
||
'k01','k02','k03','k04','k05','k06','k07','k08','k09','k10','k11','k12','k13'];
|
||
var avSrc = function (key) { return '../assets/img/mom/' + AV[seed(key) % AV.length] + '.jpg'; };
|
||
|
||
/* ---------- 笔记:data.js 的原始内容 + 确定性补字段(id / 封面样式 / 比例 / 评论) ---------- */
|
||
var NOTES = [], NBY = {};
|
||
var RATIO = [1.25, 0.96, 1.16, 0.84, 1.32, 1.06, 0.92];
|
||
T.forEach(function (t, ti) {
|
||
var d = D[t.id]; if (!d) return;
|
||
(d.notes || []).forEach(function (n, i) {
|
||
var o = {
|
||
id: t.id + '-' + (i + 1), t: t.id, i: i, title: n.title, cover: n.cover || n.title, coverSub: n.coverSub || '',
|
||
author: n.author, stage: n.stage, likes: +n.likes || 0, body: n.body || '',
|
||
style: (ti * 2 + i * 5) % 6, ratio: RATIO[(ti + i * 3) % RATIO.length],
|
||
/* 封面配色:三条里一条用本话题色,另两条借别的话题色,同一话题页里不至于一片同色 */
|
||
pal: i % 3 === 0 ? t : T[(ti + 3 + i * 4) % T.length]
|
||
};
|
||
NOTES.push(o); NBY[o.id] = o;
|
||
});
|
||
});
|
||
/* 「全部」的混排:各话题轮流取一条(同一话题不扎堆),每轮按 id 哈希打散 */
|
||
var MIXED = (function () {
|
||
var out = [], byT = T.map(function (t) { return NOTES.filter(function (n) { return n.t === t.id; }); });
|
||
for (var r = 0; r < 10; r++) {
|
||
var round = [];
|
||
byT.forEach(function (l) { if (l[r]) round.push(l[r]); });
|
||
round.sort(function (a, b) { return seed(a.id + 'm') % 97 - seed(b.id + 'm') % 97; });
|
||
out = out.concat(round);
|
||
}
|
||
return out;
|
||
})();
|
||
var AGO = ['3 分钟前', '18 分钟前', '1 小时前', '2 小时前', '5 小时前', '昨天 21:40', '昨天 08:12', '10-29', '10-27', '10-25'];
|
||
function commentsOf(n) {
|
||
var pool = (D[n.t] && D[n.t].comments) || [], r = rng(n.id + 'c');
|
||
var idx = pool.map(function (_, k) { return k; });
|
||
for (var k = idx.length - 1; k > 0; k--) { var j = Math.floor(r() * (k + 1)); var x = idx[k]; idx[k] = idx[j]; idx[j] = x; }
|
||
var cnt = Math.min(pool.length, 3 + (seed(n.id) % 6));
|
||
return idx.slice(0, cnt).map(function (k, m) {
|
||
var c = pool[k];
|
||
return { key: n.id + '#' + k, n: c.n, s: c.s, t: c.t, likes: Math.floor(r() * 180) + 2, ago: AGO[Math.min(AGO.length - 1, m * 2 + Math.floor(r() * 2))],
|
||
r: (c.r || []).map(function (x, q) { return { n: x.n, t: x.t, au: q === 0 && r() < .35 }; }) };
|
||
});
|
||
}
|
||
|
||
/* ---------- 本机存储 mmbox.gc.v1:{ <openid|_guest>: { like:{}, fav:{}, cl:{}, cm:{id:[{t,ts}]} } } ---------- */
|
||
var SK = 'mmbox.gc.v1', UK = OPENID || '_guest';
|
||
function loadAll() { try { return JSON.parse(localStorage.getItem(SK) || '{}') || {}; } catch (e) { return {}; } }
|
||
var ALL = loadAll();
|
||
var ME = ALL[UK] || (ALL[UK] = {});
|
||
['like', 'fav', 'cl', 'cm', 'fo'].forEach(function (k) { if (!ME[k] || typeof ME[k] !== 'object') ME[k] = {}; });
|
||
function save() { try { ALL[UK] = ME; localStorage.setItem(SK, JSON.stringify(ALL)); } catch (e) {} }
|
||
var liked = function (id) { return !!ME.like[id]; };
|
||
var likeN = function (n) { return n.likes + (liked(n.id) ? 1 : 0); };
|
||
var favN = function (n) { return Math.round(n.likes * .38) + 3 + (ME.fav[n.id] ? 1 : 0); };
|
||
var myCm = function (id) { return ME.cm[id] || []; };
|
||
var cmN = function (n) { return commentsOf(n).length + myCm(n.id).length; };
|
||
|
||
function toast(msg) {
|
||
var t = $('#toast'); t.textContent = msg; t.classList.add('show');
|
||
clearTimeout(toast._t); toast._t = setTimeout(function () { t.classList.remove('show'); }, 1800);
|
||
}
|
||
function haptic() { if (navigator.vibrate) navigator.vibrate(8); }
|
||
|
||
/* ---------- 封面 ---------- */
|
||
function coverHTML(n, h) {
|
||
var t = TBY[n.t], pl = n.pal || t, st = 'style="--c1:' + pl.c[0] + ';--c2:' + pl.c[1] + ';--tk:' + pl.ink + ';' + (h ? 'height:' + h : '') + '"';
|
||
var t1 = esc(n.cover), t2 = esc(n.coverSub), inner;
|
||
switch (n.style) {
|
||
case 0: inner = '<i class="dc"></i><i class="dc2"></i><div class="t1"><span>' + t1 + '</span></div><div class="t2">' + t2 + '</div>'; break;
|
||
case 1: inner = '<div class="pp"><div class="t1">' + t1 + '</div><div class="t2">' + t2 + '</div></div>'; break;
|
||
case 2: inner = '<i class="q">“</i><div class="t1">' + t1 + '</div><div class="t2">' + t2 + '</div>'; break;
|
||
case 3: inner = '<div class="t1"><span>' + t1 + '</span></div><div class="t2">' + t2 + '</div><div class="ck"><i></i><i></i><i></i></div>'; break;
|
||
case 4: inner = '<i class="bc"><b>' + esc(t.g) + '</b></i><div class="t1">' + t1 + '</div><div class="t2">' + t2 + '</div>'; break;
|
||
default: inner = '<span class="st">' + (t.cat === 'family' ? '家有暖事' : '过来人经验') + '</span><div class="t1">' + t1 + '</div><div class="t2">' + t2 + '</div><i class="sm">' + esc(t.g) + '</i>';
|
||
}
|
||
return '<div class="cv s' + n.style + '" ' + st + '>' + inner + '</div>';
|
||
}
|
||
function likeHTML(n) {
|
||
var on = liked(n.id);
|
||
return '<span class="lk' + (on ? ' on' : '') + '" data-like="' + n.id + '" role="button" aria-label="点赞"><svg class="ic"><use href="#i-heart' + (on ? '-f' : '') + '"/></svg>' + cfmt(likeN(n)) + '</span>';
|
||
}
|
||
function cardHTML(n, showTopic) {
|
||
return '<button type="button" class="nc" data-id="' + n.id + '"><div class="cvw">' +
|
||
(showTopic ? '<span class="ttag k-' + TBY[n.t].cat + '"># ' + esc(TBY[n.t].name) + '</span>' : '') +
|
||
coverHTML(n, 'calc(var(--cw) * ' + n.ratio + ')') + '</div>' +
|
||
'<div class="nb"><h3>' + esc(n.title) + '</h3><div class="nf"><img src="' + avSrc(n.author) + '" alt="" loading="lazy"><span class="nm">' + esc(n.author) + '</span>' + likeHTML(n) + '</div></div></button>';
|
||
}
|
||
|
||
/* ---------- 列表 ---------- */
|
||
/* cur 当前话题('' = 不限话题);catF 一级分类('' 全部 / family 家庭关系 / exp 宝妈经验)。选了话题时 catF 恒等于该话题的 cat */
|
||
var cur = '', catF = '';
|
||
var CATS = [['', '全部', 'i-grid'], ['family', '家庭关系', 'i-home'], ['exp', '宝妈经验', 'i-bulb']];
|
||
var CAT_NAME = { family: '家庭关系', exp: '宝妈经验' };
|
||
var inCat = function (t) { return !catF || t.cat === catF; };
|
||
function renderCats() {
|
||
$('#cats').innerHTML = CATS.map(function (x) {
|
||
return '<button type="button" role="tab" data-c="' + x[0] + '" class="c-' + (x[0] || 'all') + (catF === x[0] ? ' on' : '') + '" aria-selected="' + (catF === x[0]) + '">' +
|
||
'<span class="ci2"><svg class="ic"><use href="#' + x[2] + '"/></svg></span>' + x[1] + '</button>';
|
||
}).join('');
|
||
}
|
||
function renderTabs() {
|
||
$('#tabs').className = 'tabs' + (catF ? ' k-' + catF : '');
|
||
var h = '<button type="button" data-t="" class="' + (cur ? '' : 'on') + '">' + (catF ? '全部' + CAT_NAME[catF] : '全部话题') + '</button>' + T.filter(inCat).map(function (t) {
|
||
return '<button type="button" data-t="' + t.id + '" class="' + (cur === t.id ? 'on' : '') + '">' + esc(t.name) + (t.hot ? '<i class="hb">热</i>' : '') + '</button>';
|
||
}).join('');
|
||
$('#tabs').innerHTML = h;
|
||
}
|
||
function renderHead() {
|
||
var t = TBY[cur], el = $('#head');
|
||
if (!t) {
|
||
var tip = catF === 'family' ? '老公、婆婆、爸妈,家里那些暖事和糟心事' : catF === 'exp' ? '过来人的干货,少走弯路' : '都是孕妈们的真心话';
|
||
el.innerHTML = '<div class="intro"><span><b>' + T.filter(inCat).length + '</b> 个话题 · ' + tip + '</span></div>';
|
||
return;
|
||
}
|
||
var d = D[t.id] || {};
|
||
var avs = [0, 1, 2, 3].map(function (k) { return '<img src="' + avSrc(t.id + k) + '" alt="">'; }).join('');
|
||
el.innerHTML = '<div class="th" style="--c1:' + t.c[0] + ';--c2:' + t.c[1] + ';--tk:' + t.ink + '"><span class="tg" aria-hidden="true">' + esc(t.g) + '</span>' +
|
||
'<span class="tc k-' + t.cat + '">' + (t.cat === 'family' ? '家庭关系' : '宝妈经验') + (t.hot ? ' · 热门' : '') + '</span>' +
|
||
'<h2><em>#</em>' + esc(t.name) + '</h2><p>' + esc(d.desc || '') + '</p>' +
|
||
'<div class="tf"><span class="ts"><span class="avs">' + avs + '</span><span><b>' + kfmt(t.n) + '</b> 篇笔记 · <b>' + kfmt(t.talk) + '</b> 人在聊</span></span>' +
|
||
'<button type="button" class="join" id="join"><svg class="ic"><use href="#i-plus"/></svg>参与话题</button></div></div>';
|
||
}
|
||
function renderFeed() {
|
||
var list = cur ? NOTES.filter(function (n) { return n.t === cur; }) : MIXED.filter(function (n) { return inCat(TBY[n.t]); });
|
||
var wf = $('#wf'), cols = wf.children;
|
||
cols[0].innerHTML = ''; cols[1].innerHTML = '';
|
||
var cw = cols[0].clientWidth || 175;
|
||
wf.style.setProperty('--cw', cw + 'px');
|
||
/* 真瀑布流:每张卡放进当前更矮的那一列(逐张量高,标题一行/两行也算进去) */
|
||
var hs = [0, 0], tmp = document.createElement('div');
|
||
list.forEach(function (n, k) {
|
||
tmp.innerHTML = cardHTML(n, !cur);
|
||
var el = tmp.firstChild; el.style.animationDelay = Math.min(k, 10) * 30 + 'ms';
|
||
var c = hs[0] <= hs[1] ? 0 : 1;
|
||
cols[c].appendChild(el);
|
||
hs[c] += el.offsetHeight + 8;
|
||
});
|
||
}
|
||
function setQuery(t, n) {
|
||
var q = new URLSearchParams(location.search);
|
||
if (t) q.set('t', t); else q.delete('t');
|
||
if (!t && catF) q.set('c', catF); else q.delete('c'); /* 只选了分类没选话题时记在 ?c=,刷新 / 详情返回还在原分类 */
|
||
if (n) q.set('n', n); else q.delete('n');
|
||
var s = q.toString();
|
||
return location.pathname + (s ? '?' + s : '') + location.hash; /* hash(身份)原样保留 */
|
||
}
|
||
function selectTopic(t, smooth) {
|
||
if (!TBY[t]) t = '';
|
||
cur = t;
|
||
if (t) catF = TBY[t].cat; /* 首页带 ?t= 进来 / 点详情里的话题标签:分类跟着切到该话题所属类 */
|
||
renderCats(); renderTabs(); renderHead(); renderFeed();
|
||
history.replaceState(history.state, '', setQuery(cur, ''));
|
||
var on = $('#tabs .on');
|
||
if (on) { var tb = $('#tabs'); tb.scrollLeft = Math.max(0, on.offsetLeft - tb.clientWidth / 2 + on.offsetWidth / 2); }
|
||
var sc = $('#sc'); if (smooth !== false) sc.scrollTop = 0;
|
||
}
|
||
$('#tabs').addEventListener('click', function (e) {
|
||
var b = e.target.closest('button[data-t]');
|
||
if (b && b.dataset.t !== cur) { haptic(); selectTopic(b.dataset.t); }
|
||
});
|
||
$('#cats').addEventListener('click', function (e) {
|
||
var b = e.target.closest('button[data-c]');
|
||
if (!b || (b.dataset.c === catF && !cur)) return;
|
||
catF = b.dataset.c; haptic();
|
||
selectTopic(''); /* 换分类回到该类「全部」,避免停在别类话题上 */
|
||
});
|
||
$('#head').addEventListener('click', function (e) {
|
||
if (e.target.closest('#join')) toast('发布笔记马上开放,先去看看大家怎么说吧');
|
||
});
|
||
|
||
/* 卡片:点心形就地点赞,点别处进详情 */
|
||
function toggleLike(id) {
|
||
if (ME.like[id]) delete ME.like[id]; else ME.like[id] = 1;
|
||
save(); haptic();
|
||
}
|
||
function syncCardLike(id) {
|
||
var n = NBY[id];
|
||
document.querySelectorAll('.lk[data-like="' + id + '"]').forEach(function (el) {
|
||
var on = liked(id);
|
||
el.classList.toggle('on', on);
|
||
el.innerHTML = '<svg class="ic"><use href="#i-heart' + (on ? '-f' : '') + '"/></svg>' + cfmt(likeN(n));
|
||
if (on) { el.classList.remove('pop'); void el.offsetWidth; el.classList.add('pop'); }
|
||
});
|
||
}
|
||
$('#wf').addEventListener('click', function (e) {
|
||
var lk = e.target.closest('[data-like]');
|
||
if (lk) { e.stopPropagation(); toggleLike(lk.dataset.like); syncCardLike(lk.dataset.like); return; }
|
||
var c = e.target.closest('.nc');
|
||
if (c) openNote(c.dataset.id, true);
|
||
});
|
||
|
||
/* ---------- 详情 ---------- */
|
||
var openId = '', pushed = false;
|
||
/* 正文按 \n 分段;「1. 」「2、」开头的行当清单项:悬挂缩进、条间距更紧 */
|
||
function bodyHTML(s) {
|
||
return String(s).split(/\n+/).map(function (p) { return p.trim(); }).filter(Boolean).map(function (p) {
|
||
return /^\d{1,2}[.、.]\s*/.test(p) ? '<p class="li">' + esc(p) + '</p>' : '<p>' + esc(p) + '</p>';
|
||
}).join('');
|
||
}
|
||
function commentHTML(c, mine) {
|
||
if (mine) {
|
||
return '<div class="ci mine"><span class="me">我</span><div class="ci-b"><div class="ci-n"><b>' + esc(MYNAME) + '</b><span class="mt">我</span></div>' +
|
||
'<p class="ci-t">' + esc(c.t) + '</p><div class="ci-s">' + agoOf(c.ts) + '</div></div></div>';
|
||
}
|
||
var on = !!ME.cl[c.key], n = c.likes + (on ? 1 : 0);
|
||
var rp = c.r.length ? '<div class="rp">' + c.r.map(function (x) { return '<p><b>' + esc(x.n) + '</b>' + (x.au ? '<span class="au">作者</span>' : '') + ':' + esc(x.t) + '</p>'; }).join('') + '</div>' : '';
|
||
return '<div class="ci"><img src="' + avSrc(c.n) + '" alt="" loading="lazy"><div class="ci-b"><div class="ci-n"><b>' + esc(c.n) + '</b>' +
|
||
'<span class="lk' + (on ? ' on' : '') + '" data-cl="' + esc(c.key) + '" data-base="' + c.likes + '" role="button"><svg class="ic"><use href="#i-heart' + (on ? '-f' : '') + '"/></svg>' + n + '</span></div>' +
|
||
'<p class="ci-t">' + esc(c.t) + '</p><div class="ci-s">' + esc(c.s || '') + ' · ' + c.ago + '</div>' + rp + '</div></div>';
|
||
}
|
||
function agoOf(ts) {
|
||
var s = Math.max(0, (Date.now() - ts) / 1000);
|
||
if (s < 60) return '刚刚';
|
||
if (s < 3600) return Math.floor(s / 60) + ' 分钟前';
|
||
if (s < 86400) return Math.floor(s / 3600) + ' 小时前';
|
||
var d = new Date(ts); return (d.getMonth() + 1) + '-' + d.getDate();
|
||
}
|
||
function renderComments(n) {
|
||
var mine = myCm(n.id).slice().reverse(), cs = commentsOf(n);
|
||
$('#cmh').innerHTML = '评论 <small>共 ' + cmN(n) + ' 条</small>';
|
||
$('#cml').innerHTML = mine.map(function (c) { return commentHTML(c, true); }).join('') + cs.map(function (c) { return commentHTML(c); }).join('');
|
||
}
|
||
function syncBar(n, popK) {
|
||
var lv = $('#blk'), fv = $('#bfv'), on = liked(n.id), fo = !!ME.fav[n.id];
|
||
lv.classList.toggle('on', on); lv.querySelector('use').setAttribute('href', on ? '#i-heart-f' : '#i-heart'); lv.querySelector('span').textContent = cfmt(likeN(n));
|
||
fv.classList.toggle('on', fo); fv.querySelector('use').setAttribute('href', fo ? '#i-star-f' : '#i-star'); fv.querySelector('span').textContent = cfmt(favN(n));
|
||
$('#bcm span').textContent = cfmt(cmN(n));
|
||
if (popK) { var b = popK === 'lv' ? lv : fv; b.classList.remove('pop'); void b.offsetWidth; b.classList.add('pop'); }
|
||
}
|
||
function openNote(id, push) {
|
||
var n = NBY[id]; if (!n) return;
|
||
var t = TBY[n.t];
|
||
openId = id;
|
||
$('#dav').src = avSrc(n.author);
|
||
$('#dnm').textContent = n.author;
|
||
$('#dst').textContent = n.stage || '';
|
||
var fo = $('#dfo'); fo.classList.toggle('on', !!ME.fo[n.author]); fo.textContent = ME.fo[n.author] ? '已关注' : '关注';
|
||
var h = Math.round(window.innerWidth * Math.min(n.ratio, 1.05));
|
||
var day = 26 + (seed(n.id) % 6), mon = day > 31 ? 11 : 10;
|
||
$('#dsc').innerHTML = '<div class="dcv">' + coverHTML(n, h + 'px') + '</div>' +
|
||
'<div class="dbody"><h2>' + esc(n.title) + '</h2><div class="tx">' + bodyHTML(n.body) + '</div>' +
|
||
'<div class="tgs"><button type="button" data-go="' + t.id + '"># ' + esc(t.name) + '</button><button type="button" data-go="">#孕妈广场</button></div>' +
|
||
'<div class="tm">' + mon + '-' + (day > 31 ? day - 31 : day) + ' · ' + esc(n.stage || '') + '</div></div>' +
|
||
'<div class="cm" id="cmw"><div class="cm-h" id="cmh"></div>' +
|
||
'<div class="cm-in"><span class="me">我</span><button type="button" id="cmgo">留下你的温柔一句…</button></div>' +
|
||
'<div id="cml"></div><div class="cm-end">— 没有更多评论了 —</div></div>';
|
||
renderComments(n); syncBar(n);
|
||
$('#cin').value = ''; $('#bar').classList.remove('typing'); $('#csend').disabled = true;
|
||
$('#dsc').scrollTop = 0; $('#dnav').classList.remove('on');
|
||
var dt = $('#dt'); dt.classList.add('show'); dt.setAttribute('aria-hidden', 'false');
|
||
if (push) { history.pushState({ gcNote: id }, '', setQuery(cur, id)); pushed = true; }
|
||
else history.replaceState(history.state, '', setQuery(cur, id));
|
||
}
|
||
function hideNote() {
|
||
var dt = $('#dt'); dt.classList.remove('show'); dt.setAttribute('aria-hidden', 'true');
|
||
$('#cin').blur();
|
||
var id = openId; openId = '';
|
||
if (id) syncCardLike(id);
|
||
}
|
||
function closeNote() {
|
||
if (!openId) return;
|
||
if (pushed) { history.back(); return; } /* popstate 里 hideNote */
|
||
hideNote(); history.replaceState(history.state, '', setQuery(cur, ''));
|
||
}
|
||
window.addEventListener('popstate', function () {
|
||
pushed = false;
|
||
if (openId) hideNote();
|
||
});
|
||
$('#dback').addEventListener('click', closeNote);
|
||
$('#dfo').addEventListener('click', function () {
|
||
var n = NBY[openId]; if (!n) return;
|
||
if (ME.fo[n.author]) delete ME.fo[n.author]; else ME.fo[n.author] = 1;
|
||
save(); haptic();
|
||
this.classList.toggle('on', !!ME.fo[n.author]); this.textContent = ME.fo[n.author] ? '已关注' : '关注';
|
||
});
|
||
$('#dsc').addEventListener('scroll', function () { $('#dnav').classList.toggle('on', this.scrollTop > 8); }, { passive: true });
|
||
$('#dsc').addEventListener('click', function (e) {
|
||
var g = e.target.closest('[data-go]');
|
||
if (g) { var to = g.dataset.go; closeNote(); setTimeout(function () { if (!to) catF = ''; selectTopic(to); }, 60); return; }
|
||
var cl = e.target.closest('[data-cl]');
|
||
if (cl) {
|
||
var k = cl.dataset.cl, on;
|
||
if (ME.cl[k]) delete ME.cl[k]; else ME.cl[k] = 1;
|
||
save(); haptic(); on = !!ME.cl[k];
|
||
cl.classList.toggle('on', on);
|
||
cl.innerHTML = '<svg class="ic"><use href="#i-heart' + (on ? '-f' : '') + '"/></svg>' + (+cl.dataset.base + (on ? 1 : 0));
|
||
if (on) { cl.classList.remove('pop'); void cl.offsetWidth; cl.classList.add('pop'); }
|
||
return;
|
||
}
|
||
if (e.target.closest('#cmgo')) $('#cin').focus();
|
||
});
|
||
$('#blk').addEventListener('click', function () {
|
||
var n = NBY[openId]; if (!n) return;
|
||
toggleLike(n.id); syncBar(n, liked(n.id) ? 'lv' : '');
|
||
});
|
||
$('#bfv').addEventListener('click', function () {
|
||
var n = NBY[openId]; if (!n) return;
|
||
if (ME.fav[n.id]) delete ME.fav[n.id]; else ME.fav[n.id] = 1;
|
||
save(); haptic(); syncBar(n, ME.fav[n.id] ? 'fv' : '');
|
||
toast(ME.fav[n.id] ? '已收藏,在这台手机上随时能找到' : '已取消收藏');
|
||
});
|
||
$('#bcm').addEventListener('click', function () {
|
||
var w = $('#cmw'); if (w) $('#dsc').scrollTo({ top: w.offsetTop - 50, behavior: 'smooth' });
|
||
});
|
||
var cin = $('#cin');
|
||
cin.addEventListener('focus', function () { $('#bar').classList.add('typing'); });
|
||
cin.addEventListener('blur', function () { setTimeout(function () { if (!cin.value.trim()) $('#bar').classList.remove('typing'); }, 120); });
|
||
cin.addEventListener('input', function () { $('#csend').disabled = !cin.value.trim(); });
|
||
cin.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); send(); } });
|
||
$('#csend').addEventListener('click', send);
|
||
function send() {
|
||
var n = NBY[openId], v = cin.value.trim();
|
||
if (!n || !v) return;
|
||
(ME.cm[n.id] = myCm(n.id)).push({ t: v.slice(0, 200), ts: Date.now() });
|
||
save(); haptic();
|
||
cin.value = ''; $('#csend').disabled = true; cin.blur(); $('#bar').classList.remove('typing');
|
||
renderComments(n); syncBar(n);
|
||
var w = $('#cmw'); if (w) $('#dsc').scrollTo({ top: w.offsetTop - 50, behavior: 'smooth' });
|
||
toast('评论已发出');
|
||
}
|
||
|
||
/* ---------- 返回 ---------- */
|
||
function homeURL() {
|
||
var q = new URLSearchParams(location.search); q.delete('t'); q.delete('n'); q.delete('c');
|
||
var s = q.toString();
|
||
return '../' + (s ? '?' + s : '') + location.hash;
|
||
}
|
||
$('#back').addEventListener('click', function () {
|
||
var fromHome = false;
|
||
try { fromHome = !!document.referrer && new URL(document.referrer).origin === location.origin; } catch (e) {}
|
||
if (fromHome && history.length > 1) {
|
||
history.back();
|
||
/* 后退没生效(宿主新开的 web-view 没有站内历史)→ 直接回首页 */
|
||
setTimeout(function () { location.href = homeURL(); }, 500);
|
||
} else location.href = homeURL();
|
||
});
|
||
|
||
/* ---------- 吸顶阴影 ---------- */
|
||
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 });
|
||
|
||
/* ---------- 启动 ---------- */
|
||
var deep = new URLSearchParams(location.search).get('n'); /* 先读:selectTopic 会 replaceState 把 n 去掉 */
|
||
var c0 = new URLSearchParams(location.search).get('c');
|
||
if (c0 === 'family' || c0 === 'exp') catF = c0;
|
||
selectTopic(param('t') && TBY[param('t')] ? param('t') : '', false);
|
||
if (deep && NBY[deep]) openNote(deep, false);
|
||
var rt; window.addEventListener('resize', function () { clearTimeout(rt); rt = setTimeout(renderFeed, 150); });
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|