Files
mama-box/guangchang/index.html
2026-11-02 10:16:42 +00:00

1182 lines
88 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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-02 第四版:用户「去掉图标、滑块缺设计感」→ 小红书式文字标签:选中字放大加粗 + 底下一条会滑动的分类色胶囊;左右滑页面也能切) ---------- */
.cats{position:relative;display:flex;gap:8px;margin:0 6px;padding:2px 0 10px}
.cats button{position:relative;z-index:1;flex:none;padding:6px 12px 4px;font-size:15.5px;font-weight:700;color:#A08B85;letter-spacing:.3px;line-height:24px;transition:color .25s}
.cats button .ic{display:none}
.cats button.on{font-size:18px;font-weight:900;color:#2A1E1E}
.cats button i{position:absolute;left:calc(100% - 12px);top:2px;font-style:normal;font-size:10px;font-weight:800;line-height:12px;color:var(--cf);opacity:0;transition:opacity .25s}
.cats button.on i{opacity:1}
.cats .bar{position:absolute;z-index:0;left:0;bottom:12px;height:7px;width:28px;border-radius:7px;background:var(--cbar,#F4593C);opacity:.32;
transition:transform .32s cubic-bezier(.3,1.3,.5,1),width .32s cubic-bezier(.3,1.3,.5,1),background .25s;pointer-events:none}
.cats::after{content:"";position:absolute;left:6px;right:6px;bottom:0;height:1px;background:linear-gradient(90deg,transparent,#EADAD3 20%,#EADAD3 80%,transparent)}
.cats button:active{transform:scale(.96)}
.wf.swl{animation:swl .32s ease-out}.wf.swr{animation:swr .32s ease-out}
@keyframes swl{from{opacity:.2;transform:translateX(36px)}to{opacity:1;transform:none}}
@keyframes swr{from{opacity:.2;transform:translateX(-36px)}to{opacity:1;transform:none}}
.cats .c-all{--cf:#F4593C}
/* 四块分类色(11-01 第四版:按用户选题清单分 家庭 / 婚姻 / 职场 / 母婴):kf 实色 · kt 深字 · kl/kl2 浅底两色 */
.k-family,.c-family{--kf:#E0566F;--kt:#C23A55;--kl:#FFF0F3;--kl2:#FFD9E0}
.k-marriage,.c-marriage{--kf:#7B5CC4;--kt:#6346B0;--kl:#F4F0FF;--kl2:#E0D5FA}
.k-work,.c-work{--kf:#3A72B8;--kt:#2C5E9E;--kl:#EEF4FC;--kl2:#D2E2F6}
.k-baby,.c-baby{--kf:#2E8A7C;--kt:#21705F;--kl:#EBF7F3;--kl2:#CDEBE3}
.cats .c-family,.cats .c-marriage,.cats .c-work,.cats .c-baby{--cf:var(--kf)}
/* ---------- 投稿有奖横幅 ---------- */
.rw{position:relative;display:flex;align-items:center;gap:12px;margin:2px 12px 0;padding:13px 14px;border-radius:18px;overflow:hidden;width:calc(100% - 24px);text-align:left;
background:radial-gradient(120px 90px at 100% 0,rgba(255,255,255,.35),transparent 70%),linear-gradient(120deg,#FF8A5B,#F4593C 60%,#E8473A);color:#fff;box-shadow:0 10px 22px -12px #E8473A}
.rw .gf{width:42px;height:42px;flex:none;display:grid;place-items:center;border-radius:14px;background:rgba(255,255,255,.22)}
.rw .gf .ic{width:24px;height:24px}
.rw .rt{flex:1;min-width:0}
.rw .rt small{display:block;font-size:12px;font-weight:700;opacity:.9;letter-spacing:.5px}
.rw .rt b{display:block;margin-top:1px;font-size:17px;font-weight:900;letter-spacing:.3px;white-space:nowrap}
.rw .rt b em{font-style:normal;font-size:20px;color:#FFF3B8}
.rw .go{flex:none;height:30px;padding:0 11px;border-radius:99px;background:#fff;color:#E8473A;font-size:12.5px;font-weight:800;display:inline-flex;align-items:center}
.rw.sm{margin-top:12px;padding:10px 12px}
.rw.sm .gf{width:34px;height:34px;border-radius:11px}
.rw.sm .gf .ic{width:19px;height:19px}
.rw.sm .rt b{font-size:14.5px}
.rw.sm .rt b em{font-size:16px}
/* ---------- 区块标题 ---------- */
.sh{display:flex;align-items:center;gap:6px;margin:18px 14px 8px}
.sh h2{margin:0;font-size:17px;font-weight:900;letter-spacing:.3px}
.sh .fire{width:18px;height:18px;color:#FF5A3C}
.sh small{font-size:12px;font-weight:600;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.sh .more{margin-left:auto;font-size:12.5px;font-weight:700;color:var(--muted);display:inline-flex;align-items:center}
/* ---------- 热门话题:横滑卡 ---------- */
.hot{display:flex;gap:10px;padding:0 12px 2px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scroll-snap-type:x mandatory}
.hot::-webkit-scrollbar{display:none}
.hot::after{content:"";flex:none;width:2px}
.htl{margin:0 12px;padding:4px 12px 2px;border-radius:18px;background:#fff;box-shadow:0 6px 18px -12px rgba(120,60,40,.25)}
.htl .hr{display:flex;align-items:center;gap:10px;padding:11px 0;border-bottom:1px dashed #F0E2DC;--hk:var(--kf)}
.htl .hr:last-of-type{border-bottom:0}
.htl .no{flex:none;width:20px;text-align:center;font-style:italic;font-size:16px;font-weight:900;color:#C9B3AC}
.htl .no.t0{color:#F2465A}.htl .no.t1{color:#FF6A3D}.htl .no.t2{color:#FF9A2E}
.htl .hm{flex:1;min-width:0}
.htl .hm b{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:14.5px;font-weight:900;line-height:1.4;color:#2A1E1E}
.htl .hm em{font-style:normal;color:var(--hk);margin:0 1px}
.htl .hm small{display:block;margin-top:2px;font-size:11.5px;color:#A8918B;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.htl .hm u{text-decoration:none;color:var(--hk);font-weight:700;margin-right:6px}
.htl .rk{flex:none;height:17px;padding:0 5px;border-radius:5px;background:#FF5A3C;color:#fff;font-size:10.5px;font-weight:800;line-height:17px}
.htl .jn{flex:none;height:26px;padding:0 11px;border-radius:99px;border:1px solid var(--hk);color:var(--hk);background:#fff;font-size:12px;font-weight:800}
.htl .hall{display:block;width:100%;padding:10px 0 9px;border-top:1px solid #F5EAE6;font-size:12.5px;font-weight:700;color:#9A817C}
.hc{flex:none;width:168px;scroll-snap-align:start;display:flex;flex-direction:column;padding:12px 12px 11px;border-radius:18px;text-align:left;background:var(--hb);position:relative;overflow:hidden}
.hc{--hb:linear-gradient(160deg,var(--kl),var(--kl2));--hk:var(--kf);--ht:var(--kt)}
.hc .wm{position:absolute;right:-4px;bottom:-14px;font-size:72px;font-weight:900;line-height:1;color:#fff;opacity:.7;font-family:"STKaiti","KaiTi","Kaiti SC",serif;pointer-events:none}
.hc .kb{align-self:flex-start;position:relative}
.hc .rk{position:absolute;right:10px;top:10px;height:18px;padding:0 6px;border-radius:6px;background:#FF5A3C;color:#fff;font-size:10.5px;font-weight:800;line-height:18px}
.hc h3{position:relative;margin:8px 0 0;font-size:15px;font-weight:900;line-height:1.35;color:#2A1E1E}
.hc p{position:relative;margin:4px 0 0;font-size:11.5px;line-height:1.5;color:#7A6663;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:34px}
.hc .jn{position:relative;align-self:flex-start;margin-top:10px;height:28px;padding:0 12px;border-radius:99px;background:var(--hk);color:#fff;font-size:12.5px;font-weight:800;display:inline-flex;align-items:center;gap:3px}
.hc .jn .ic{width:13px;height:13px}
/* 分类小徽标:家庭 / 经验(封面、热门卡、话题头、详情共用) */
.kb{display:inline-flex;align-items:center;gap:3px;height:20px;padding:0 7px 0 5px;border-radius:7px;font-size:11px;font-weight:800;letter-spacing:.5px;color:#fff;white-space:nowrap}
.kb .ic{width:12px;height:12px}
.kb{background:var(--kf)}
/* ---------- 话题头卡(选了具体话题时) ---------- */
.th{position:relative;margin:2px 12px 0;padding:14px 16px 14px;border-radius:20px;overflow:hidden;background:var(--hb);box-shadow:0 10px 24px -18px var(--hk)}
.th{--hb:linear-gradient(150deg,var(--kl),var(--kl2));--hk:var(--kf);--ht:var(--kt)}
.th .wm{position:absolute;right:-4px;top:-8px;font-size:104px;font-weight:900;line-height:1;color:#fff;opacity:.6;font-family:"STKaiti","KaiTi","Kaiti SC",serif;pointer-events:none}
.th .x{position:absolute;right:8px;top:8px;width:30px;height:30px;display:grid;place-items:center;border-radius:50%;background:rgba(255,255,255,.7);color:#7A6663}
.th .x .ic{width:14px;height:14px}
.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(--ht);margin-right:2px}
.th p{position:relative;margin:0;max-width:280px;font-size:12.5px;line-height:1.6;color:#5E4E4A}
.th .tf{position:relative;display:flex;gap:8px;margin-top:12px}
.th .join{height:34px;padding:0 16px;border-radius:99px;background:var(--hk);color:#fff;font-size:13.5px;font-weight:800;display:inline-flex;align-items:center;gap:4px;box-shadow:0 6px 12px -6px var(--hk)}
.th .join .ic{width:14px;height:14px}
.th .sw{height:34px;padding:0 14px;border-radius:99px;background:rgba(255,255,255,.8);color:var(--ht);font-size:13px;font-weight:800}
/* ---------- 层级:分类 · 话题胶囊(11-02) ---------- */
.lvw{margin:16px 0 0}
.lvw .lv{display:flex;align-items:baseline;gap:8px;padding:0 14px}
.lvw .lv h2{margin:0;font-size:17px;font-weight:900;letter-spacing:.3px;color:var(--kt)}
.lvw .lv small{font-size:12px;font-weight:600;color:var(--muted);white-space:nowrap}
.lvw .lv .ba{margin-left:auto;font-size:12.5px;font-weight:800;color:var(--kt)}
.tcs{display:flex;gap:7px;padding:9px 12px 2px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:none}
.tcs::-webkit-scrollbar{display:none}
.tcs::after{content:"";flex:none;width:4px}
.tcs button{flex:none;height:30px;padding:0 11px;border-radius:99px;background:#fff;border:1px solid #EFE1DB;font-size:12.5px;font-weight:700;color:#5E4E4A;white-space:nowrap;display:inline-flex;align-items:center;gap:5px}
.tcs button i{font-style:normal;font-size:11px;font-weight:800;color:#B59A93;font-variant-numeric:tabular-nums}
.tcs button.on{background:var(--kf);border-color:var(--kf);color:#fff;box-shadow:0 5px 12px -6px var(--kf)}
.tcs button.on i{color:rgba(255,255,255,.85)}
.th .bc{position:relative;display:flex;align-items:center;gap:6px}
.th .bc button{display:inline-flex}
.th .bc span:last-child{font-size:12px;font-weight:700;color:var(--ht)}
.mo{display:block;width:calc(100% - 24px);margin:14px 12px 0;padding:13px 14px;border-radius:16px;text-align:center;background:linear-gradient(150deg,var(--kl),var(--kl2))}
.mo small{display:block;font-size:11.5px;font-weight:600;color:#9A817C}
.mo b{display:block;margin-top:3px;font-size:14.5px;font-weight:900;color:var(--kt)}
/* ---------- 瀑布流 ---------- */
.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 .tp{display:block;margin-top:4px;font-size:11.5px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nc .tp{color:var(--kt)}
.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,详情放大)
11-01 第三版:用户说列表「太乱」→ 原来 6 种花样(方格纸/横线本/波点胶带/深色引号…)全部去掉,只留一种版式;
颜色只按分类走:家庭 = 粉、经验 = 青绿,各 3 个深浅轮换。左上角实底「家庭 / 经验」徽标,一眼分清。 ---------- */
.cv{position:relative;width:100%;overflow:hidden;font-size:13px;isolation:isolate;display:flex;flex-direction:column;padding:.95em 1.05em 1.1em;background:linear-gradient(160deg,var(--c1),var(--c2))}
.cv .kb{align-self:flex-start;font-size:.85em;height:1.55em;padding:0 .55em 0 .4em;border-radius:.5em;gap:.2em}
.cv .kb .ic{width:1em;height:1em}
.cv .ct{flex:1;display:flex;flex-direction:column;justify-content:center;position:relative;z-index:1}
.cv .t1{font-size:1.65em;font-weight:900;line-height:1.25;letter-spacing:.04em;color:#2A1E1E;word-break:break-all}
.cv .t2{margin-top:.5em;font-size:.92em;font-weight:700;line-height:1.4;color:var(--tk)}
/* 照片封面(11-01 用户:广场图片要有一些像真实上传的照片,不要全是文字封面):约三分之一笔记用照片,满铺裁切,左上角仍挂分类徽标 */
.cv.ph{padding:0;background:#EFE6E1}
.cv.ph img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}
.cv.ph .kb{position:absolute;left:.95em;top:.95em;z-index:1;box-shadow:0 2px 6px rgba(0,0,0,.12)}
.cv .wm{position:absolute;right:-.1em;bottom:-.25em;font-size:5.6em;font-weight:900;line-height:1;color:#fff;opacity:.55;font-family:"STKaiti","KaiTi","Kaiti SC",serif;pointer-events:none;z-index:0}
/* 图上压字(11-02 用户:文字放到图片上穿插来,小红书式):ov 底部渐变大字 / tg 贴纸字 */
.nc .ovt{position:absolute;left:0;right:0;bottom:0;padding:34px 10px 10px;background:linear-gradient(transparent,rgba(30,18,14,.62));color:#fff;pointer-events:none}
.nc .ovt b{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;font-size:17px;font-weight:900;line-height:1.3;letter-spacing:.5px;text-shadow:0 1px 4px rgba(0,0,0,.25)}
.nc .ovt small{display:block;margin-top:4px;font-size:11px;font-weight:700;opacity:.9;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nc .tgt{position:absolute;left:9px;right:9px;bottom:12px;pointer-events:none}
.nc .tgt b{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;font-size:15px;font-weight:900;line-height:1.55;color:#2A1E1E}
.nc .tgt span{background:#FFF2A6;padding:1px 5px;-webkit-box-decoration-break:clone;box-decoration-break:clone;border-radius:3px}
.nc:nth-child(odd) .tgt span{background:#fff}
.nc .ovt~*,.nc .tgt~*{display:none}
/* ---------- 详情层 ---------- */
#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:24px}
.dcv .cv .kb{display:none}
.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 .dk{display:flex;align-items:center;gap:6px;margin-bottom:8px}
.dbody .dk button{height:22px;padding:0 8px;border-radius:7px;font-size:12px;font-weight:800}
.dbody .dk button{background:var(--kl);color:var(--kt)}
.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}
/* 详情正文后:参与本话题 */
.pj{display:flex;align-items:center;gap:12px;margin:14px 18px 4px;padding:13px 14px;border-radius:16px;background:var(--hb)}
.pj{--hb:linear-gradient(140deg,var(--kl),var(--kl2));--hk:var(--kf);--ht:var(--kt)}
.pj .pt{flex:1;min-width:0}
.pj .pt b{display:block;font-size:14.5px;font-weight:900;color:#2A1E1E}
.pj .pt small{display:block;margin-top:2px;font-size:12px;color:#6E5C57}
.pj .pt small em{font-style:normal;font-weight:800;color:#E8473A}
.pj button{flex:none;height:32px;padding:0 13px;border-radius:99px;background:var(--hk);color:#fff;font-size:13px;font-weight:800}
/* ---------- 底部弹层:投稿规则 / 全部话题 ---------- */
#mask{position:fixed;inset:0;z-index:60;background:rgba(30,20,18,.45);opacity:0;pointer-events:none;transition:opacity .22s}
#mask.show{opacity:1;pointer-events:auto}
#sheet{position:fixed;left:0;right:0;bottom:0;z-index:61;max-height:82vh;display:flex;flex-direction:column;border-radius:22px 22px 0 0;background:#FFFBF8;transform:translateY(105%);transition:transform .28s cubic-bezier(.2,.8,.2,1)}
#sheet.show{transform:none}
#sheet .sg{width:36px;height:4px;margin:8px auto 0;border-radius:4px;background:#E6D8D2;flex:none}
#sheet .sbd{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:none;padding:6px 18px calc(18px + var(--safe-b))}
#sheet h3{margin:8px 0 0;font-size:18px;font-weight:900;text-align:center}
.rb{margin:14px 0 0;padding:16px 14px;border-radius:18px;text-align:center;color:#fff;background:radial-gradient(140px 90px at 100% 0,rgba(255,255,255,.3),transparent 70%),linear-gradient(120deg,#FF8A5B,#F4593C 60%,#E8473A)}
.rb small{display:block;font-size:12.5px;font-weight:700;opacity:.9}
.rb b{display:block;margin-top:4px;font-size:24px;font-weight:900;letter-spacing:.5px}
.rb b em{font-style:normal;color:#FFF3B8}
.rb i{display:block;margin-top:2px;font-style:normal;font-size:12px;opacity:.9}
.stp{margin:16px 0 0;padding:0;list-style:none;counter-reset:s}
.stp li{position:relative;padding:0 0 14px 38px;font-size:14px;line-height:1.6;color:#3A302C;counter-increment:s}
.stp li::before{content:counter(s);position:absolute;left:0;top:0;width:26px;height:26px;border-radius:50%;background:#FFEDE6;color:#F4593C;font-size:13px;font-weight:900;display:grid;place-items:center}
.stp li b{display:block;font-size:14.5px;font-weight:800;color:#2A1E1E}
.stp li small{display:block;font-size:12.5px;color:var(--muted)}
.cur-t{margin-top:12px;padding:10px 12px;border-radius:12px;background:#F6EEEA;font-size:13px;color:#6E5C57}
.cur-t b{color:#2A1E1E}
.sbtn{display:block;width:100%;height:46px;margin-top:6px;border-radius:99px;background:var(--btn);color:#fff;font-size:16px;font-weight:900;box-shadow:0 8px 16px -8px #EE5A3E}
.snote{margin-top:10px;text-align:center;font-size:11.5px;color:#B8A49E}
.tl-h{display:flex;align-items:center;gap:6px;margin:16px 0 8px;font-size:14px;font-weight:900}
.tl{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.tl button{display:flex;align-items:center;gap:4px;min-height:42px;padding:6px 10px;border-radius:12px;text-align:left;font-size:13.5px;font-weight:700;line-height:1.35;background:var(--hb);color:#3A2C28}
.tl button.on{box-shadow:inset 0 0 0 2px var(--hk)}
.tl button{--hb:var(--kl);--hk:var(--kf)}
.tl button span{flex:1}
.tl button em{font-style:normal;color:var(--hk);font-weight:900;margin:0 1px}
.tl button small{display:block;margin-top:2px;font-size:11px;font-weight:600;color:#A8918B}
.tl-h small{margin-left:6px;font-size:12px;font-weight:600;color:#A8918B}
.tl button i{flex:none;font-style:normal;padding:0 4px;border-radius:5px;background:#FF5A3C;color:#fff;font-size:9.5px;font-weight:800;line-height:15px}
.tl-all{display:block;width:100%;height:40px;margin-top:14px;border-radius:12px;background:#F6EEEA;font-size:14px;font-weight:800;color:#6E5C57}
.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}
/* ---------- 投稿(11-01:用户可投稿 → 审核中 → 后台通过/不通过 → 下次打开提醒) ---------- */
.nav .mine{position:relative;flex:none;height:30px;padding:0 10px;border-radius:99px;background:#fff;border:1px solid #F0E2DA;font-size:12.5px;font-weight:800;color:#6E5A55}
.nav .mine i{position:absolute;right:-2px;top:-3px;min-width:16px;height:16px;padding:0 4px;border-radius:99px;background:#F0453A;color:#fff;font-size:10px;font-style:normal;font-weight:800;line-height:16px;text-align:center;box-shadow:0 0 0 2px #F8F3EF}
#cp{position:fixed;inset:0;z-index:50;background:#FFFBF8;display:flex;flex-direction:column;transform:translateY(100%);transition:transform .3s cubic-bezier(.2,.8,.2,1)}
#cp.show{transform:none}
#cp .cph{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;border-bottom:1px solid var(--line);background:#fff}
#cp .cph .x{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;color:var(--ink)}
#cp .cph .x .ic{width:18px;height:18px}
#cp .cph h2{flex:1;margin:0;font-size:16px;font-weight:900;text-align:center}
#cp .cph .ok{flex:none;height:32px;padding:0 16px;border-radius:99px;background:var(--btn);color:#fff;font-size:14px;font-weight:900}
#cp .cph .ok:disabled{opacity:.45}
#cp .cpb{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:none;padding:14px 16px calc(24px + var(--safe-b))}
.cp-t{display:flex;align-items:center;gap:8px;width:100%;min-height:46px;padding:8px 12px;border-radius:14px;background:var(--kl,#F6EEEA);text-align:left}
.cp-t .ct2{flex:1;min-width:0;font-size:14px;font-weight:800;color:var(--kt,#6E5C57);line-height:1.4}
.cp-t .ch{flex:none;font-size:12px;font-weight:700;color:var(--muted);display:inline-flex;align-items:center}
.cp-rw{margin-top:10px;padding:9px 12px;border-radius:12px;background:#FFF1EB;font-size:12.5px;color:#9A5A44}
.cp-rw em{font-style:normal;font-weight:900;color:#E8473A}
.cp-in{display:block;width:100%;margin-top:14px;padding:4px 2px 10px;border:0;border-bottom:1px solid var(--line);background:none;outline:none;font:inherit;font-size:19px;font-weight:900;color:var(--ink)}
.cp-in::placeholder,.cp-ta::placeholder{color:#C2B0AA;font-weight:600}
.cp-ta{display:block;width:100%;min-height:260px;margin-top:12px;padding:2px;border:0;background:none;outline:none;resize:none;font:inherit;font-size:15.5px;line-height:1.8;color:#3A302C}
.cp-cnt{margin-top:4px;font-size:12px;color:var(--muted);text-align:right}
.cp-cnt b{color:#E8473A}
.cp-cnt.ok b{color:#2E8A7C}
.cp-pics{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.cp-pics .pt,.cp-pics .add{position:relative;width:calc((100% - 16px) / 3);aspect-ratio:1;border-radius:12px;overflow:hidden;background:#F3EAE5}
.cp-pics .pt img{width:100%;height:100%;object-fit:cover}
.cp-pics .pt.up::after{content:"上传中…";position:absolute;inset:0;display:grid;place-items:center;background:rgba(255,255,255,.6);font-size:12px;color:#6E5C57}
.cp-pics .pt.bad::after{content:"上传失败";position:absolute;inset:0;display:grid;place-items:center;background:rgba(255,255,255,.75);font-size:12px;color:#E8473A}
.cp-pics .pt button{position:absolute;right:4px;top:4px;width:22px;height:22px;border-radius:50%;background:rgba(0,0,0,.5);color:#fff;font-size:15px;line-height:22px}
.cp-pics .add{display:grid;place-items:center;border:1.5px dashed #E2CFC7;background:#FFF8F4;color:#B8A49E;font-size:12px}
.cp-pics .add .ic{display:block;margin:0 auto 4px;width:22px;height:22px}
.cp-tip{margin-top:16px;font-size:12px;line-height:1.7;color:#B8A49E}
/* 我的投稿 */
.my-e{padding:26px 0 10px;text-align:center;color:var(--muted);font-size:13.5px}
.my-it{padding:12px 0;border-bottom:1px solid #F3E9E4}
.my-it:last-child{border-bottom:0}
.my-h{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}
.my-h .tn{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.st{flex:none;height:20px;padding:0 7px;border-radius:6px;font-size:11.5px;font-weight:800;line-height:20px}
.st.pending{background:#FFF1DE;color:#C27612}
.st.approved{background:#DDF2EE;color:#21705F}
.st.rejected{background:#F2ECEA;color:#8A7570}
.my-it b{display:block;margin-top:5px;font-size:15px;font-weight:800;color:#2A1E1E}
.my-it p{margin:4px 0 0;font-size:12.5px;line-height:1.6;color:#7A6663}
.my-it p.why{padding:7px 10px;border-radius:10px;background:#F6F0EE}
.my-it p.rw2{padding:7px 10px;border-radius:10px;background:#FFF1EB;color:#9A5A44}
.my-it p.rw2 em{font-style:normal;font-weight:900;color:#E8473A}
/* 审核结果 / 提交成功弹窗 */
#rs{position:fixed;inset:0;z-index:70;display:grid;place-items:center;padding:24px;background:rgba(30,20,18,.5);opacity:0;pointer-events:none;transition:opacity .2s}
#rs.show{opacity:1;pointer-events:auto}
#rs .rsb{width:100%;max-width:320px;padding:22px 20px 18px;border-radius:22px;background:#FFFBF8;text-align:center;transform:scale(.94);transition:transform .2s}
#rs.show .rsb{transform:none}
#rs .rsi{width:58px;height:58px;margin:0 auto;border-radius:50%;display:grid;place-items:center;background:#FFEDE6;color:#F4593C}
#rs .rsi .ic{width:30px;height:30px}
#rs .rsi.ok{background:#DDF2EE;color:#2E8A7C}
#rs .rsi.no{background:#F2ECEA;color:#8A7570}
#rs h3{margin:12px 0 0;font-size:18px;font-weight:900}
#rs .rst{margin:6px 0 0;font-size:13.5px;line-height:1.7;color:#6E5C57}
#rs .rst b{color:#2A1E1E}
#rs .rst em{font-style:normal;font-weight:900;color:#E8473A}
#rs .rsw{margin-top:10px;padding:8px 10px;border-radius:10px;background:#F6F0EE;font-size:12.5px;line-height:1.6;color:#7A6663;text-align:left}
#rs .rsk{display:block;width:100%;height:42px;margin-top:16px;border-radius:99px;background:var(--btn);color:#fff;font-size:15px;font-weight:900}
/* 真实投稿:封面「精选」角标、详情配图 */
.cv .jx{position:absolute;right:.7em;top:.8em;z-index:2;height:1.55em;padding:0 .55em;border-radius:.5em;background:linear-gradient(135deg,#FFB547,#F4803C);color:#fff;font-size:.85em;font-weight:800;line-height:1.55em}
.dbody .pics{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:0 0 14px}
.dbody .pics img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:10px;background:#F3EAE5}
.dbody .pics img:only-child{grid-column:1/-1;aspect-ratio:auto}
.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-gift" viewBox="0 0 24 24"><path d="M4 10.5h16v3H4zM5.5 13.5h13v6.5h-13zM12 10.5V20M12 10.5c-1.2-2.6-4.8-4.4-6-2.6-1 1.6 1.6 2.6 6 2.6zm0 0c1.2-2.6 4.8-4.4 6-2.6 1 1.6-1.6 2.6-6 2.6z" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round"/></symbol>
<symbol id="i-fire" viewBox="0 0 24 24"><path d="M12 21c-4 0-6.5-2.7-6.5-6.2 0-3.6 2.9-5.6 3.6-9.3 2.6 1.4 3.6 3.6 3.6 5.4 1-.6 1.6-1.8 1.7-3 2.4 1.9 4.1 4.3 4.1 7 0 3.5-2.5 6.1-6.5 6.1z" fill="currentColor"/></symbol>
<symbol id="i-x" viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="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.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-ring" 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="2" stroke-linejoin="round"/></symbol>
<symbol id="i-bag" viewBox="0 0 24 24"><path d="M4 8.5h16v10.5H4zM9 8.5V6.2c0-.9.7-1.7 1.7-1.7h2.6c.9 0 1.7.8 1.7 1.7v2.3M4 13h16" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-baby" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="2"/><path d="M9.2 14.6c1.6 1.4 4 1.4 5.6 0" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><circle cx="9.3" cy="10.6" r="1.1" fill="currentColor"/><circle cx="14.7" cy="10.6" r="1.1" fill="currentColor"/></symbol>
<symbol id="i-check" viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.5" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 7.5V12l3 2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="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>
<button class="mine" id="mineBtn" type="button">我的投稿<i id="mineDot" class="hide"></i></button>
</div>
<div class="cats" id="cats" role="tablist" aria-label="分类"></div>
</div>
<div id="head"></div>
<div class="sh" id="fh"></div>
<div class="wf" id="wf"><div class="col"></div><div class="col"></div></div>
<div id="more"></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 id="cp" aria-hidden="true">
<div class="cph"><button class="x" id="cpX" type="button" aria-label="关闭"><svg class="ic"><use href="#i-x"/></svg></button><h2>写我的故事</h2><button class="ok" id="cpOk" type="button">提交</button></div>
<div class="cpb">
<button type="button" class="cp-t" id="cpT"></button>
<div class="cp-rw">投稿被选中,奖励 <em>¥30</em> 现金 + <em>500</em> 兜豆</div>
<input class="cp-in" id="cpTitle" type="text" maxlength="30" placeholder="起个标题(4~30 字)">
<textarea class="cp-ta" id="cpBody" maxlength="3000" placeholder="写下你的真实经历:发生了什么、当时怎么想、后来怎么做的……写得越具体,越容易被选中。"></textarea>
<div class="cp-cnt" id="cpCnt"></div>
<div class="cp-pics" id="cpPics"><label class="add" id="cpAdd"><span><svg class="ic"><use href="#i-plus"/></svg>配图(选填)</span><input id="cpFile" type="file" accept="image/*" hidden></label></div>
<div class="cp-tip">· 提交后进入审核,审核结果会在这里提醒你;通过的故事会展示在孕妈广场。<br>· 请写自己的真实经历,不要发广告、联系方式或别人的隐私。<br>· 草稿会自动保存在这台手机上。</div>
</div>
</div>
<div id="rs" role="dialog" aria-modal="true"><div class="rsb" id="rsb"></div></div>
<div id="mask"></div>
<div id="sheet" role="dialog" aria-modal="true"><i class="sg"></i><div class="sbd" id="sbd"></div></div>
<div class="toast" id="toast"></div>
<script src="topics.js?v=26110213"></script>
<script src="data.js?v=26110213"></script>
<script src="feed.js?v=26110213"></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 { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[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'; };
var avOf = function (n) { return n.avatar || avSrc(n.author); }; /* 真实投稿用本人头像,占位笔记用头像池 */
/* ---------- 笔记:data.js 的原始内容 + 确定性补字段(id / 封面样式 / 比例 / 评论) ---------- */
var NOTES = [], NBY = {}; /* 真实投稿到达后会往前插(loadApproved),所以 NOTES / MIXED 用 var 可重赋值 */
var RATIO = [1.12, 0.94, 1.04, 0.88, 1.18, 0.98, 0.9];
/* 11-02 用户:「要参差不齐的小红书瀑布流,现在都横向对齐」→ 照片封面高度按 id 哈希在 0.95~1.45 之间取,不再统一 1.3 */
var PR = [1.33, 1.05, 1.25, 1.45, 1.15, 0.95, 1.38, 1.2];
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 || '',
ratio: n.photo ? PR[seed(t.id + '-' + (i + 1) + 'r') % PR.length] : RATIO[(ti + i * 3) % RATIO.length], tone: (ti + i) % 3, photo: n.photo || ''
};
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 < 30; 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) {
if (n.real) return []; /* 真实投稿不配占位评论 */
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); }
/* ---------- 封面:一种版式,颜色只按分类(家庭粉 / 经验青绿)× 3 个深浅 ---------- */
var PAL = {
family: { ink: '#C23A55', c: [['#FFE6EB', '#FFC6D2'], ['#FFEAE2', '#FFCBB8'], ['#FCE8F2', '#F5C4DC']] },
marriage: { ink: '#6346B0', c: [['#EFE9FF', '#D6C8F6'], ['#F5E8FA', '#E2C6EF'], ['#E9EBFF', '#C9CEF5']] },
work: { ink: '#2C5E9E', c: [['#E4EFFB', '#BED5F1'], ['#E5F2F8', '#BFDDEB'], ['#ECEFF6', '#CBD3E6']] },
baby: { ink: '#21705F', c: [['#E0F3EE', '#B8E3D8'], ['#E6F3E3', '#C2E2BE'], ['#E1EFF5', '#B9D9E7']] }
};
var CAT_IC = { family: 'i-home', marriage: 'i-ring', work: 'i-bag', baby: 'i-baby' };
var CAT_SHORT = { family: '家庭婚姻', marriage: '家庭婚姻', work: '职场', baby: '经验' };
var CAT_SUB = { family: '婆家、长辈、夫妻相处、分工、日常拉扯', marriage: '夫妻相处、落差、分工、情绪、细碎磨合',
work: '在岗孕妈、产检、边界、顾虑、复工', baby: '身体变化、囤货、预算、生产经历、过来人经验' };
var kbHTML = function (cat) { return '<span class="kb k-' + cat + '"><svg class="ic"><use href="#' + CAT_IC[cat] + '"/></svg>' + CAT_SHORT[cat] + '</span>'; };
function coverHTML(n, h) {
var t = TBY[n.t], pl = PAL[t.cat], c = pl.c[n.tone];
if (n.photo) return '<div class="cv ph" style="' + (h ? 'height:' + h : '') + '"><img src="' + esc(n.photo) + '" alt="" loading="lazy">' + kbHTML(t.cat) + '</div>';
return '<div class="cv" style="--c1:' + c[0] + ';--c2:' + c[1] + ';--tk:' + pl.ink + ';' + (h ? 'height:' + h : '') + '">' + kbHTML(t.cat) + (n.real ? '<span class="jx">精选投稿</span>' : '') +
'<div class="ct"><div class="t1">' + esc(n.cover) + '</div><div class="t2">' + esc(n.coverSub) + '</div></div><i class="wm" aria-hidden="true">' + esc(t.g) + '</i></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>';
}
/* 卡片样式 sty(只对照片封面):'' 普通图 / 'ov' 图上压大字(底部渐变)/ 'tg' 图上贴纸字 —— 11-02 用户:「把一些文字放到图片上,穿插着来,类似小红书」 */
function cardHTML(n, showTopic, sty) {
var t = TBY[n.t], r = n.ratio, ov = '';
if (!n.photo) sty = '';
if (sty === 'ov') { r = Math.max(r, 1.28); ov = '<div class="ovt"><b>' + esc(n.cover) + '</b>' + (n.coverSub ? '<small>' + esc(n.coverSub) + '</small>' : '') + '</div>'; }
else if (sty === 'tg') ov = '<div class="tgt"><b><span>' + esc(n.cover) + '</span></b></div>';
return '<button type="button" class="nc' + (sty ? ' s-' + sty : '') + '" data-id="' + n.id + '"><div class="cvw">' +
coverHTML(n, 'calc(var(--cw) * ' + r + ')') + ov + '</div>' +
'<div class="nb"><h3>' + esc(n.title) + '</h3>' + (showTopic ? '<span class="tp k-' + t.cat + '">#' + esc(t.name) + '#</span>' : '') + '<div class="nf"><img src="' + esc(avOf(n)) + '" alt="" loading="lazy"><span class="nm">' + esc(n.author) + '</span>' + likeHTML(n) + '</div></div></button>';
}
/* ---------- 列表 ---------- */
/* cur 当前话题('' = 不限话题);catF 一级分类('' 全部 / family 家庭 / marriage 婚姻 / work 职场 / baby 母婴)。选了话题时 catF 恒等于该话题的 cat */
var cur = '', catF = '';
var UBAND = (function () { try { var g = JSON.parse(localStorage.getItem('mmbox.gcwk.v1') || 'null'); return !g ? -1 : g.pp ? 'pp' : g.w && window.GC_BAND ? window.GC_BAND('孕' + g.w + '周') : -1; } catch (e) { return -1; } })();
/* 11-01 用户:家庭+婚姻合成「家庭婚姻」,母婴改「经验」→ 三块(marriage 话题在 topics.js 里已并进 family) */
var CATS = [['', '全部', 'i-grid'], ['family', '家庭婚姻', 'i-home'], ['work', '职场', 'i-bag'], ['baby', '经验', 'i-baby']];
var CAT_ORDER = ['family', 'work', 'baby'];
var CAT_NAME = { family: '家庭婚姻', work: '职场方向', baby: '孕育经验' };
var inCat = function (t) { return !catF || t.cat === catF; };
/* 投稿奖励(11-01 用户定):话题投稿被选中 → 30 元现金 + 500 兜豆 */
var REWARD = '<em>¥30</em> 现金 + <em>500</em> 兜豆';
function renderCats() {
var bs = $('#cats').querySelectorAll('button[data-c]');
if (bs.length) { /* 已画过:只换选中态,胶囊才能滑过去 */
[].forEach.call(bs, function (b) { var on = b.dataset.c === catF; b.classList.toggle('on', on); b.setAttribute('aria-selected', on); });
moveBar(); return;
}
$('#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]) + '">' +
x[1] + '<i>' + catCnt(x[0]) + '</i></button>';
}).join('') + '<span class="bar"></span>';
moveBar();
}
function catCnt(c) { return NOTES.filter(function (n) { return !c || TBY[n.t].cat === c; }).length; }
/* 胶囊挪到选中标签文字下方,宽度跟文字走(取文字宽的一半,偏小红书) */
function moveBar() {
var on = $('#cats .on'), bar = $('#cats .bar'); if (!on || !bar) return;
var w = on.offsetWidth - 20, x = on.offsetLeft + (on.offsetWidth - w) / 2;
bar.style.width = w + 'px'; bar.style.transform = 'translateX(' + x + 'px)';
bar.style.background = getComputedStyle(on).getPropertyValue('--cf');
}
window.addEventListener('resize', moveBar);
function rewardHTML(sm) {
return '<button type="button" class="rw' + (sm ? ' sm' : '') + '" data-rule="1"><span class="gf"><svg class="ic"><use href="#i-gift"/></svg></span>' +
'<span class="rt"><small>参与话题投稿 · 被选中奖励</small><b>' + REWARD + '</b></span><span class="go">怎么参与<svg class="ic" style="width:12px;height:12px"><use href="#i-right"/></svg></span></button>';
}
/* 热门话题:带 hot 的排前面,其余按原顺序;跟着一级分类过滤 */
function hotList() {
var l = T.filter(inCat), hot = l.filter(function (t) { return t.hot; });
if (!catF) { /* 「全部」下四块轮流排,避免前几张全是同一块 */
var by = CAT_ORDER.map(function (c) { return hot.filter(function (t) { return t.cat === c; }); }), rr = [];
for (var r = 0; r < 10; r++) by.forEach(function (x) { if (x[r]) rr.push(x[r]); });
hot = rr;
}
return hot.concat(l.filter(function (t) { return !t.hot; }));
}
function renderHead() {
var t = TBY[cur], el = $('#head'), fh = $('#fh');
if (!t) {
var hl = hotList();
el.innerHTML = rewardHTML() +
'<div class="sh"><svg class="fire"><use href="#i-fire"/></svg><h2>热门话题</h2><button type="button" class="more" data-all="1">全部 ' + hl.length + ' 个<svg class="ic" style="width:13px;height:13px"><use href="#i-right"/></svg></button></div>' +
/* 11-02 用户:「热门话题不要一块一块的,改成井号、偏列表的形式」→ 排行列表:名次 + #话题# + 一行简介 + 篇数/热,右侧「参与」 */
'<div class="htl">' + hl.slice(0, 6).map(function (x, i) {
return '<div class="hr k-' + x.cat + '" data-t="' + x.id + '" role="button"><i class="no' + (i < 3 ? ' t' + i : '') + '">' + (i + 1) + '</i>' +
'<span class="hm"><b><em>#</em>' + esc(x.name) + '<em>#</em></b><small>' + (catF ? '' : '<u>' + CATS.filter(function (c) { return c[0] === x.cat; })[0][1] + '</u>') + cntT(x.id) + ' 篇分享 · ' + esc((D[x.id] || {}).desc || '') + '</small></span>' +
'<button type="button" class="jn" data-join="' + x.id + '">参与</button></div>';
}).join('') + '<button type="button" class="hall" data-all="1">查看全部 ' + hl.length + ' 个话题 ›</button></div>';
if (catF) { fhLevels(fh); return; }
fh.className = 'sh';
fh.innerHTML = '<h2>大家在聊</h2><small>' + T.filter(function (x) { return cntT(x.id); }).length + ' 个话题 · 共 ' + NOTES.length + ' 篇</small>';
return;
}
var d = D[t.id] || {};
el.innerHTML = '<div class="th k-' + t.cat + '"><i class="wm" aria-hidden="true">' + esc(t.g) + '</i><button type="button" class="x" data-t="" aria-label="看全部"><svg class="ic"><use href="#i-x"/></svg></button>' +
'<div class="bc"><button type="button" data-t="">' + kbHTML(t.cat).replace('</span>', ' ›</span>') + '</button><span>话题 · ' + cntT(t.id) + ' 篇</span></div>' +
'<h2><em>#</em>' + esc(t.name) + '<em>#</em></h2><p>' + esc(d.desc || '') + '</p>' +
'<div class="tf"><button type="button" class="join" data-join="' + t.id + '"><svg class="ic"><use href="#i-plus"/></svg>参与话题</button><button type="button" class="sw" data-all="1">换个话题</button></div></div>';
/* 11-02 用户:「话题页比较乱」→ 去掉投稿奖励横幅和同分类话题胶囊,只留一行标题 */
fh.className = 'sh';
fh.innerHTML = '<h2>这个话题下的分享</h2><small>共 ' + cntT(t.id) + ' 篇</small>';
}
/* 11-02 用户:「选了家庭婚姻下一个话题,看着像这块就这几篇,层次感没出来」→ 选了分类 / 话题时,列表上方固定一行「分类 · N 个话题 · 共 M 篇」+ 该分类全部话题胶囊(带篇数),当前话题高亮,「全部」回分类 */
var cntT = function (id) { return NOTES.filter(function (n) { return n.t === id; }).length; };
function fhLevels(fh) {
var tl = hotList().filter(function (x) { return cntT(x.id); }), all = 0;
tl.forEach(function (x) { all += cntT(x.id); });
fh.className = 'lvw k-' + catF;
fh.innerHTML = '<div class="lv"><h2>' + CATS.filter(function (c) { return c[0] === catF; })[0][1] + '</h2><small>' + tl.length + ' 个话题 · 共 ' + all + ' 篇</small>' +
(cur ? '<button type="button" class="ba" data-t="">看这块全部 ›</button>' : '') + '</div>' +
'<div class="tcs"><button type="button" data-t=""' + (cur ? '' : ' class="on"') + '>全部<i>' + all + '</i></button>' +
tl.map(function (x) { return '<button type="button" data-t="' + x.id + '"' + (cur === x.id ? ' class="on"' : '') + '>#' + esc(x.name) + '#<i>' + cntT(x.id) + '</i></button>'; }).join('') + '</div>';
var on = fh.querySelector('.tcs .on'); if (on && cur) fh.querySelector('.tcs').scrollLeft = Math.max(0, on.offsetLeft - 60);
}
function renderFeed() {
var list = cur ? NOTES.filter(function (n) { return n.t === cur; }) : MIXED.filter(function (n) { return inCat(TBY[n.t]); });
/* 11-02 按孕周段排:同阶段孕妈的帖子为主、穿插过来人(GC_ORDER 在 feed.js);真实投稿仍排最前;孕周由首页写进 mmbox.gcwk.v1 */
if (window.GC_ORDER) list = list.filter(function (n) { return n.real; }).concat(window.GC_ORDER(list.filter(function (n) { return !n.real; }), UBAND));
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'), STY = ['', 'ov', '', '', 'tg', '', '', 'ov', '', 'tg', '', ''];
list.forEach(function (n, k) {
tmp.innerHTML = cardHTML(n, !cur, STY[k % STY.length]);
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;
});
/* 话题下帖子看完,接着引到同分类其他话题,避免以为这块只有这几篇 */
var mo = $('#more'), tc = cur && TBY[cur];
if (tc) {
var rest = NOTES.filter(function (n) { return n.t !== cur && TBY[n.t].cat === tc.cat; }).length;
mo.innerHTML = '<button type="button" class="mo k-' + tc.cat + '" data-t=""><small>这个话题就这些啦</small><b>「' + CATS.filter(function (c) { return c[0] === tc.cat; })[0][1] + '」还有 ' + rest + ' 篇,去看看 ›</b></button>';
} else mo.innerHTML = '';
}
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');
q.delete('mine');
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(); renderHead(); renderFeed();
history.replaceState(history.state, '', setQuery(cur, ''));
var sc = $('#sc'); if (smooth !== false) sc.scrollTop = 0;
}
$('#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(''); /* 换分类回到该类「全部」,避免停在别类话题上 */
});
/* 11-02 用户:「广场首页左右滑动,可以切到家庭婚姻、职场、经验」→ 横向滑动超过 60px 且明显比竖向大,就切到相邻分类;横滑列表、弹层里不触发 */
(function () {
var sx = 0, sy = 0, ok = false, sc = $('#sc');
sc.addEventListener('touchstart', function (e) {
var t = e.touches[0]; sx = t.clientX; sy = t.clientY;
ok = e.touches.length === 1 && !e.target.closest('.tcs,.hot,.htl .jn,#sheet,#note,.nd') && !document.body.classList.contains('lock');
}, { passive: true });
sc.addEventListener('touchend', function (e) {
if (!ok) return; ok = false;
var t = e.changedTouches[0], dx = t.clientX - sx, dy = t.clientY - sy;
if (Math.abs(dx) < 60 || Math.abs(dx) < Math.abs(dy) * 1.6) return;
var order = CATS.map(function (c) { return c[0]; }), i = order.indexOf(catF) + (dx < 0 ? 1 : -1);
if (i < 0 || i >= order.length) return;
catF = order[i]; haptic();
var wf = $('#wf'); wf.classList.remove('swl', 'swr'); void wf.offsetWidth; wf.classList.add(dx < 0 ? 'swl' : 'swr');
selectTopic('');
}, { passive: true });
})();
$('#fh').addEventListener('click', function (e) {
var b = e.target.closest('[data-t]'); if (!b || b.dataset.t === cur) return;
haptic(); var sl = $('#fh .tcs') ? $('#fh .tcs').scrollLeft : 0;
selectTopic(b.dataset.t, false);
var tc = $('#fh .tcs'); if (tc && !b.dataset.t) tc.scrollLeft = sl;
});
$('#more').addEventListener('click', function (e) { if (e.target.closest('[data-t]')) { haptic(); selectTopic(''); } });
$('#head').addEventListener('click', function (e) {
var j = e.target.closest('[data-join]'); if (j) { haptic(); openRule(j.dataset.join); return; }
if (e.target.closest('[data-rule]')) { openRule(''); return; }
if (e.target.closest('[data-all]')) { openTopics(); return; }
var b = e.target.closest('[data-t]'); if (b) { haptic(); selectTopic(b.dataset.t); }
});
/* ---------- 底部弹层:投稿规则 / 全部话题 ---------- */
var sheetOn = '';
function openSheet(kind, html) {
sheetOn = kind; $('#sbd').innerHTML = html; $('#sbd').scrollTop = 0;
$('#mask').classList.add('show'); $('#sheet').classList.add('show');
}
var pickFor = '';
function closeSheet() { sheetOn = ''; $('#mask').classList.remove('show'); $('#sheet').classList.remove('show'); }
function openRule(tid) {
var t = TBY[tid];
openSheet('rule', '<h3>话题投稿有奖</h3>' +
'<div class="rb"><small>投稿被选中,每篇奖励</small><b>' + REWARD + '</b></div>' +
(t ? '<div class="cur-t">你要参与的话题:<b>#' + esc(t.name) + '#</b></div>' : '') +
'<ol class="stp">' +
'<li><b>选一个话题</b><small>在「热门话题」或「全部话题」里挑你有话说的那个</small></li>' +
'<li><b>写下你的真实经历</b><small>家里的暖事、踩过的坑、过来人的经验都可以</small></li>' +
'<li><b>编辑挑选,被选中就发奖励</b><small>选中的故事会展示在孕妈广场,奖励发给作者</small></li></ol>' +
'<button type="button" class="sbtn" data-write="' + (t ? t.id : '') + '">写我的故事</button>' +
'<div class="snote">提交后进入审核,审核结果会在孕妈广场提醒你</div>');
}
function openTopics() {
var grp = function (cat) {
var tl = T.filter(function (t) { return t.cat === cat; });
return '<div class="tl-h">' + kbHTML(cat) + '<small>' + tl.length + ' 个话题</small></div><div class="tl k-' + cat + '">' + tl.map(function (t) {
return '<button type="button" data-pick="' + t.id + '" class="' + (cur === t.id ? 'on' : '') + '"><span><em>#</em>' + esc(t.name) + '<em>#</em><small>' + cntT(t.id) + ' 篇分享</small></span>' + (t.hot ? '<i>热</i>' : '') + '</button>';
}).join('') + '</div>';
};
openSheet('topics', '<h3>全部 ' + T.length + ' 个话题</h3>' + (catF ? [catF] : []).concat(CAT_ORDER.filter(function (c) { return c !== catF; })).map(grp).join('') +
'<button type="button" class="tl-all" data-pick="">看全部分享</button>');
}
$('#mask').addEventListener('click', closeSheet);
$('#sheet').addEventListener('click', function (e) {
var p = e.target.closest('[data-pick]');
if (p && pickFor === 'compose') { closeSheet(); pickFor = ''; if (p.dataset.pick) setCpTopic(p.dataset.pick); return; }
if (p) { closeSheet(); haptic(); if (!p.dataset.pick) catF = ''; selectTopic(p.dataset.pick); return; }
var w = e.target.closest('[data-write]');
if (w) { closeSheet(); openCompose(w.dataset.write || cur); return; }
if (e.target.closest('[data-mywrite]')) { closeSheet(); openCompose(cur); }
});
/* 卡片:点心形就地点赞,点别处进详情 */
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></div>'; /* 11-02 自己的评论也不显示时间 */
}
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>' + (c.s ? '<div class="ci-s">' + esc(c.s) + '</div>' : '') /* 11-02 用户:评论时间先不显示 */ + 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 = avOf(n);
$('#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 * (n.photo ? 1.1 : .72)); /* 详情封面统一矮一点,正文早点露出来 */
var day = 26 + (seed(n.id) % 6), mon = day > 31 ? 11 : 10;
var when = n.real ? (function (d) { return (d.getMonth() + 1) + '-' + d.getDate(); })(new Date(n.at)) : mon + '-' + (day > 31 ? day - 31 : day);
$('#dsc').innerHTML = '<div class="dcv">' + coverHTML(n, h + 'px') + '</div>' +
'<div class="dbody"><div class="dk">' + kbHTML(t.cat) + '<button type="button" class="k-' + t.cat + '" data-go="' + t.id + '">#' + esc(t.name) + '#</button></div>' +
'<h2>' + esc(n.title) + '</h2><div class="tx">' + bodyHTML(n.body) + '</div>' +
((n.images || []).length ? '<div class="pics">' + n.images.map(function (u) { return '<img src="' + esc(u) + '" alt="" loading="lazy">'; }).join('') + '</div>' : '') +
'<div class="tm">' + [n.stage ? esc(n.stage) : '', n.real ? '妈妈投稿' : ''].filter(Boolean).join(' · ') + '</div></div>' /* 11-02 用户:帖子发布日期先隐藏(when 留着,以后恢复直接拼回去) */ +
'<div class="pj k-' + t.cat + '"><span class="pt"><b>你也有类似的经历?</b><small>投稿被选中得 ' + REWARD + '</small></span><button type="button" data-join="' + t.id + '">参与话题</button></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 () {
if (sheetOn) closeSheet();
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 jn = e.target.closest('[data-join]'); if (jn) { haptic(); openRule(jn.dataset.join); return; }
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('评论已发出');
}
/* ================= 投稿(2026-11-01) =================
用户原话:「用户的账号可以去投稿……提交之后会显示『正在被审核』。如果用户的稿件被通过,后台会给他一个提醒」。
接口 box_app /api/mp/public/mama-box/plaza/*(只认 openid):
POST post {topic,title,body,images[]} → 稿件(pending)· GET mine → {list, unread} · POST mine/seen {ids}
GET posts?limit= → 已通过的稿件(不含 openid),混进广场展示,封面标「精选投稿」。
审核在管理后台「孕妈广场投稿」页;通过 = 被选中,奖励 ¥30 现金 + 500 兜豆由运营线下发放、后台标记。
· 提醒:每次打开广场拉 mine,unread(审核有结果且没提醒过)逐条弹窗,关掉后 seen。首页广场模块也会挂一条提示(app.js initPlaza)。
· 草稿存本机 mmbox.gc.draft.v1(按 openid),关掉写稿页不丢。 */
var API = '/api/mp/public/mama-box/plaza', UNION = param('unionid');
var idq = function () { return 'openid=' + encodeURIComponent(OPENID) + (UNION ? '&unionid=' + encodeURIComponent(UNION) : ''); };
var getJ = function (u, opt) { return fetch(u, opt).then(function (r) { return r.json(); }); };
var ST_NAME = { pending: '审核中', approved: '已通过', rejected: '未通过' };
var MINE = [];
/* 已通过的稿件 → 混进笔记流(话题流和「全部」都排最前) */
function loadApproved() {
getJ(API + '/posts?limit=100').then(function (j) {
var l = (j && j.result && (j.result.list || j.result)) || [];
if (!Array.isArray(l) || !l.length) return;
var add = [];
l.forEach(function (p, k) {
if (!TBY[p.topic] || NBY['u-' + p.id]) return;
var o = { id: 'u-' + p.id, t: p.topic, real: true, title: p.title, cover: p.title.length > 9 ? p.title.slice(0, 8) + '…' : p.title, coverSub: '来自妈妈的真实投稿',
author: p.nickname || '孕妈', avatar: p.avatar || '', stage: p.stage || '', likes: 0, body: p.body || '', images: p.images || [],
at: p.approvedAt || p.at || Date.now(), ratio: RATIO[k % RATIO.length], tone: k % 3 };
NBY[o.id] = o; add.push(o);
});
if (!add.length) return;
NOTES = add.concat(NOTES); MIXED = add.concat(MIXED);
renderFeed();
if (deep && NBY[deep] && !openId) openNote(deep, false); /* 分享出去的真实投稿链接:稿件到了再开 */
}).catch(function () {});
}
/* 我的投稿 */
function loadMine(cb) {
if (!OPENID) return;
getJ(API + '/mine?' + idq()).then(function (j) {
var r = j && j.result; if (!r) return;
MINE = r.list || [];
var un = r.unread || [];
var d = $('#mineDot'); d.textContent = un.length || ''; d.classList.toggle('hide', !un.length);
if (cb) cb(); else if (un.length) showResults(un);
}).catch(function () {});
}
function fmtDay(ms) { var d = new Date(ms); return (d.getMonth() + 1) + '月' + d.getDate() + '日'; }
function openMine() {
var h = '<h3>我的投稿</h3>';
if (!OPENID) h += '<div class="my-e">请从小程序里打开孕妈广场,才能查看你的投稿</div>';
else if (!MINE.length) h += '<div class="my-e">还没有投稿,写下你的第一个故事吧</div>';
else h += MINE.map(function (p) {
var t = TBY[p.topic];
return '<div class="my-it"><div class="my-h"><span class="tn">#' + esc(t ? t.name : p.topicName || '') + '#</span><span>' + fmtDay(p.at) + '</span><span class="st ' + p.status + '">' + (ST_NAME[p.status] || '') + '</span></div>' +
'<b>' + esc(p.title) + '</b>' +
(p.status === 'pending' ? '<p>正在审核中,有结果会第一时间提醒你</p>' : '') +
(p.status === 'rejected' ? '<p class="why">没通过的原因:' + esc(p.reason || '暂不符合展示要求') + '</p>' : '') +
(p.status === 'approved' ? '<p class="rw2">已被选中,奖励 <em>¥30</em> 现金 + <em>500</em> 兜豆 · ' + (p.reward === 'paid' ? '已发放' : '待发放') + '</p>' : '') + '</div>';
}).join('');
h += '<button type="button" class="sbtn" data-mywrite="1" style="margin-top:16px">写新的故事</button>';
openSheet('mine', h);
}
$('#mineBtn').addEventListener('click', function () { haptic(); loadMine(openMine); openMine(); });
/* 审核结果弹窗:逐条弹,全部看完一次性 seen */
function showResults(list) {
var q = list.slice(), ids = list.map(function (p) { return p.id; });
(function next() {
var p = q.shift();
if (!p) {
fetch(API + '/mine/seen?' + idq(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ids: ids }) }).catch(function () {});
$('#mineDot').classList.add('hide');
return;
}
var ok = p.status === 'approved';
showRs(ok ? 'ok' : 'no', ok ? '你的投稿通过啦' : '这篇投稿没有通过',
'《<b>' + esc(p.title) + '</b>》' + (ok ? '已被选中,将展示在孕妈广场。<br>奖励 <em>¥30</em> 现金 + <em>500</em> 兜豆,工作人员会尽快发放。' : '暂时没有通过审核,可以修改后重新投稿。'),
ok ? '' : '原因:' + esc(p.reason || '暂不符合展示要求'), q.length ? '下一条' : '知道了', next);
})();
}
function showRs(kind, title, text, why, btn, cb) {
$('#rsb').innerHTML = '<div class="rsi ' + kind + '"><svg class="ic"><use href="#' + (kind === 'ok' ? 'i-check' : kind === 'no' ? 'i-x' : 'i-clock') + '"/></svg></div>' +
'<h3>' + title + '</h3><p class="rst">' + text + '</p>' + (why ? '<div class="rsw">' + why + '</div>' : '') + '<button type="button" class="rsk" id="rsk">' + btn + '</button>';
$('#rs').classList.add('show');
$('#rsk').onclick = function () { $('#rs').classList.remove('show'); if (cb) setTimeout(cb, 220); };
}
/* 写稿页 */
var DK = 'mmbox.gc.draft.v1', cpTopic = '', pics = [], ups = 0;
function draft(v) {
try {
var all = JSON.parse(localStorage.getItem(DK) || '{}') || {};
if (v === undefined) return all[UK] || {};
if (v) all[UK] = v; else delete all[UK];
localStorage.setItem(DK, JSON.stringify(all));
} catch (e) { return {}; }
}
function setCpTopic(id) {
cpTopic = TBY[id] ? id : '';
var t = TBY[cpTopic], b = $('#cpT');
b.className = 'cp-t' + (t ? ' k-' + t.cat : '');
b.innerHTML = (t ? kbHTML(t.cat) + '<span class="ct2">#' + esc(t.name) + '#</span>' : '<span class="ct2">选择要参与的话题</span>') +
'<span class="ch">' + (t ? '换话题' : '去选') + '<svg class="ic" style="width:13px;height:13px"><use href="#i-right"/></svg></span>';
saveDraft();
}
function cnt() {
var n = $('#cpBody').value.trim().length, c = $('#cpCnt');
c.className = 'cp-cnt' + (n >= 300 ? ' ok' : '');
c.innerHTML = '已写 <b>' + n + '</b> 字 · ' + (n < 50 ? '至少 50 字' : n < 300 ? '写到 300 字以上更容易被选中' : '很棒,继续写也可以');
}
function saveDraft() { draft({ t: cpTopic, a: $('#cpTitle').value, b: $('#cpBody').value }); }
function openCompose(tid) {
if (!OPENID) { toast('请从小程序里打开孕妈广场再投稿'); return; }
if (openId) closeNote();
var d = draft();
$('#cpTitle').value = d.a || ''; $('#cpBody').value = d.b || '';
setCpTopic(tid || d.t || '');
cnt();
$('#cp').classList.add('show'); $('#cp').setAttribute('aria-hidden', 'false');
}
function closeCompose() { saveDraft(); $('#cp').classList.remove('show'); $('#cp').setAttribute('aria-hidden', 'true'); document.activeElement && document.activeElement.blur(); }
$('#cpX').addEventListener('click', closeCompose);
$('#cpT').addEventListener('click', function () { pickFor = 'compose'; openTopics(); });
$('#cpTitle').addEventListener('input', saveDraft);
$('#cpBody').addEventListener('input', function () { cnt(); saveDraft(); });
function shrink(f) {
return new Promise(function (res) {
var u = URL.createObjectURL(f), im = new Image();
im.onload = function () {
var k = Math.min(1, 1600 / Math.max(im.width, im.height)), c = document.createElement('canvas');
c.width = Math.round(im.width * k); c.height = Math.round(im.height * k);
c.getContext('2d').drawImage(im, 0, 0, c.width, c.height); URL.revokeObjectURL(u);
c.toBlob(function (b) { res(b || f); }, 'image/jpeg', .85);
};
im.onerror = function () { URL.revokeObjectURL(u); res(f); };
im.src = u;
});
}
var syncAdd = function () { $('#cpAdd').classList.toggle('hide', pics.length >= 6); };
$('#cpFile').addEventListener('change', function () {
var f = this.files && this.files[0]; this.value = '';
if (!f || pics.length >= 6) return;
var it = { url: null, el: document.createElement('span') };
it.el.className = 'pt up';
it.el.innerHTML = '<img alt=""><button type="button" aria-label="删除这张">×</button>';
it.el.querySelector('img').src = URL.createObjectURL(f);
it.el.querySelector('button').onclick = function () { pics = pics.filter(function (x) { return x !== it; }); it.el.remove(); syncAdd(); };
$('#cpPics').insertBefore(it.el, $('#cpAdd')); pics.push(it); syncAdd(); ups++;
shrink(f).then(function (b) { var fd = new FormData(); fd.append('file', b, 'plaza.jpg'); return fetch('/api/upload', { method: 'POST', body: fd }); })
.then(function (r) { return r.json(); }).then(function (j) { it.url = j && j.result && j.result.url || null; if (!it.url) throw 0; it.el.classList.remove('up'); })
.catch(function () { toast('图片上传失败,可以删掉重新选'); it.el.classList.remove('up'); it.el.classList.add('bad'); })
.then(function () { ups--; });
});
$('#cpOk').addEventListener('click', function () {
var btn = this, title = $('#cpTitle').value.trim(), body = $('#cpBody').value.trim();
if (!cpTopic) { toast('先选一个要参与的话题'); return; }
if (title.length < 4) { toast('标题至少 4 个字'); return; }
if (body.length < 50) { toast('正文至少 50 个字,再多写一点吧'); return; }
if (ups > 0) { toast('图片还在上传,稍等一下'); return; }
btn.disabled = true; btn.textContent = '提交中';
getJ(API + '/post?' + idq(), { method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ topic: cpTopic, title: title, body: body, images: pics.map(function (x) { return x.url; }).filter(Boolean) }) })
.then(function (j) {
if (!j || j.code !== 200 || !j.result) { toast((j && j.message) || '提交失败,请稍后再试'); return; }
MINE.unshift(j.result);
draft(null); pics.forEach(function (x) { x.el.remove(); }); pics = []; syncAdd();
$('#cpTitle').value = ''; $('#cpBody').value = '';
closeCompose(); haptic();
showRs('wait', '已提交,正在审核中', '《<b>' + esc(title) + '</b>》已经交给编辑审核,<br>有结果会在这里提醒你。', '', '好的');
})
.catch(function () { toast('网络不太好,请稍后再试(草稿已保存)'); })
.then(function () { btn.disabled = false; btn.textContent = '提交'; });
});
/* ---------- 返回 ---------- */
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 () {
/* 11-02 用户:「从首页点热门话题进来,左上角返回要回孕妈广场,不是首页」→ 在话题里先退回广场「全部」,再按一次才回首页 */
if (cur) { haptic(); catF = ''; selectTopic(''); return; }
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 (CAT_ORDER.indexOf(c0) >= 0) catF = c0;
selectTopic(param('t') && TBY[param('t')] ? param('t') : '', false);
if (deep && NBY[deep]) openNote(deep, false);
loadApproved();
if (new URLSearchParams(location.search).get('mine') === '1') {
loadMine(function () {
var un = MINE.filter(function (p) { return !p.seen && p.status !== 'pending'; });
if (un.length) showResults(un); else openMine();
});
} else loadMine();
var rt; window.addEventListener('resize', function () { clearTimeout(rt); rt = setTimeout(renderFeed, 150); });
})();
</script>
</body>
</html>