Compare commits

...

94 Commits

Author SHA1 Message Date
deploy
52b2fe4a51 上正式准备:首页孕妈广场模块 V6/V4 与品牌露出从 demo/ 并入 js/gch/,去掉 V4 每次不缓存的加载(v26110245)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 03:33:53 +00:00
deploy
c2ae798ac6 专题页点回复时底部出「回复 XX:原文」提示条(可取消);广场评论孕周挪到名字右边小胶囊,同专题页(v26110244)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 02:00:06 +00:00
deploy
3f40e11c96 广场帖子、专题页评论可以回复:点评论或「回复」即回复 TA,回复同样先审后发,楼里按时间排(v26110243)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 00:07:38 +00:00
deploy
c2ebad1169 广场帖子、专题页评论改为先交后台审核:审核中只自己可见并挂状态,通过后所有人可见,未通过显示原因(v26110242)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:45:20 +00:00
deploy
3a97708bd7 测一测首页撑满一屏:多余高度均分到各块之间,屏越高头图和结果图越大,不再底部留空(v26110241)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:35:07 +00:00
deploy
de73154cbc 其他妈妈也在搜:热搜标去掉「沸」,第 2~7 名统一挂「热」(v26110240)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 23:04:37 +00:00
deploy
45ce041ad6 测一测首页一屏放下:头图缩右上小图、信息横排、结果类型一行四个,开始测试按钮贴底兜底(v26110239)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 22:56:56 +00:00
deploy
db93c22e15 首页广场入口条下移拉开间距;广场和专题评论+回复里生成真人照头像占 62% 以上;专题相关推荐去图改紧凑文字行,评论框改为底部浮条(v26110238)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 15:08:15 +00:00
deploy
65a814a216 孕妈广场:591 个照片头像替换代码头像,评论区前排换真人照;测一测换 3D 黏土图标、人测过数字醒目、知识考卷改名常识小测、好物配置热度 5~15 万(v26110237)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:50:49 +00:00
deploy
2cdea16f2e v26110236 首页孕妈广场:「逛广场」并进副标题行,整行做成可点的入口条
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:17:21 +00:00
deploy
2c136c2cf2 v26110235 全部问题页:去掉「正在看」和热度条,只留「N 人看过」;前 10 名挂热搜小标(爆/沸/热/新)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:14:26 +00:00
deploy
ef0f95d260 v26110234 评论人设头像按比例重分:卡通 150 + 可爱卡通 150 + 内置头像 50(新画 300 张);准爸爸不再用妈妈照片;照片类 650 个待生图
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:51:02 +00:00
deploy
1e9b88896b v26110233 广场普通卡去话题;图上文字 30% 放顶部/中间;回复里「作者」拉开间距;自己的评论带孕周;我的收藏(首页「我的」入口 + 广场收藏层)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:29:18 +00:00
deploy
0a74cfc83f v26110232 问题页小 Banner + 热度/正在看/看过;专题页工具固定模块 + 相关推荐 3 个 + 评论区;首页「进孕妈广场」「全部 30 份测试」
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:21:48 +00:00
deploy
a21c3ace47 孕妈广场:每篇帖子 22~26 条贴合正文的评论 + 作者回复(cm.json,约 4100 条),评论人取自 1000 个人设(av/ 代码绘制头像 + 59 张写实照);带字卡下方加回一行标题;测一测顶部压成一行;AGENTS.md 12c 登记模拟评论例外;v26110231
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:10:11 +00:00
deploy
94f26f256e 孕妈广场瀑布流:图上带字的卡下方不再显示话题,只留作者和点赞;v26110230
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:55:25 +00:00
deploy
245838ef6a 测一测列表整理:热度榜和四个分组统一为一种列表行(缩略图 + 标题说明 + 右侧大号「N万 人测过」),去掉推荐大卡/卷宗/问句卡/关卡路线;热度榜默认前 5;v26110229
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:54:09 +00:00
deploy
f1917733d1 孕妈广场瀑布流:图上带字卡改为直接放完整标题(压大字带孕周、贴纸字),卡片下方不再重复标题;v26110228
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:52:13 +00:00
deploy
22e18c27ab 孕妈广场瀑布流:图上带字卡提到约 45%(每列带字/不带字交替、两列错开,压大字与贴纸字轮换);「全部」每 8 张帖子插 1 张测试卡(约 11%,先精选再按热度);v26110227
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:46:19 +00:00
deploy
bbdc306114 测一测:5 个好物配置测试换回用户原标题(副标题保留);v26110226
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:21:07 +00:00
deploy
cd645dae24 测一测:新增热度榜(按测过人数排名,前 10 可展开全部 30);各组按热度排序,推荐位为本组最热未测;考卷编号改 TOP 排名;v26110225
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:19:49 +00:00
deploy
1d3eb9de93 测一测:列表、信息流卡、测试开始页显示「N万人测过」模拟人数(AGENTS.md 12b 登记例外,2026-12-31 前复核);v26110224
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:18:01 +00:00
deploy
e9ed707c44 测一测:30 个测试标题、副标题改成大白话(谁来测 · 测什么);列表副标题去掉题数避免截断;v26110223
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:14:05 +00:00
deploy
770d7068ec 孕妈广场:「我的投稿」从右上角移到「全部」瀑布流第一张入口卡,新增独立页 guangchang/mine/(统计、筛选、审核状态、奖励、重投);首页审核提醒 ?mine=1 转到该页;v26110222
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:10:08 +00:00
deploy
a5128c4a19 测一测:12 种好物玩家类型图改为代码绘制的徽章插画;趣味心理改彩色问句卡、趣味闯关改关卡路线(不再堆插画);6 种类型结果改双列占比条;v26110221
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 12:05:27 +00:00
deploy
4be3d20275 测一测:新增 5 个好物配置测试(t26-t30,12 种采购玩家类型);测一测列表按组换排法(考卷编号/心理双列/闯关横滑/好物图文);测一测分类标签独立样式;v26110220
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 11:55:39 +00:00
deploy
96ca17261c 测一测 v2:广场「经验」后加「测一测」分类 + 信息流穿插测试卡、删祈福树下横滑条;测试页按妈妈类型卡样式重做并配插画;v26110219
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 11:44:23 +00:00
deploy
9b29af6dc3 生娃计算器:路线顺序改为 普通人 → 中产 → 大富豪(存档按路线 id 兼容旧顺序)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 11:41:29 +00:00
deploy
a8a27964f6 孕妈广场加「测一测」:25 个测试(知识考卷/趣味心理/闯关打分,共 341 题)+ 广场入口横滑卡;v26110218
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 11:14:30 +00:00
deploy
49d6ddbcec 孕妈广场热门话题:6 个改 4 个,去掉每行下方浅色小字
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 11:04:21 +00:00
deploy
5575062c4c 营养专题:并入用户给的营养与智力表,扩为 5 种营养可展开卡(DHA/叶酸/碘/铁/胆碱:管什么+研究怎么说+怎么吃),数据按可查文献校正并补来源
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:59:37 +00:00
deploy
fb42d930f8 生娃计算器结果页:去掉「换条路线再算」「改一下答案」,保存账单图片下只留「重新测试」(清空路线和答案回开始屏)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:57:13 +00:00
deploy
273fa9ec09 孕妈广场左右切分类:内容跟手拖动、胶囊同步挪,松手滑出滑入/不够回弹,两头阻尼;点标签同样滑入
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:37:30 +00:00
deploy
9cd77be0e1 祈福树 banner 标题改为 #为宝宝挂一张福牌# 话题样式
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:35:52 +00:00
deploy
62a889b474 孕妈广场:顶部换成宝宝祈福树 banner(树摇摆、福牌上飘、星光,点击进 /qifu-shu/ 带身份并上报 last_app);投稿奖励挪到热门话题列表头
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:26:15 +00:00
deploy
2fe63c7717 孕妈广场:179 篇标题/封面字/正文按小红书口吻第三轮重写
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:16:42 +00:00
deploy
48a9793f8d 孕妈广场:分类滑块改文字标签+荧光笔胶囊(去图标)、左右滑切分类;话题页去奖励横幅和话题胶囊,返回先回广场
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:14:21 +00:00
deploy
d6f1be67fd 孕妈广场热门话题:横滑卡片改为 #话题# 排行列表(名次+篇数+简介+参与)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 10:07:42 +00:00
deploy
3788dce122 其他妈妈也在搜:标签改为 爆/热/热/新/新,第 6 条不显示
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:58:26 +00:00
deploy
8d4d4c97de 孕妈广场全部话题弹层:#话题# 井号着色、每个话题标篇数、分类行改为「N 个话题」
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:52:59 +00:00
deploy
a821e59d62 首页 slogan 改为「陪你从孕期到育儿的每一天」(重新生成站酷小薇子集);底部落款只留这一句
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:50:11 +00:00
deploy
fb97cc2bde 其他妈妈也在搜:6 条按名次配标签 爆/热/关注最多/收藏多/讨论多/新,各自配色
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:48:42 +00:00
deploy
33a5376408 孕妈广场:话题统一用 #话题# 双井号样式(热门话题、话题头、话题胶囊、卡片话题行、首页话题标签)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:47:31 +00:00
deploy
f2b27f9b6a 孕妈广场:首页加逛广场入口、帖子返回落广场首页;参差瀑布流+图上压字;分类·话题胶囊层级;话题名与179篇帖子口语化重写
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 09:43:22 +00:00
deploy
5fc072fb50 孕妈广场配图不露人头:44 张有人脸/后脑勺/宝宝脸的换成物件场景图(只露手、孕肚、腿等身体的保留),12 张露下巴的裁掉头部,去掉视觉重复图;v26110204
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 07:38:22 +00:00
deploy
29e1f3a9a2 品牌露出 4 处默认显示(页底落款 / 专属福利「兜爸出品」/ 测一测「兜爸原创」/ 投稿卡「兜爸心选 · 官方征集」,?brand=0 可关);专题页底部加「兜爸心选 | 孕育知识整理」落款(共用模板 + 5 个自带页);v26110203
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 06:37:11 +00:00
deploy
1dd1456f16 孕妈广场按孕周 6 段出帖:新增 59 篇(孕早期/9-13周/14-20周/37周+),120 篇旧帖标题口语化、去负面;179 篇全部配图(Burst 真实照片为主);首页卡堆和广场页按孕周排(同段为主+穿插过来人,feed.js);隐藏评论时间与发帖日期;修「查看全部问题」点了没反应(openQA 变量先用后声明);品牌露出效果稿 ?brand=1;v26110202
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 06:32:19 +00:00
deploy
7e02da209b 其他妈妈也在搜按孕周分 6 段:首条固定生娃计算器 + 本段 4 条 + 通用 1 条;新增 50 个分段专题页(问题库共 100);全部问题页加「孕 N 周」筛选;v26110201
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 05:28:58 +00:00
deploy
be74d7cf35 首页广场:「全部」里翻卡时右上角分类滑块跟着当前卡的归属类跳
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:48:32 +00:00
deploy
0b72e9fed8 首页广场:「查看全部 50 个问题」改成一行居中小灰字
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:44:29 +00:00
deploy
a3dc7e9578 预览首页测一测默认改用第 4 版彩色卡
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:41:56 +00:00
deploy
ecbb8db15a 预览首页默认启用孕妈广场合并版(测一测第 1 版);测一测加第 4 版彩色卡(&qz=4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:34:40 +00:00
deploy
60ee41bb9d 首页广场 V6:测一测只留两个,挪到「其他妈妈也在搜」下面
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:22:25 +00:00
deploy
a9fb9c6421 首页广场 V6 测一测:上面两个主推 + 下面 3 个小列表;新测试 压力(yali)/饮食(yinshi)/待产准备(zhunbei)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:15:13 +00:00
deploy
c239567524 首页广场 V6「测一测」三版(&qz=1/2/3)+ 对比页 demo/gch/qz.html
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 03:46:49 +00:00
deploy
7198dc769e 首页广场合并版 V6:测一测改素色白卡、两块小标题统一、热搜列表去掉与测试重复的一条
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 02:14:53 +00:00
deploy
b627ed76fc 首页广场合并版 V6:照片文字加强 + 测一测两张卡;新测试「你家准爸爸是哪种队友」topic/duiyou
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 01:36:59 +00:00
deploy
85fcd96cdf 首页孕妈广场效果稿 V6:广场卡堆 + 其他妈妈也在搜合并成一块(?gcv=6),汇总页置顶
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 01:02:59 +00:00
deploy
68fa31eea9 首页孕妈广场模块五版效果稿:index.html 加 ?gcv=N 演示开关 + demo/gch 汇总与 v1~v5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 00:46:38 +00:00
deploy
228b06170f 孕妈广场五版效果稿演示页(demo/gc 汇总 + gc-v1~v5)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 23:59:31 +00:00
deploy
8012e9ced1 此刻标题行降权;首页广场分类字居中;生娃计算器去性别题加 4 题、给妈妈的话改轻提示;妊娠纹加成分含量;v26110127
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 23:48:14 +00:00
deploy
243b0f93a1 数据卡改一行横滑小卡;广场分类合并为 家庭婚姻/职场/经验;其他妈妈也在搜扩到 50 题并全部做成专题页(新增 26 页);v26110126
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 23:22:24 +00:00
deploy
175d15240a 首页孕妈广场第五版「广场地面」:话题气泡之字形错落、头像站在气泡下、虚线小路串起、可横滑;v26110125
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 23:06:10 +00:00
deploy
e961048616 首页孕期工具:工具宫格移到上面,记录数据卡移到下面;v26110124
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 22:54:18 +00:00
deploy
567d6b36cf 其他妈妈也在搜:剩余 18 个问题做成专题页(共用模板 topic/_shared/article.*,版式参照补剂专题);v26110123
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 20:27:27 +00:00
deploy
4ae16d1eb1 首页孕妈广场:横滑话题卡隔一张换成真实照片卡;v26110122
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 15:15:53 +00:00
deploy
fbffb9cbbd 孕妈广场:38 张占位照片由 AI 图换成真实照片(Burst 免费商用图库,来源见 img/SOURCES.txt);v26110121
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:56:11 +00:00
deploy
2121fae5fb 首页孕期工具:数据块改半透明白玻璃质感;「兜爸」水印再浅一档;v26110120
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:18:06 +00:00
deploy
d88b150376 首页孕期工具:背后「兜爸」水印加深一档,隐约可见;v26110119
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:14:53 +00:00
deploy
17a14f056b 首页数据块缩小一档;孕妈广场约 1/3 笔记改为照片封面(38 张);v26110118
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:57:19 +00:00
deploy
d25e390c9d 首页孕期工具:数据块(数胎动/体重/血压/血糖)底色加深一档;v26110117
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:19:37 +00:00
deploy
d76c212f89 孕妈广场投稿:写稿页(选话题/标题/正文/配图/草稿)、我的投稿、审核结果弹窗提醒、通过稿件以「精选投稿」展示;首页广场模块挂审核结果提示;接 box_app /plaza 接口;v26110116
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:20:45 +00:00
deploy
cc8cc3e98a 孕妈广场:每块 3 个热门,「全部」里家庭/婚姻/职场/母婴轮流排(首页 + 广场页);v26110115
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:42:16 +00:00
deploy
6172a780d3 孕妈广场第四版:按用户选题清单分 家庭/婚姻/职场/母婴 四块共 40 个话题,每题 3 篇 450 字以上占位文章;首页广场分类同步四块;v26110114
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:23:55 +00:00
deploy
8f1f7675ab 孕妈广场第三版:封面统一一种版式、按家庭/经验配色;分类改分段按钮;加投稿有奖横幅(被选中 ¥30 现金 + 500 兜豆)、热门话题、全部话题弹层;详情页加参与话题卡;v26110113
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:10:48 +00:00
deploy
7cd3702554 孕妈广场:正文扩写到 400~700 字;列表页加大号「全部/家庭关系/宝妈经验」分类;v26110112
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:00:44 +00:00
deploy
4125e82540 首页我的孕期工具右上角恢复「编辑」按钮 v26110111
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 07:45:45 +00:00
deploy
79ca6f6e80 首页工具图标下状态胶囊恢复各工具同色系配色 v26110110
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 07:30:47 +00:00
deploy
107e02a47e 首页此刻改2行轮播;新增孕妈广场(首页横滑话题卡+15话题瀑布流+详情点赞评论,占位内容)v26110109
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 06:16:52 +00:00
deploy
225fb21bf3 孕妈故事模块设计稿(静态,mock/story/,不接入首页)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 05:46:34 +00:00
deploy
e15daff46c 首页工具模块叠淡暖色背景;数据块提高不透明度 v26110108
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:58:31 +00:00
deploy
854e30eed2 首页工具区去白底卡、删标题栏全部/编辑(添加格常显作编辑入口);养娃账单表头删路线、家庭 v26110107
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:51:02 +00:00
deploy
05ef51bf41 首页:数据与图标合成一张卡去虚线;工具默认6个最多8个,满8隐藏添加格;编辑弹层加号居中;本周话题改为对未来宝宝说的话;其他妈妈也在搜标题去斜体 v26110106
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:39:44 +00:00
deploy
eece929571 首页数据区去掉彩色logo,改成一整块白底面板发丝线分格;图标状态胶囊统一暖灰 v26110105
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:29:04 +00:00
deploy
be8656a415 首页工具最多6个+添加格 v26110104
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:26:05 +00:00
deploy
4b474d755b 首页工具默认6个+末尾「添加」格点开编辑,最多7个 v26110103
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:08:51 +00:00
deploy
cb1201df42 首页:数据卡与编辑解耦(用过就显示,最多4张可展开);图标宫格由编辑决定最多8个,全部工具移到标题栏 v26110102
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 04:05:39 +00:00
deploy
c57546f9ba 首页:工具与孕期数据合成一个模块+用户自定义首页工具(排序/增删);其他妈妈也在搜加热搜榜样式 v26110101
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 03:35:12 +00:00
deploy
72131f98c6 生娃计算器:新增「保存账单图片」,canvas 画整张小票长图,长按保存
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:23:23 +00:00
deploy
b44fcb8021 测一测:结果页「复制给老公」改为「写给未来宝宝」,按类型生成一句话
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:22:23 +00:00
deploy
c1c9e4a165 生娃计算器 v5:大标题+路线编号、结果前不露金额、可选阶段、填收入对比、账单每段11~24项明细
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:14:21 +00:00
deploy
af249ab1c0 生娃计算器 v4:三条养娃路线+6问+18岁长账单小票+对妈妈说辛苦了收尾卡
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:38:00 +00:00
deploy
e8089ae3fa 生娃计算器一句话答案补充月嫂+托班区间;计算器/补剂页插画换成主色调
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 14:34:56 +00:00
deploy
5f419b840d 专题页 v3:加设计感+每页推荐工具(共用 _shared/tools.js);生娃计算器扩到15项+快速/详细估算;测一测改成妈妈类型卡+按类型推荐工具
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 14:29:47 +00:00
1655 changed files with 49255 additions and 1282 deletions

View File

@@ -101,6 +101,20 @@ nginx:`root /opt/app` + `Cache-Control: no-cache` + `etag on` —— 缓存靠
- ⚠️ 悄悄话后端(`models/mamaBoxWhisper.py`、`services/mama_box_whisper_serv.py`、`mama_box_router.py` 与 `models/__init__.py` 的改动)是 2026-10-02 **直接改在服务器 `/opt/app/box_app` 上的,没进 git**(当时的账号无 box_app 推送权限;改前备份在 `/opt/app/box_app_bak_202610021000`)。服务器下次 `git reset --hard` 前,必须由有权限的人先把这几个文件提交进仓库,否则接口会丢。
- 边界:**只限这张卡**。孕期盲盒的数字(已收集、本周开盒人数)一律真实;任何别处都不得引用这里的模拟数字,前端也不得在接口失败时自造数字兜底。
12b. **⚠️ 第 2 条的第二个登记例外:孕妈广场「测一测」的「N 人测过」(2026-11-02 起)**
- 内容:测一测列表、信息流测试卡、测试开始页显示的「N万人测过」和测一测头卡的「累计 N 万人次参与」,都是前端 `guangchang/ceshi/meta.js` 里 `gcTested(id)` 按测试 id 哈希出的模拟数(1.2万~6万起,好物配置 5 个 11-02 起调为 5万~13万起,每天约 +0.4%),不落库、不进任何报表。
- 决策人:产品负责人(用户本人),2026-11-02 拍板「人数用模拟数字就行,先帮我放上模拟数字」;已书面告知虚假宣传风险(《反不正当竞争法》第 8 条),并建议过改用真实统计。
- 期限:**最晚 2026-12-31** 复核;接真实统计后删掉 `gcTested` / `gcTestedText`,调用处改读接口。
- 边界:只限上述几处;测试结果页、分享图、其他应用不得引用这个数。
- 2026-11-02 扩展:首页「其他妈妈也在搜 → 全部问题」页每条的「N 人看过」(11-02 用户撤掉了「正在看」)(「此刻」总人数 × heat,同首页),以及专题页「相关推荐」的「N 人看过」,同属模拟数,同一期限复核。
12c. **⚠️ 第 2 条的第三个登记例外:孕妈广场帖子下的模拟评论与 1000 个模拟人设(2026-11-02 起)**
- 内容:`guangchang/cm.json`(179 篇占位帖子,每篇 22~26 条评论 + 作者回复 + 楼中楼,共约 4100 条)和其中 1000 个人设(昵称 + 头像 `guangchang/av/*.webp` 代码绘制 / 59 张 `assets/img/mom/` 写实照 + 阶段)。全是 AI 写的「假装有人说过的话」,不是真实用户发言,不落库、不进任何报表。
- 决策人:产品负责人(用户本人),2026-11-02 拍板「准备 1000 个头像和名字,每篇评论至少 20 条以上,也会有作者回复」;已书面告知虚假宣传风险(《反不正当竞争法》第 8 条),且比模拟数字更敏感。
- 期限:**最晚 2026-12-31** 复核;真实评论上线后,有真实评论的帖子要先撤掉模拟评论,不得混排冒充。
- 2026-11-02 扩展:104 个专题页底部「大家怎么说」的预置评论 `topic/_shared/cm/<slug>.json`(每页 10~14 条 + 楼中楼,共约 1200 条,人设取自同一批 1000 个),由 `topic/_shared/tools.js` 渲染;用户自己发的评论只存本机 `mmbox.tp.v1`,不上传。同一期限复核。
- 边界:只用于占位帖子的详情页评论区;真实投稿(`n.real`)一律不配模拟评论;这 1000 个人设不得出现在投稿审核、排行榜、通知等任何其他地方。
13. **跳其它 H5 应用 / 调第三方接口一律同源:只写相对路径 `/<slug>/`,不写域名**(2026-10-09 用户定)
- 背景:小程序 web-view 只放行业务域名 `mp.yizhezhe.com`,直连 `taidong.douba.top`(或任何 `*.douba.top`)会被拦;
首页直接 `fetch` 别的域名还会跨域。所有第三方 H5 都由 mp 前置机(8.145.39.61)nginx 反代过去,路径不变。

View File

@@ -32,14 +32,6 @@
"heat": 0.083
},
{
"q": "孕妈产后复工,职场维权指南",
"tag": "职场",
"a": "这几条是国家《女职工劳动保护特别规定》写明的:①孕期、产期、哺乳期,单位不能因为怀孕生育降低工资、辞退或单方解除劳动合同;②产假不少于 98 天(产前可休 15 天),难产增加 15 天,多胞胎每多一个增加 15 天,各省还有延长奖励假,以当地规定为准;③产检时间算劳动时间,不能扣工资;④怀孕 7 个月以上,单位不能延长工作时间或安排夜班,并应安排一定休息时间;⑤宝宝 1 岁内,每天有 1 小时哺乳时间。遇到不公平对待,先保留书面证据(通知、聊天记录、工资条),可以向当地劳动监察部门投诉或申请劳动仲裁。",
"href": "topic/zhichang/",
"badge": "新",
"heat": 0.041
},
{
"q": "妊娠纹,与体重管理",
"tag": "专题",
"href": "topic/wen/",
@@ -48,93 +40,905 @@
"heat": 0.069
},
{
"q": "孕妈产后复工,职场维权指南",
"tag": "职场",
"a": "这几条是国家《女职工劳动保护特别规定》写明的:①孕期、产期、哺乳期,单位不能因为怀孕生育降低工资、辞退或单方解除劳动合同;②产假不少于 98 天(产前可休 15 天),难产增加 15 天,多胞胎每多一个增加 15 天,各省还有延长奖励假,以当地规定为准;③产检时间算劳动时间,不能扣工资;④怀孕 7 个月以上,单位不能延长工作时间或安排夜班,并应安排一定休息时间;⑤宝宝 1 岁内,每天有 1 小时哺乳时间。遇到不公平对待,先保留书面证据(通知、聊天记录、工资条),可以向当地劳动监察部门投诉或申请劳动仲裁。",
"href": "topic/zhichang/",
"badge": "新",
"heat": 0.041
},
{
"q": "怀孕后什么时候去医院建档?",
"tag": "产检",
"a": "一般在孕 6~8 周做第一次 B 超确认宫内孕、看到胎心胎芽后,就可以着手准备建档,多数医院在孕 12 周左右正式建档,并同时做 NT 检查。热门医院床位紧张,有的需要提前预约,最好早点打电话或在医院公众号上查清楚流程。建档一般要带身份证、医保卡、母子健康手册(或社区开的建册证明)和之前的检查报告。"
"a": "一般在孕 6~8 周做第一次 B 超确认宫内孕、看到胎心胎芽后,就可以着手准备建档,多数医院在孕 12 周左右正式建档,并同时做 NT 检查。热门医院床位紧张,有的需要提前预约,最好早点打电话或在医院公众号上查清楚流程。建档一般要带身份证、医保卡、母子健康手册(或社区开的建册证明)和之前的检查报告。",
"href": "topic/jiandang/",
"st": [
1,
2
],
"heat": 0.064
},
{
"q": "唐筛、无创、羊穿,该怎么选?",
"tag": "产检",
"a": "三者都是查染色体问题,但准确度和风险不同。唐筛是抽血筛查,便宜无创伤,但准确度最低;无创 DNA 也是抽血,准确度明显高于唐筛,费用更高;羊水穿刺是诊断,结果最准,但属于有创操作,有很小的流产风险。一般没有高危因素的妈妈可以先做唐筛或无创;年龄偏大、筛查高风险、有家族史或 B 超发现异常的,医生会建议直接做羊穿。具体按产检医生的建议来。"
"a": "三者都是查染色体问题,但准确度和风险不同。唐筛是抽血筛查,便宜无创伤,但准确度最低;无创 DNA 也是抽血,准确度明显高于唐筛,费用更高;羊水穿刺是诊断,结果最准,但属于有创操作,有很小的流产风险。一般没有高危因素的妈妈可以先做唐筛或无创;年龄偏大、筛查高风险、有家族史或 B 超发现异常的,医生会建议直接做羊穿。具体按产检医生的建议来。",
"href": "topic/shaicha/",
"st": [
2,
3
],
"heat": 0.063
},
{
"q": "孕期体重长多少合适?",
"tag": "身体",
"a": "看孕前体重来定:孕前偏瘦的,整个孕期可以长得多一些;体重正常的,一般建议长 8~14kg 左右;偏胖或肥胖的要长得更少。孕早期变化不大,孕中晚期每周增长约 0.3~0.5kg 比较合适。长得太快容易出现妊娠期糖尿病、高血压、巨大儿,还更容易长妊娠纹;长得太少又可能影响宝宝发育。可以用首页的「孕期体重」每周记一次,看看自己在不在合理范围。"
"a": "看孕前体重来定:孕前偏瘦的,整个孕期可以长得多一些;体重正常的,一般建议长 8~14kg 左右;偏胖或肥胖的要长得更少。孕早期变化不大,孕中晚期每周增长约 0.3~0.5kg 比较合适。长得太快容易出现妊娠期糖尿病、高血压、巨大儿,还更容易长妊娠纹;长得太少又可能影响宝宝发育。可以用首页的「孕期体重」每周记一次,看看自己在不在合理范围。",
"href": "topic/tizhong/",
"heat": 0.04
},
{
"q": "孕期能喝咖啡、奶茶吗?",
"tag": "营养",
"a": "可以少量喝。孕期每天咖啡因建议不超过 200mg,大约是一杯中杯美式。要注意奶茶、浓茶、可乐、巧克力里也有咖啡因,要一起算。奶茶的问题更多在糖分高,喝多了体重和血糖都容易超标,想喝可以选小杯、少糖或无糖,一周偶尔一两次就好。"
"a": "可以少量喝。孕期每天咖啡因建议不超过 200mg,大约是一杯中杯美式。要注意奶茶、浓茶、可乐、巧克力里也有咖啡因,要一起算。奶茶的问题更多在糖分高,喝多了体重和血糖都容易超标,想喝可以选小杯、少糖或无糖,一周偶尔一两次就好。",
"href": "topic/kafei/",
"heat": 0.0392
},
{
"q": "怀孕了还能养猫、养狗吗?",
"tag": "生活",
"a": "大多数情况下可以继续养。养猫主要担心弓形虫:室内长期饲养、只吃猫粮、不外出的猫感染概率很低。孕期尽量让家人铲屎,自己要铲的话戴手套、铲完洗手,每天及时清理猫砂。不要喂生肉,自己也别吃没熟的肉,处理生肉后洗手。可以在孕前或孕早期查一下弓形虫抗体,心里更有底。狗狗要按时打疫苗驱虫,避免被抓伤咬伤。"
"a": "大多数情况下可以继续养。养猫主要担心弓形虫:室内长期饲养、只吃猫粮、不外出的猫感染概率很低。孕期尽量让家人铲屎,自己要铲的话戴手套、铲完洗手,每天及时清理猫砂。不要喂生肉,自己也别吃没熟的肉,处理生肉后洗手。可以在孕前或孕早期查一下弓形虫抗体,心里更有底。狗狗要按时打疫苗驱虫,避免被抓伤咬伤。",
"href": "topic/chongwu/",
"heat": 0.0384
},
{
"q": "孕期可以染发、烫发吗?",
"tag": "生活",
"a": "建议尽量避开,尤其是孕早期宝宝器官形成的关键阶段。染发烫发剂里的化学成分通过头皮吸收的量很少,目前没有确切证据说明会伤害宝宝,但出于谨慎,孕期能不做就不做。实在需要,等到孕中期后,选择通风好的店,挑选不接触头皮的挑染,缩短停留时间。剪发、普通洗护不受影响。"
"a": "建议尽量避开,尤其是孕早期宝宝器官形成的关键阶段。染发烫发剂里的化学成分通过头皮吸收的量很少,目前没有确切证据说明会伤害宝宝,但出于谨慎,孕期能不做就不做。实在需要,等到孕中期后,选择通风好的店,挑选不接触头皮的挑染,缩短停留时间。剪发、普通洗护不受影响。",
"href": "topic/ranfa/",
"heat": 0.0376
},
{
"q": "孕期能坐飞机、出远门吗?",
"tag": "生活",
"a": "孕中期(孕 14~27 周)身体最舒服,是出行最合适的时候。孕早期反应大、孕晚期有早产风险,尽量少长途出行。多数航空公司对孕 32 周以上的孕妈有限制,需要医生开具适宜乘机的证明,36 周以上一般不能乘机,具体看航司规定。出行时穿宽松衣服和舒适的鞋,每隔 1 小时起来活动一下,多喝水,带好产检资料。有出血、前置胎盘、早产迹象的要遵医嘱,不要出行。"
"a": "孕中期(孕 14~27 周)身体最舒服,是出行最合适的时候。孕早期反应大、孕晚期有早产风险,尽量少长途出行。多数航空公司对孕 32 周以上的孕妈有限制,需要医生开具适宜乘机的证明,36 周以上一般不能乘机,具体看航司规定。出行时穿宽松衣服和舒适的鞋,每隔 1 小时起来活动一下,多喝水,带好产检资料。有出血、前置胎盘、早产迹象的要遵医嘱,不要出行。",
"href": "topic/chuxing/",
"heat": 0.0368
},
{
"q": "孕期能运动吗?做什么运动好?",
"tag": "身体",
"a": "没有医生明确禁止的话,孕期适当运动对妈妈和宝宝都有好处,能控制体重、减少腰背痛、改善睡眠,也有助于顺产。推荐散步、游泳、孕妇瑜伽、固定单车等低冲击运动,每周累计 150 分钟左右,以运动时还能正常说话为度。避免跳跃、对抗性运动、容易摔倒的运动和仰卧太久。运动中出现出血、腹痛、头晕、胸闷、流液要马上停下并就医。"
"a": "没有医生明确禁止的话,孕期适当运动对妈妈和宝宝都有好处,能控制体重、减少腰背痛、改善睡眠,也有助于顺产。推荐散步、游泳、孕妇瑜伽、固定单车等低冲击运动,每周累计 150 分钟左右,以运动时还能正常说话为度。避免跳跃、对抗性运动、容易摔倒的运动和仰卧太久。运动中出现出血、腹痛、头晕、胸闷、流液要马上停下并就医。",
"href": "topic/yundong/",
"heat": 0.036
},
{
"q": "孕吐什么时候能结束?",
"tag": "身体",
"a": "孕吐一般在孕 6 周左右开始,孕 8~10 周最明显,大多数妈妈在孕 12~14 周后逐渐减轻。缓解小办法:少量多餐,别让胃空着;早上起床前先吃几块苏打饼干;避开油腻和气味重的食物;吃点姜味食物或酸味水果。如果吐得什么都吃不下、喝水也吐、尿很少、体重明显下降,可能是妊娠剧吐,要及时去医院补液治疗。"
"a": "孕吐一般在孕 6 周左右开始,孕 8~10 周最明显,大多数妈妈在孕 12~14 周后逐渐减轻。缓解小办法:少量多餐,别让胃空着;早上起床前先吃几块苏打饼干;避开油腻和气味重的食物;吃点姜味食物或酸味水果。如果吐得什么都吃不下、喝水也吐、尿很少、体重明显下降,可能是妊娠剧吐,要及时去医院补液治疗。",
"href": "topic/yuntu/",
"st": [
1,
2
],
"heat": 0.058
},
{
"q": "什么时候能感觉到胎动?",
"tag": "宝宝",
"a": "第一胎的妈妈一般在孕 18~20 周第一次感觉到胎动,二胎妈妈经验多,可能早到 16 周左右。最开始的胎动很轻,像小鱼吐泡泡或肚子里冒泡。孕 28 周以后要每天留意胎动,可以用首页的「数胎动」记录:如果胎动明显减少、比平时弱很多或突然特别频繁,要及时去医院。"
"a": "第一胎的妈妈一般在孕 18~20 周第一次感觉到胎动,二胎妈妈经验多,可能早到 16 周左右。最开始的胎动很轻,像小鱼吐泡泡或肚子里冒泡。孕 28 周以后要每天留意胎动,可以用首页的「数胎动」记录:如果胎动明显减少、比平时弱很多或突然特别频繁,要及时去医院。",
"href": "topic/taidong/",
"st": [
3
],
"heat": 0.066
},
{
"q": "顺产还是剖宫产,怎么选?",
"tag": "准备",
"a": "没有医学指征时,一般更推荐顺产:产后恢复快、住院时间短,宝宝经过产道挤压,对呼吸系统也有好处。剖宫产是解决难产和高危情况的重要手段,比如胎位不正、前置胎盘、胎儿窘迫、骨盆过小等,由医生评估决定。害怕疼的话,可以了解一下医院有没有无痛分娩(分娩镇痛)。具体分娩方式要和产检医生一起商量。"
"a": "没有医学指征时,一般更推荐顺产:产后恢复快、住院时间短,宝宝经过产道挤压,对呼吸系统也有好处。剖宫产是解决难产和高危情况的重要手段,比如胎位不正、前置胎盘、胎儿窘迫、骨盆过小等,由医生评估决定。害怕疼的话,可以了解一下医院有没有无痛分娩(分娩镇痛)。具体分娩方式要和产检医生一起商量。",
"href": "topic/fenmian/",
"st": [
5,
6
],
"heat": 0.057
},
{
"q": "待产包要准备些什么?",
"tag": "准备",
"a": "建议孕 32~35 周前准备好,放在门口方便拿。证件类:身份证、医保卡、母子健康手册、产检资料。妈妈用品:产褥垫、一次性内裤、哺乳内衣、防溢乳垫、吸管杯、拖鞋、洗漱用品、宽松保暖的衣服。宝宝用品:新生儿纸尿裤、包被、和尚服、口水巾、湿巾,以及出院穿的衣服。医院提供的物品不一样,提前问清楚可以少带很多。首页「待产清单」可以帮你逐项勾选。"
"a": "建议孕 32~35 周前准备好,放在门口方便拿。证件类:身份证、医保卡、母子健康手册、产检资料。妈妈用品:产褥垫、一次性内裤、哺乳内衣、防溢乳垫、吸管杯、拖鞋、洗漱用品、宽松保暖的衣服。宝宝用品:新生儿纸尿裤、包被、和尚服、口水巾、湿巾,以及出院穿的衣服。医院提供的物品不一样,提前问清楚可以少带很多。首页「待产清单」可以帮你逐项勾选。",
"href": "topic/daichanbao/",
"st": [
5
],
"heat": 0.06
},
{
"q": "生育津贴怎么领?能领多少?",
"tag": "花钱",
"a": "生育津贴由生育保险支付,一般条件是:产前单位为你连续缴纳生育保险(职工医保)满一定月数,具体月数各地不同。金额通常是:单位上年度职工月平均工资 ÷ 30 × 产假天数。多数地方由单位统一申请,也有的可以个人在当地医保 App 或线上服务平台申请,需要准备出生医学证明、住院病历等材料。具体条件和流程以当地医保部门为准,可以提前问单位人事。"
"a": "生育津贴由生育保险支付,一般条件是:产前单位为你连续缴纳生育保险(职工医保)满一定月数,具体月数各地不同。金额通常是:单位上年度职工月平均工资 ÷ 30 × 产假天数。多数地方由单位统一申请,也有的可以个人在当地医保 App 或线上服务平台申请,需要准备出生医学证明、住院病历等材料。具体条件和流程以当地医保部门为准,可以提前问单位人事。",
"href": "topic/jintie/",
"heat": 0.0352
},
{
"q": "孕期失眠、睡不好怎么办?",
"tag": "身体",
"a": "孕期睡不好很常见,原因有尿频、腿抽筋、胃灼热、肚子大翻身难,还有焦虑。可以试试:睡前 2 小时少喝水;晚饭别太饱,吃完别马上躺下;左侧卧,在两腿之间、肚子下面垫个孕妇枕;白天适当运动,但睡前别剧烈运动;固定作息,睡前少看手机。腿抽筋的话多晒太阳、吃奶制品,产检时问问医生需不需要补钙。长期严重失眠或情绪低落,要告诉医生。"
"a": "孕期睡不好很常见,原因有尿频、腿抽筋、胃灼热、肚子大翻身难,还有焦虑。可以试试:睡前 2 小时少喝水;晚饭别太饱,吃完别马上躺下;左侧卧,在两腿之间、肚子下面垫个孕妇枕;白天适当运动,但睡前别剧烈运动;固定作息,睡前少看手机。腿抽筋的话多晒太阳、吃奶制品,产检时问问医生需不需要补钙。长期严重失眠或情绪低落,要告诉医生。",
"href": "topic/shimian/",
"heat": 0.0344
},
{
"q": "孕期便秘怎么缓解?",
"tag": "身体",
"a": "孕激素让肠道蠕动变慢,加上子宫压迫和补铁,孕期便秘很常见。先从生活入手:每天喝够 1500~1700ml 水;多吃蔬菜、水果、粗杂粮、薯类,增加膳食纤维;每天适当散步;养成定时排便的习惯,不要憋。不要自己乱用泻药或开塞露,如果几天都排不出、肚子胀痛或便中带血,要问医生,用孕期安全的药物。"
"a": "孕激素让肠道蠕动变慢,加上子宫压迫和补铁,孕期便秘很常见。先从生活入手:每天喝够 1500~1700ml 水;多吃蔬菜、水果、粗杂粮、薯类,增加膳食纤维;每天适当散步;养成定时排便的习惯,不要憋。不要自己乱用泻药或开塞露,如果几天都排不出、肚子胀痛或便中带血,要问医生,用孕期安全的药物。",
"href": "topic/bianmi/",
"heat": 0.0336
},
{
"q": "孕期可以同房吗?",
"tag": "生活",
"a": "孕期一切正常的话,可以有温和的性生活,一般建议避开孕早期前 3 个月和孕晚期最后 1 个月。注意动作轻柔、避免压迫腹部,选择舒适的体位,最好使用避孕套减少感染。如果有阴道出血、前置胎盘、先兆流产或早产迹象、宫颈机能不全、胎膜早破等情况,要禁止同房,听医生的。同房后出现腹痛、出血、流液要及时就医。"
"a": "孕期一切正常的话,可以有温和的性生活,一般建议避开孕早期前 3 个月和孕晚期最后 1 个月。注意动作轻柔、避免压迫腹部,选择舒适的体位,最好使用避孕套减少感染。如果有阴道出血、前置胎盘、先兆流产或早产迹象、宫颈机能不全、胎膜早破等情况,要禁止同房,听医生的。同房后出现腹痛、出血、流液要及时就医。",
"href": "topic/tongfang/",
"heat": 0.0328
},
{
"q": "孕期情绪低落、焦虑怎么办?",
"tag": "心情",
"a": "孕期激素变化大,再加上身体不舒服和对未来的担心,情绪起伏很正常。试着把担心说出来,和老公、家人或其他孕妈聊聊;每天留点时间做喜欢的事,散步、听音乐、晒太阳;少在网上搜吓人的个例;规律作息,适当运动。如果连续两周以上情绪低落、对什么都提不起兴趣、睡不着或总想哭,甚至有伤害自己的念头,要及时告诉产检医生,寻求专业帮助。"
"a": "孕期激素变化大,再加上身体不舒服和对未来的担心,情绪起伏很正常。试着把担心说出来,和老公、家人或其他孕妈聊聊;每天留点时间做喜欢的事,散步、听音乐、晒太阳;少在网上搜吓人的个例;规律作息,适当运动。如果连续两周以上情绪低落、对什么都提不起兴趣、睡不着或总想哭,甚至有伤害自己的念头,要及时告诉产检医生,寻求专业帮助。",
"href": "topic/qingxu/",
"heat": 0.032
},
{
"q": "准爸爸孕期能帮上什么忙?",
"tag": "心情",
"a": "准爸爸的陪伴对孕妈很重要。可以做这些:尽量陪着去产检,一起了解宝宝的情况;承担家务,特别是铲猫砂、搬重物、做饭;晚上帮她按摩腿脚、垫好孕妇枕;和她一起学分娩和新生儿护理知识,准备待产包;每天和宝宝说说话、讲故事;多听她倾诉,别说「别人都这样」。孕晚期保持电话畅通,提前规划好去医院的路线。"
"a": "准爸爸的陪伴对孕妈很重要。可以做这些:尽量陪着去产检,一起了解宝宝的情况;承担家务,特别是铲猫砂、搬重物、做饭;晚上帮她按摩腿脚、垫好孕妇枕;和她一起学分娩和新生儿护理知识,准备待产包;每天和宝宝说说话、讲故事;多听她倾诉,别说「别人都这样」。孕晚期保持电话畅通,提前规划好去医院的路线。",
"href": "topic/zhunbaba/",
"heat": 0.0312
},
{
"q": "NT 检查查什么?要注意什么?",
"tag": "产检",
"a": "NT 是孕 11~13+6 周做的一次 B 超,测量宝宝颈后透明层的厚度,用来早期筛查唐氏综合征等染色体问题和部分心脏等结构异常,可联合早期血清筛查评估。它是筛查不是诊断:结果在正常范围也不能排除所有问题,后面的唐筛或无创 DNA、20~24 周大排畸照常做;结果偏厚也不代表宝宝一定有问题,医生会建议进一步检查。检查不用空腹,穿宽松衣服,窗口期短要提前预约。",
"href": "topic/nt/",
"st": [
2
],
"heat": 0.065
},
{
"q": "糖耐怎么做?没过怎么办?",
"tag": "产检",
"a": "糖耐(75g 口服葡萄糖耐量试验)一般在孕 24~28 周做:前 3 天正常吃饭,空腹至少 8 小时,先抽空腹血,再喝 75g 葡萄糖水,1 小时、2 小时各抽一次。标准是空腹低于 5.1、1 小时低于 10.0、2 小时低于 8.5mmol/L,任一项达到或超过就诊断为妊娠期糖尿病。没过别慌:少量多餐、饭后散步、自测血糖,控不住再在医生指导下用药。产后 4~12 周要复查糖耐。",
"href": "topic/tangnai/",
"st": [
4
],
"heat": 0.064
},
{
"q": "大排畸什么时候做?能看出什么?",
"tag": "产检",
"a": "大排畸就是胎儿系统超声,一般在孕 20~24 周做,这时宝宝器官基本长好、羊水多,最容易看清。不用空腹,一般也不用憋尿。它主要查宝宝身体结构:头颅、脊柱、心脏、腹壁、内脏、面部和四肢,重点排除无脑儿、严重脊柱裂、单腔心等严重畸形,同时看胎盘、羊水和脐带。它看不出染色体问题,也查不了听力、视力和智力,不能代替唐筛或无创。宝宝体位不好没看全很常见,按医生安排复查即可。",
"href": "topic/paiji/",
"st": [
4
],
"heat": 0.066
},
{
"q": "胎心监护怎么做?多久做一次?",
"tag": "产检",
"a": "胎心监护(NST)是孕晚期常规检查:半躺着,肚子上绑两个探头,记录宝宝心跳和宫缩,每次约 20 分钟,宝宝睡着可延长到 40 分钟。一般孕妈 37 周起每周做 1 次,34 周起医生可能按情况安排;有妊娠期糖尿病、高血压、胎动减少等情况的,常从 32~34 周开始,频率听医生的。做之前吃点东西、上个厕所。「无反应型」不等于有问题,医生会延长或复查。满 41 周要住院评估。",
"href": "topic/taixin/",
"st": [
5,
6
],
"heat": 0.052
},
{
"q": "孕期腿抽筋怎么办?",
"tag": "身体",
"a": "孕期腿抽筋多见于孕中晚期、夜里,和腿部疲劳、受凉、血液回流慢有关,缺钙只是可能原因之一。抽筋时把腿伸直,脚尖往自己方向勾,按揉小腿肚,缓过来后热敷几分钟。平时睡前拉伸小腿、温水泡脚,夜里给小腿保暖,别久站久坐;每天喝奶 300~500g,加豆腐、深绿叶菜,孕中晚期钙需要约 1000mg/天。要不要额外补钙、补镁听医生的。如果一侧小腿持续疼痛、红肿发热,要尽快就医排除下肢静脉血栓。",
"href": "topic/choujin/",
"st": [
4,
5
],
"heat": 0.05
},
{
"q": "孕期水肿正常吗?怎么消?",
"tag": "身体",
"a": "孕中晚期脚踝、小腿水肿很常见,多是子宫压迫下肢静脉、体内水分增多引起的,特点是久站久坐后加重、傍晚明显、睡一夜能消退,一般不用治疗。缓解办法:别久站久坐,每小时起来活动一下;休息时把腿垫高,睡觉多左侧卧;清淡饮食,盐每天不超过 5g,但水照常喝,不要靠少喝水消肿。如果脸和手突然肿、休息后不消、一周体重涨超过 1kg,或伴头痛、眼花、血压升高,或一条腿肿痛,要及时就医。",
"href": "topic/shuizhong/",
"st": [
5
],
"heat": 0.049
},
{
"q": "孕期贫血怎么办?",
"tag": "身体",
"a": "孕期血红蛋白低于 110g/L 就算贫血,最常见的是缺铁性贫血。血红蛋白正常但铁蛋白低于 30μg/L,也说明铁储备快用完了。日常孕中晚期每天多吃 20~50g 红肉,每周 1~2 次动物血或肝,搭配维 C 果蔬;浓茶、咖啡和钙别和补铁一起吃,红枣菠菜补不上来。查出贫血要在医生指导下补铁,定期复查,血红蛋白恢复后也别马上停,补多久听医生的。",
"href": "topic/pinxue/",
"st": [
3,
4
],
"heat": 0.047
},
{
"q": "孕期腰酸背痛怎么缓解?",
"tag": "身体",
"a": "孕期腰酸背痛很常见,多半是肚子变大、重心前移、韧带变松和体重增加引起的,孕中晚期最明显。缓解先从姿势入手:别久坐久站,每 30~60 分钟换个姿势;坐时腰后垫靠枕;睡觉侧卧、两膝夹枕;拿东西先蹲下;穿低跟软底鞋。每天活动 30 分钟,散步、游泳、孕妇瑜伽都可以,再加几组骨盆摇摆、猫式伸展,腰背温热敷也有帮助。止痛药要在医生指导下用。若腰酸伴规律腹紧、出血流水、发热尿痛或腿麻无力,要及时就医。",
"href": "topic/yaotong/",
"heat": 0.0304
},
{
"q": "妊娠期糖尿病要紧吗?怎么控糖?",
"tag": "身体",
"a": "妊娠期糖尿病很常见,控制好了,大多数母婴都能平安;不控制会增加巨大儿、子痫前期等风险。孕 24~28 周做 75g 糖耐量,空腹、1 小时、2 小时达到 5.1、10.0、8.5mmol/L 任一项即诊断。控糖目标:空腹 <5.3,餐后 1 小时 <7.8 或 2 小时 <6.7mmol/L。先靠少食多餐、粗细搭配、餐后散步 30 分钟;不达标再在医生指导下用药。产后 4~12 周复查糖耐量。",
"href": "topic/rentangbing/",
"st": [
4,
5
],
"heat": 0.055
},
{
"q": "孕期血压高怎么办?",
"tag": "身体",
"a": "孕期同一只手臂两次测得收缩压≥140 或舒张压≥90mmHg 就算血压高,要尽快告诉医生;达到 160/110,或出现持续头痛、眼花、上腹痛、突然水肿、胎动减少,要马上去医院。在家测量前静坐 5 分钟,坐好、手臂和心脏齐平,连测两次取平均,固定时间记录,产检时给医生看。日常每天盐不超过 5g、多休息。降压药吃不吃、吃多少都听医生的,别自己停药或换药;产后 42 天也要复查血压。",
"href": "topic/gaoxueya/",
"st": [
4,
5
],
"heat": 0.045
},
{
"q": "孕期白带增多正常吗?",
"tag": "身体",
"a": "怀孕后雌激素升高、阴道和宫颈分泌增多,白带变多很常见,正常的白带是乳白色或透明、稀薄、没有明显异味,外阴也不痒。如果白带像豆腐渣、发痒,或灰白稀薄有鱼腥味,或黄绿色起泡沫,可能是阴道炎;带血丝,或持续流出清水样液体,要警惕出血或破水,及时就医。日常穿透气的棉质内裤、每天更换,用温水清洗外阴即可,不要冲洗阴道,也不要自己买药用,孕期用药要在医生指导下进行。",
"href": "topic/baidai/",
"heat": 0.0296
},
{
"q": "孕期感冒发烧能吃药吗?",
"tag": "身体",
"a": "孕期普通感冒多数靠休息就能好:多喝温水、睡够、吃清淡,鼻塞可用生理盐水洗鼻,嗓子痛用淡盐水漱口,一周左右会好转。别自己买复方感冒药,别捂汗、试偏方。发烧先物理降温(温水擦身、少穿),体温到 38℃以上或烧不退就去医院,退烧药在医生指导下用,比硬扛更安全。突然高烧、浑身酸痛可能是流感,孕妈容易变重,要尽早就医。流感疫苗孕期任何阶段都能打。已经吃过药的,带上药盒问医生。",
"href": "topic/ganmao/",
"heat": 0.0288
},
{
"q": "孕期水果吃多少?哪些要少吃?",
"tag": "营养",
"a": "孕期水果每天 200~350g 左右就够,大约 1~2 个拳头大:孕早期和孕中期 200~300g,孕晚期可到 350g。最好在两餐之间整个吃,比饭后一大盘血糖更平稳。果汁不能代替水果,果干、蜜饯糖分浓缩要少吃;荔枝、龙眼、榴莲、葡萄、芒果这类很甜的可以吃,但量要算进当天总量里。腐烂或切开久放的别吃。血糖偏高或确诊妊娠期糖尿病的,吃多少听医生或营养科的。",
"href": "topic/shuiguo/",
"heat": 0.028
},
{
"q": "孕期能吃螃蟹、海鲜吗?",
"tag": "营养",
"a": "能吃。螃蟹、虾、贝类和鱼都是优质蛋白,深海鱼还含 DHA,「螃蟹寒凉会流产」没有科学依据。关键是新鲜、熟透:死蟹不吃,蟹要蒸到肉全熟、蟹黄凝固,贝类要煮到开口后再多煮几分钟。生鱼片、醉蟹醉虾、生蚝刺身这类生的或半生的别吃,容易感染寄生虫和细菌。鱼每周吃 2~3 次,优先三文鱼、鳕鱼、沙丁鱼等,鲨鱼、旗鱼、大眼金枪鱼这类大型鱼汞多,少吃。对海鲜过敏的别吃。",
"href": "topic/haixian/",
"heat": 0.0272
},
{
"q": "产假有多少天?怎么休更合适?",
"tag": "职场",
"a": "按国家《女职工劳动保护特别规定》,生育产假 98 天,其中产前可以休 15 天;难产增加 15 天,多胞胎每多一个宝宝增加 15 天;怀孕未满 4 个月流产休 15 天,满 4 个月流产休 42 天。各地在此基础上还有延长,天数和节假日怎么算以当地规定为准。孕期产检时间算劳动时间,7 个月以上不加班、不上夜班。建议先问清当地政策和生育保险,37 周前交接好工作,产后假尽量休足。",
"href": "topic/chanjia/",
"st": [
5
],
"heat": 0.05
},
{
"q": "孕期要穿防辐射服吗?手机电脑有影响吗?",
"tag": "生活",
"a": "孕期不需要穿防辐射服。手机、电脑、电视、微波炉、Wi-Fi 等日常电器产生的是非电离辐射,能量很低,在国家标准限值内正常使用,目前没有证据表明会伤害胎儿,防辐射服也起不到额外保护作用。真正要留心的是久坐久看屏幕带来的眼睛疲劳、腰背酸痛、睡眠变差,每用 1 小时起来活动一下,睡前少刷手机。需要拍 X 光、做 CT 等检查时,提前告诉医生自己怀孕了,由医生评估要不要做、怎么防护。",
"href": "topic/fushe/",
"heat": 0.0264
},
{
"q": "孕期能开空调、用电热毯吗?",
"tag": "生活",
"a": "孕期空调和电热毯都能用,关键是别过冷过热。空调调到 26℃左右,出风口别对着人吹,出汗后先擦干再进空调房,隔几小时开窗通风,入夏前清洗滤网,空调房干燥要多喝水。电热毯产生的低频电磁场目前没有可靠证据会伤害胎儿,要防的是过热和烫伤:睡前预热、上床关掉或调最低档,别整夜开。热水袋、暖宝宝隔布用,别贴肚子。桑拿、温泉和长时间热水泡澡会让体温升高,孕期尤其孕早期要避开;燃气炭火取暖一定要通风。",
"href": "topic/kongtiao/",
"heat": 0.0256
},
{
"q": "孕期护肤品、化妆品怎么选?",
"tag": "生活",
"a": "孕期护肤做减法:温和清洁、保湿、防晒照常做,甘油、透明质酸、神经酰胺这类保湿成分都能用;防晒先靠帽子、伞等遮挡。要停的是维 A 酸、视黄醇等维 A 酸类和氢醌,高浓度刷酸、激光、注射等医美也等产后。淡妆可以,当天卸干净;染烫和美甲尽量少做,避开孕早期、选通风处。挑产品看成分表,不必追「孕妇专用」,新品先小范围试。手心脚心痒得厉害要尽快就医,查肝功能和胆汁酸。",
"href": "topic/hufu/",
"heat": 0.0248
},
{
"q": "孕期还能开车吗?",
"tag": "生活",
"a": "身体舒服、没有医生特别交代的话,孕期可以开车。关键是系对安全带:肩带从两乳之间斜过、贴着肚子侧边,腰带压在肚子下方、贴住胯骨,别勒在肚子上;座椅往后调,胸口离方向盘保持 25cm 左右,安全气囊别关。孕早期犯困、孕吐时少开;孕晚期肚子顶到方向盘、反应变慢就别开;有宫缩、破水去医院时千万别自己开。每开 1~2 小时停下来走走。哪怕是轻微碰撞,也要去医院检查。",
"href": "topic/kaiche/",
"heat": 0.024
},
{
"q": "孕期能泡澡、泡温泉吗?",
"tag": "生活",
"a": "孕期不建议泡温泉、蒸桑拿、汗蒸:水温常在 40℃ 上下,体温升高快,孕早期长时间体温升高可能增加胎儿神经管缺陷风险,孕中晚期还容易血压下降、头晕摔倒,公共水质也难保证。日常以温水淋浴为主,水温温热不烫,15 分钟内洗完;地面放防滑垫,开点门或排风,别锁门洗太久。家里泡澡要谨慎,孕晚期、破水、阴道出血、发烧时别泡,想泡先问产检医生。",
"href": "topic/paozao/",
"heat": 0.0232
},
{
"q": "胎教有用吗?怎么做?",
"tag": "宝宝",
"a": "目前没有可靠证据说明胎教能让宝宝更聪明,但它并非没用:宝宝大约孕 24 周前后能听到声音,常听到的妈妈声音出生后更熟悉;更重要的是让妈妈放松、让爸爸早点参与,这对孕期和亲子关系都有好处。做法很简单:每天找个安静时段和宝宝说说话、读段故事,听自己喜欢的舒缓音乐,音量像平常说话就好,不要把耳机贴在肚子上;孕中晚期可以轻轻抚摸肚子回应胎动。有先兆早产、前置胎盘、宫缩频繁等情况时,抚摸前先问医生。",
"href": "topic/taijiao/",
"heat": 0.0224
},
{
"q": "胎位不正怎么办?",
"tag": "宝宝",
"a": "头朝下才算胎位正,臀位、横位、斜位都算不正。孕 30 周前宝宝空间大、翻身频繁,多数会自己转正,不用急。30~36 周按时产检复查;膝胸卧位、艾灸等方法效果证据不足,要做先问医生,千万别自己推肚子。到 36~37 周仍是臀位,医生会评估能否做外倒转。足月仍臀位,多数选择剖宫产,少数条件合适的可试产;横位必须剖宫产。臀位一旦破水,立即平躺、垫高臀部,尽快去医院。",
"href": "topic/taiwei/",
"st": [
5
],
"heat": 0.056
},
{
"q": "B 超说宝宝偏大或偏小,怎么办?",
"tag": "宝宝",
"a": "B 超说宝宝偏大或偏小先别慌。单项数值差一两周很常见,和父母体型遗传有关;B 超估重本身也有约 10%~15% 的误差。真正要关注的是估重或腹围低于同孕周第 10 百分位(偏小),或高于第 90 百分位(偏大)。先请医生用孕早期 B 超核对孕周,再间隔 2 周以上复查看增长趋势。偏小一般查脐血流、羊水和血压,偏大查血糖和体重增长。别拼命大补也别节食,每天数胎动,胎动明显减少要尽快就医。",
"href": "topic/daxiao/",
"st": [
4,
5
],
"heat": 0.051
},
{
"q": "到了预产期还没动静怎么办?",
"tag": "准备",
"a": "别着急。预产期只是按 40 周推算的日子,孕 37 周到 41 周 6 天出生都算足月,正好在预产期当天生的是少数。过了预产期要按医生安排加密产检,做胎心监护、B 超看羊水,每天数胎动。一般满 41 周就要住院,由医生评估宫颈并引产,别拖到 42 周(过期妊娠)。等待期间照常散步、吃好睡好,别自己试催产偏方。出现规律宫缩、破水、见红量多或胎动减少,马上去医院。",
"href": "topic/guoqi/",
"st": [
6
],
"heat": 0.058
},
{
"q": "临产有哪些信号?什么时候去医院?",
"tag": "准备",
"a": "临产有三个信号:见红、破水、规律宫缩。见红多是少量血丝,常在 1~2 天内临产,可以在家观察,但出血像月经一样多或鲜红要马上去医院。破水不管有没有宫缩都要立刻出发,垫上护垫尽量躺着去。宫缩不规律、休息后缓解多是假宫缩;规律且越来越密、每次 30 秒以上才是真的,头胎约 5 分钟一次就出发,二胎及以上一规律就去。胎动明显减少、剧烈腹痛也别等。",
"href": "topic/linchan/",
"st": [
6
],
"heat": 0.067
},
{
"q": "月子怎么坐?要注意什么?",
"tag": "准备",
"a": "“月子”医学上叫产褥期,约 6 周。老规矩很多不用守:可以洗澡(淋浴为主,剖宫产等伤口愈合)、刷牙洗头,房间常开窗通风,只是别对着风口吹,衣被不捂。尽早下床活动,能减少血栓、促进恢复。吃得多样不过量,比孕前每天多吃一些鱼禽蛋瘦肉,奶类喝到 400~500ml,汤要撇油。恶露一般 4~6 周干净。产后 42 天母婴一起去医院复查。出血多、发热、伤口红肿、情绪持续低落超过 2 周,要及时就医。",
"href": "topic/yuezi/",
"st": [
5,
6
],
"heat": 0.054
},
{
"q": "验孕两道杠,接下来做什么?",
"tag": "产检",
"a": "先接着吃叶酸、停掉烟酒,停经 6~8 周去医院做 B 超确认是宫内孕。",
"href": "topic/yanyun/",
"st": [
1
],
"heat": 0.062,
"badge": "热"
},
{
"q": "HCG、孕酮偏低要紧吗?",
"tag": "产检",
"a": "单次数值说明不了好坏:HCG 主要看翻倍趋势,最后以 B 超为准;孕酮单次偏低多数不用慌。",
"href": "topic/hcg/",
"st": [
1
],
"heat": 0.058
},
{
"q": "孕早期见红是要流产吗?",
"tag": "身体",
"a": "孕早期见红很常见,不少人后来都顺利;但量多、伴腹痛要当天就医。",
"href": "topic/jianhong/",
"st": [
1
],
"heat": 0.054
},
{
"q": "什么时候能看到胎心胎芽?",
"tag": "宝宝",
"a": "按末次月经算,阴超一般孕 6~7 周能看到胎芽胎心;没看到先别慌,1~2 周后复查。",
"href": "topic/taiya/",
"st": [
1
],
"heat": 0.05,
"badge": "新"
},
{
"q": "不知道怀孕时吃了药、喝了酒怎么办?",
"tag": "身体",
"a": "多数情况影响很小,从现在起停掉酒、用药先问医生;别自己决定不要宝宝,带上药名去问产科。",
"href": "topic/chiyao/",
"st": [
1
],
"heat": 0.046
},
{
"q": "宫外孕有什么信号?",
"tag": "身体",
"a": "常见是停经后少量出血 + 一侧下腹痛;B 超确认宫内孕之前,有这些信号要尽快去医院。",
"href": "topic/gongwai/",
"st": [
1
],
"heat": 0.042
},
{
"q": "预产期怎么算?",
"tag": "准备",
"a": "末次月经第一天加 280 天;月经不规律或试管的,以早孕 B 超或移植日校正。",
"href": "topic/yuchanqi/",
"st": [
1
],
"heat": 0.038
},
{
"q": "尿频、乳房胀痛正常吗?",
"tag": "身体",
"a": "很正常,是激素和子宫变大引起的;但尿痛、尿血、发烧就要看医生了。",
"href": "topic/niaopin/",
"st": [
1
],
"heat": 0.034
},
{
"q": "什么时候告诉领导和同事?",
"tag": "职场",
"a": "多数人在孕 12 周左右、胎心稳定后说;岗位有辐射、化学品、重体力或夜班的要尽早说。",
"href": "topic/gaozhi/",
"st": [
1
],
"heat": 0.03
},
{
"q": "建档要带什么、查什么?",
"tag": "产检",
"a": "带好身份证、医保卡和早孕 B 超单,空腹去;建档当天主要是抽血、验尿、量血压体重,再约好下次产检。",
"href": "topic/jiandangqd/",
"st": [
2
],
"heat": 0.062,
"badge": "热"
},
{
"q": "第一次产检抽血查什么?",
"tag": "产检",
"a": "主要查血常规、血型、血糖、肝肾功能和乙肝、梅毒、艾滋筛查,记得空腹去。",
"href": "topic/chouxue/",
"st": [
2
],
"heat": 0.058
},
{
"q": "孕吐吃不下,宝宝会缺营养吗?",
"tag": "营养",
"a": "一般不会:孕早期宝宝很小,需要的能量不比孕前多;守住叶酸、水和主食这三样就够了。",
"href": "topic/tuyy/",
"st": [
2
],
"heat": 0.054
},
{
"q": "早孕反应突然消失要紧吗?",
"tag": "身体",
"a": "大多数不要紧:反应本来就时轻时重,10~12 周后会自然减轻;但如果伴出血、腹痛,或心里放不下,就去做个 B 超。",
"href": "topic/fanying/",
"st": [
2
],
"heat": 0.05,
"badge": "新"
},
{
"q": "孕早期肚子隐隐痛正常吗?",
"tag": "身体",
"a": "轻微、一阵一阵、像来月经前那样的隐痛多半正常;越来越痛、一侧剧痛或伴出血要马上去医院。",
"href": "topic/futong/",
"st": [
2
],
"heat": 0.046
},
{
"q": "孕早期哪些东西不能吃?",
"tag": "营养",
"a": "真正要躲的不多:酒一口别碰,生的、没熟透的肉蛋海鲜和没消毒的奶不吃,咖啡、大鱼、动物肝控制量。",
"href": "topic/jikou/",
"st": [
2
],
"heat": 0.042
},
{
"q": "孕期能打流感疫苗吗?",
"tag": "产检",
"a": "能,而且推荐:孕妇是流感重症高风险人群,孕期任何阶段都能打灭活流感疫苗,最好赶在流感季前。",
"href": "topic/yimiao/",
"st": [
2
],
"heat": 0.038
},
{
"q": "怀了双胞胎要注意什么?",
"tag": "宝宝",
"a": "先在孕早期做 B 超分清绒毛膜性,它决定产检多密;双胎的早产、贫血、妊高症风险都更高,要按时产检。",
"href": "topic/shuangtai/",
"st": [
2
],
"heat": 0.034
},
{
"q": "肚子什么时候开始显怀?",
"tag": "身体",
"a": "头胎多在孕 16~20 周慢慢看出来,二胎、偏瘦的会早一些,早晚都正常。",
"href": "topic/xianhuai/",
"st": [
3
],
"heat": 0.062,
"badge": "热"
},
{
"q": "唐筛高风险怎么办?",
"tag": "产检",
"a": "高风险只说明需要进一步查,不是确诊;尽快找医生做遗传咨询,按建议选无创 DNA 或羊水穿刺。",
"href": "topic/tanggao/",
"st": [
3
],
"heat": 0.058
},
{
"q": "孕中期要开始补钙补铁了吗?",
"tag": "营养",
"a": "该重视起来了:钙先靠每天 300~500g 奶,喝不够再补钙片;铁先查血,缺了按医嘱补。",
"href": "topic/bugai/",
"st": [
3
],
"heat": 0.054
},
{
"q": "胃口变好了,怎么吃才不长太快?",
"tag": "营养",
"a": "孕中期每天只比孕前多约 250 千卡,差不多一杯奶加一个蛋;吃够蛋白、主食粗细搭配,每周称一次体重。",
"href": "topic/weikou/",
"st": [
3
],
"heat": 0.05,
"badge": "新"
},
{
"q": "孕期牙疼、牙龈出血能看牙吗?",
"tag": "身体",
"a": "能看,孕期看牙是安全的,孕中期最适合治疗;牙疼得厉害、脸肿发烧别硬扛,任何孕周都要及时看。",
"href": "topic/yatong/",
"st": [
3
],
"heat": 0.046
},
{
"q": "孕期皮肤变黑、长斑正常吗?",
"tag": "身体",
"a": "很常见,是激素让色素变多了;多数产后几个月慢慢变淡,现在做好防晒最管用。",
"href": "topic/zhangban/",
"st": [
3
],
"heat": 0.042
},
{
"q": "孕期头晕、心慌怎么办?",
"tag": "身体",
"a": "多数和血压偏低、低血糖或贫血有关,先坐下或侧躺缓一缓;晕倒、胸痛、喘不上气要马上就医。",
"href": "topic/touyun/",
"st": [
3
],
"heat": 0.038
},
{
"q": "孕妇装、孕妇内衣什么时候买?",
"tag": "准备",
"a": "内衣胸围变紧就换,常在孕 3~4 个月;孕妇装显怀了再买,一般孕 4~5 个月;哺乳内衣孕晚期再备。",
"href": "topic/yunfu/",
"st": [
3
],
"heat": 0.034
},
{
"q": "四维彩超有必要做吗?",
"tag": "产检",
"a": "真正必做的是 20~24 周的系统超声(大排畸);四维只是多了立体画面,不做也不少查。",
"href": "topic/siwei/",
"st": [
4
],
"heat": 0.062,
"badge": "热"
},
{
"q": "胎动多少算正常?怎么数?",
"tag": "宝宝",
"a": "孕 28 周起每天数,2 小时 10 次以上算正常;更要紧的是和自己平时比,少了一半就去医院。",
"href": "topic/taidongshu/",
"st": [
4
],
"heat": 0.058
},
{
"q": "肚子发紧是宫缩吗?",
"tag": "身体",
"a": "多半是生理性宫缩(假宫缩),不规律、休息就缓解;不足 37 周越来越规律或伴疼痛、出血、流水要马上去医院。",
"href": "topic/fajin/",
"st": [
4
],
"heat": 0.054
},
{
"q": "糖耐前一天怎么吃?",
"tag": "产检",
"a": "前 3 天正常吃、别刻意少吃主食;前一晚清淡晚餐,之后空腹 8 小时以上,可以喝少量白水。",
"href": "topic/tangnaiqian/",
"st": [
4
],
"heat": 0.05,
"badge": "新"
},
{
"q": "宫颈短要紧吗?",
"tag": "身体",
"a": "孕中期 24 周前宫颈 短于 25 毫米才叫宫颈短,早产风险会升高;发现了有成熟的处理办法,按医生方案来,多数能顺利往后走。",
"href": "topic/gongjing/",
"st": [
4
],
"heat": 0.046
},
{
"q": "孕期胃灼热、反酸怎么缓解?",
"tag": "身体",
"a": "孕期很常见,越到后期越明显;少量多餐、饭后 2 小时内不躺、床头垫高多能缓解,产后基本会消失。",
"href": "topic/fansuan/",
"st": [
4
],
"heat": 0.042
},
{
"q": "孕期耻骨痛怎么办?",
"tag": "身体",
"a": "多是激素让骨盆韧带变松引起的,两腿并拢动作、少单腿受力就能减轻;疼得走不了路要找医生或康复科。",
"href": "topic/chigu/",
"st": [
4
],
"heat": 0.038
},
{
"q": "孕期一定要左侧睡吗?",
"tag": "生活",
"a": "不一定,左右侧睡都可以;真正要注意的是孕 28 周后别长时间平躺,半夜醒来翻回侧睡就好。",
"href": "topic/cewo/",
"st": [
4
],
"heat": 0.034
},
{
"q": "假性宫缩和真宫缩怎么区分?",
"tag": "身体",
"a": "假宫缩不规律、歇一歇就缓解;真宫缩越来越密、越来越疼,休息也不停。",
"href": "topic/jiagong/",
"st": [
5
],
"heat": 0.062,
"badge": "热"
},
{
"q": "孕晚期胎动变少要紧吗?",
"tag": "宝宝",
"a": "孕晚期胎动不该明显变少;比平时少一半或明显变弱,当天就去医院查。",
"href": "topic/taidongshao/",
"st": [
5
],
"heat": 0.058
},
{
"q": "脐带绕颈怎么办?",
"tag": "宝宝",
"a": "很常见,约每 5 个宝宝有 1 个,多数能顺产;关键是每天数胎动、按时产检。",
"href": "topic/raojing/",
"st": [
5
],
"heat": 0.054
},
{
"q": "羊水偏多偏少怎么办?",
"tag": "产检",
"a": "看 B 超上的 AFI 或最大羊水池,偏一点多半复查就好;明显过多过少,医生会查原因再定。",
"href": "topic/yangshui/",
"st": [
5
],
"heat": 0.05,
"badge": "新"
},
{
"q": "无痛分娩怎么申请?有影响吗?",
"tag": "准备",
"a": "产检时说意愿、入院后签同意书,进产房有需求就能打;用药量很小,不影响宝宝、不增加剖宫产。",
"href": "topic/wutong/",
"st": [
5
],
"heat": 0.046
},
{
"q": "什么时候开始休产假?",
"tag": "职场",
"a": "国家规定 98 天里产前可休 15 天,多数人在预产期前 2 周左右开始休;身体不适可凭医生证明提前请假。",
"href": "topic/chanjiaqi/",
"st": [
5
],
"heat": 0.042
},
{
"q": "要不要请月嫂?怎么选?",
"tag": "准备",
"a": "家里没人能专心帮就值得请;选人看健康证、真实经验和实操,合同写清能换人。",
"href": "topic/yuesao/",
"st": [
5
],
"heat": 0.038
},
{
"q": "宝宝衣物用品要买多少?",
"tag": "准备",
"a": "新生儿长得快,衣服备 4~6 套就够,先少买、生了再补;安全座椅出院就要用。",
"href": "topic/yongpin/",
"st": [
5
],
"heat": 0.034
},
{
"q": "孕晚期喘不上气、睡不好怎么办?",
"tag": "身体",
"a": "子宫往上顶,气短多半正常,入盆后会好些;侧卧垫高、少食多餐能睡得更舒服。",
"href": "topic/chuanqi/",
"st": [
5
],
"heat": 0.03
},
{
"q": "破水了怎么办?",
"tag": "准备",
"a": "不管有没有宫缩,马上去医院;垫上护垫、尽量躺着去,记下破水时间和颜色。",
"href": "topic/poshui/",
"st": [
6
],
"heat": 0.062,
"badge": "热"
},
{
"q": "见红后多久会生?",
"tag": "准备",
"a": "多数在见红后 24~48 小时内临产;量少在家等,量多或鲜红马上去。",
"href": "topic/jianhongsheng/",
"st": [
6
],
"heat": 0.058
},
{
"q": "入院要带哪些证件?",
"tag": "准备",
"a": "夫妻双方身份证、母子健康手册、医保凭证和全套产检报告必带,其余按分娩医院的通知补。",
"href": "topic/ruyuan/",
"st": [
6
],
"heat": 0.054
},
{
"q": "侧切、撕裂能避免吗?",
"tag": "准备",
"a": "侧切现在不常规做,需要时才切;撕裂不能保证避免,但多数是轻度,缝好后恢复得快。",
"href": "topic/cheqie/",
"st": [
6
],
"heat": 0.05,
"badge": "新"
},
{
"q": "催产怎么做?疼吗?",
"tag": "准备",
"a": "宫颈没准备好先放药或球囊促成熟,再人工破膜 + 缩宫素;疼主要是宫缩疼,可以打无痛。",
"href": "topic/cuichan/",
"st": [
6
],
"heat": 0.046
},
{
"q": "剖宫产前要准备什么?",
"tag": "准备",
"a": "按医院通知术前禁食禁水、洗澡、摘首饰卸指甲油;带齐证件和待产包,家属陪同签字。",
"href": "topic/pougong/",
"st": [
6
],
"heat": 0.042
},
{
"q": "产后第一口奶怎么开?",
"tag": "宝宝",
"a": "出生后 1 小时内肌肤贴肌肤,让宝宝自己吸就是开奶,不用等奶来、不用揉奶。",
"href": "topic/kainai/",
"st": [
6
],
"heat": 0.038
},
{
"q": "宝宝出生后要打哪些针、做哪些筛查?",
"tag": "宝宝",
"a": "住院期间一般打乙肝、卡介苗两针疫苗和维生素 K1,做足跟血、听力、先心病三项筛查。",
"href": "topic/chusheng/",
"st": [
6
],
"heat": 0.034
}
]
]

Binary file not shown.

BIN
assets/img/brand-logo-c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
assets/img/d71826d10457.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

338
demo/gc-v1/index.html Normal file
View File

@@ -0,0 +1,338 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>孕妈周刊 · 效果稿 V1</title>
<!-- 效果稿 V1 · 孕妈周刊(杂志封面):广场列表页演示,独立页面,不接后端;数据读 guangchang/topics.js + data.js -->
<style>
:root{
--paper:#F7F2EA;--paper-2:#EFE7DB;--ink:#221C18;--ink-2:#5E554E;--muted:#9B8F85;--rule:#D9CEC0;
--brand:#F4593C;--fam:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
--serif:"Songti SC","STSong","Noto Serif CJK SC","Source Han Serif SC","Noto Serif SC","SimSun",serif;
--sans:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC",sans-serif;
--st:env(safe-area-inset-top);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
body{background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:14px;line-height:1.55;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
a{color:inherit;text-decoration:none}
img{display:block}
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;background:var(--paper)}
#sc::-webkit-scrollbar{display:none}
/* ---------- 顶栏(盖在封面上,滚动后变纸色) ---------- */
.bar{position:sticky;top:0;z-index:30;height:calc(46px + var(--st));padding-top:var(--st);margin-bottom:calc(-46px - var(--st));
display:flex;align-items:center;padding-left:6px;padding-right:12px;color:#fff;transition:background .25s,color .25s,box-shadow .25s}
.bar.on{background:rgba(247,242,234,.94);color:var(--ink);box-shadow:0 1px 0 var(--rule);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px)}
.bar .bk{width:38px;height:38px;display:grid;place-items:center;border-radius:50%}
.bar .bk svg{width:22px;height:22px}
.bar .tt{flex:1;text-align:center;font-family:var(--serif);font-weight:700;font-size:16px;letter-spacing:4px;opacity:0;transition:opacity .25s;margin-right:-26px}
.bar.on .tt{opacity:1}
.bar .ver{font-size:11px;opacity:.75;letter-spacing:.5px;white-space:nowrap}
/* ---------- 封面 ---------- */
.cover{position:relative;height:620px;overflow:hidden;background:#3a302a;color:#fff}
.cover>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.cover::after{content:"";position:absolute;inset:0;background:
linear-gradient(90deg,rgba(20,14,10,.5) 0,rgba(20,14,10,.18) 55%,rgba(20,14,10,0) 80%),
linear-gradient(180deg,rgba(20,14,10,.55) 0,rgba(20,14,10,.12) 26%,rgba(20,14,10,.12) 40%,rgba(20,14,10,.42) 60%,rgba(20,14,10,.88) 100%)}
.cv{position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;padding:calc(50px + var(--st)) 20px 22px}
.mast{display:flex;align-items:flex-end;justify-content:space-between;border-bottom:1px solid rgba(255,255,255,.55);padding-bottom:8px}
.mast h1{margin:0;font-family:var(--serif);font-weight:900;font-size:50px;line-height:1;letter-spacing:6px;text-shadow:0 2px 14px rgba(0,0,0,.25)}
.mast .iss{text-align:right;font-size:11px;line-height:1.5;letter-spacing:1px;opacity:.95}
.mast .iss b{display:block;font-family:var(--serif);font-size:15px;letter-spacing:2px}
.mast-sub{display:flex;justify-content:space-between;font-size:11px;letter-spacing:3px;margin-top:6px;opacity:.85}
.cv .sp{flex:1}
.lines{list-style:none;margin:0 0 18px;padding:0;width:58%}
.lines li{margin-bottom:12px;padding-left:10px;border-left:2px solid var(--brand)}
.lines li small{display:block;font-size:11px;letter-spacing:2px;opacity:.9;text-shadow:0 1px 4px rgba(0,0,0,.6)}
.lines li span{display:block;font-family:var(--serif);font-weight:700;font-size:14px;line-height:1.4;text-shadow:0 1px 3px rgba(0,0,0,.55),0 0 12px rgba(0,0,0,.35)}
.story .kick{display:inline-block;font-size:11px;letter-spacing:3px;padding:2px 8px;background:var(--brand);color:#fff;margin-bottom:10px}
.story h2{margin:0;font-family:var(--serif);font-weight:900;font-size:29px;line-height:1.28;letter-spacing:1px;text-shadow:0 2px 12px rgba(0,0,0,.35)}
.story p{margin:10px 0 0;font-size:13px;line-height:1.6;opacity:.9;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.story .by{margin-top:12px;display:flex;align-items:center;gap:8px;font-size:12px;opacity:.95}
.story .by img{width:22px;height:22px;border-radius:50%;object-fit:cover;border:1px solid rgba(255,255,255,.7)}
.story .by .rd{margin-left:auto;font-size:12px;letter-spacing:1px;border-bottom:1px solid rgba(255,255,255,.7)}
/* ---------- 栏目导航 ---------- */
.secnav{position:sticky;top:calc(46px + var(--st));z-index:25;background:var(--paper);border-bottom:1px solid var(--ink);display:flex;padding:0 16px}
.secnav button{flex:1;height:44px;font-size:14px;color:var(--muted);position:relative;letter-spacing:1px}
.secnav button.on{color:var(--ink);font-weight:700}
.secnav button.on::after{content:"";position:absolute;left:28%;right:28%;bottom:-1px;height:3px;background:var(--c,var(--brand))}
/* ---------- 通用版块标题 ---------- */
.sec{padding:26px 20px 0}
.hd{display:flex;align-items:baseline;gap:10px;border-top:3px double var(--ink);padding-top:12px;margin-bottom:6px}
.hd h3{margin:0;font-family:var(--serif);font-weight:900;font-size:22px;letter-spacing:3px}
.hd em{font-style:normal;font-size:11px;letter-spacing:2px;color:var(--muted);text-transform:uppercase}
.hd .r{margin-left:auto;font-size:12px;color:var(--ink-2)}
.lede{font-size:13px;color:var(--ink-2);margin:0 0 6px}
/* ---------- 目录 ---------- */
.toc{list-style:none;margin:0;padding:0}
.toc li{border-bottom:1px solid var(--rule)}
.toc a{display:flex;gap:14px;padding:13px 0 12px;align-items:flex-start}
.toc .no{font-family:Georgia,"Times New Roman",var(--serif);font-size:26px;line-height:1;font-style:italic;color:var(--c);width:34px;flex:none;padding-top:2px}
.toc .bd{flex:1;min-width:0}
.toc .col{font-size:11px;letter-spacing:2px;color:var(--c);font-weight:700}
.toc .col i{font-style:normal;color:var(--muted);font-weight:400;letter-spacing:0;margin-left:6px}
.toc .nm{font-family:var(--serif);font-weight:700;font-size:16px;line-height:1.4;margin-top:2px}
.toc .mt{font-size:12px;color:var(--muted);margin-top:3px}
.toc .hot{font-size:11px;color:var(--brand);border:1px solid var(--brand);padding:0 4px;margin-left:6px;letter-spacing:1px}
.more{display:block;width:100%;margin-top:12px;height:40px;border:1px solid var(--ink);font-size:13px;letter-spacing:2px;color:var(--ink)}
/* ---------- 征稿启事 ---------- */
.call{margin:26px 20px 0;border:1px solid var(--ink);padding:4px}
.call .in{border:1px solid var(--ink);padding:16px 16px 14px;position:relative;background:#FBF8F2}
.call .ti{text-align:center;font-family:var(--serif);font-weight:900;font-size:18px;letter-spacing:8px}
.call .ti small{display:block;font-family:var(--sans);font-weight:400;font-size:11px;letter-spacing:3px;color:var(--muted);margin-top:2px}
.call p{margin:10px 0 0;font-size:13px;color:var(--ink-2);line-height:1.7;text-align:justify}
.call .pay{display:flex;justify-content:center;gap:0;margin:12px 0 2px;border-top:1px dashed var(--rule);border-bottom:1px dashed var(--rule)}
.call .pay div{flex:1;text-align:center;padding:8px 0}
.call .pay div+div{border-left:1px dashed var(--rule)}
.call .pay b{display:block;font-family:Georgia,var(--serif);font-size:22px;color:var(--brand);line-height:1.2}
.call .pay span{font-size:11px;color:var(--muted);letter-spacing:1px}
.call .act{display:flex;gap:10px;margin-top:12px}
.call .act a{flex:1;height:36px;display:grid;place-items:center;font-size:13px;letter-spacing:1px;border:1px solid var(--ink)}
.call .act a.p{background:var(--ink);color:var(--paper)}
.call .stamp{position:absolute;right:10px;top:10px;width:46px;height:46px;border:1.5px solid var(--brand);border-radius:50%;color:var(--brand);
display:grid;place-items:center;font-size:11px;line-height:1.15;text-align:center;transform:rotate(-14deg);font-weight:700;opacity:.85}
/* ---------- 专栏 ---------- */
.feat{display:block;margin-top:14px}
.feat .ph{position:relative;aspect-ratio:4/3;overflow:hidden;background:var(--paper-2)}
.feat .ph img{width:100%;height:100%;object-fit:cover}
.feat .ph .tag{position:absolute;left:0;bottom:0;background:var(--paper);color:var(--c);font-size:11px;letter-spacing:2px;font-weight:700;padding:5px 10px 3px 0}
.feat h4{margin:6px 0 0;font-family:var(--serif);font-weight:900;font-size:21px;line-height:1.38}
.feat p{margin:8px 0 0;font-size:14px;color:var(--ink-2);line-height:1.7;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.feat p::first-letter{font-family:var(--serif);font-size:30px;float:left;line-height:1;margin:3px 6px 0 0;color:var(--c);font-weight:900}
.by{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--muted);margin-top:10px}
.by img{width:20px;height:20px;border-radius:50%;object-fit:cover}
.by .nm{color:var(--ink-2)}
.by .lk{margin-left:auto;display:flex;align-items:center;gap:3px}
.by .lk svg{width:13px;height:13px}
.pair{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:20px;padding-top:18px;border-top:1px solid var(--rule)}
.pair a{display:block;min-width:0}
.pair .ph{aspect-ratio:3/4;overflow:hidden;background:var(--paper-2)}
.pair img.cvr{width:100%;height:100%;object-fit:cover}
.pair .col{font-size:11px;letter-spacing:2px;color:var(--c);font-weight:700;margin-top:8px}
.pair h5{margin:3px 0 0;font-family:var(--serif);font-weight:700;font-size:15px;line-height:1.42;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.pair .by{margin-top:6px}
.pair .by .lk{display:none}
.quote{display:block;margin:22px 0 0;padding:22px 20px 18px;background:var(--paper-2);position:relative;border-top:3px solid var(--c)}
.quote .mk{position:absolute;left:14px;top:-4px;font-family:Georgia,serif;font-size:64px;line-height:1;color:var(--c);opacity:.35}
.quote q{display:block;quotes:none;font-family:var(--serif);font-weight:700;font-size:18px;line-height:1.65;letter-spacing:.5px;padding-left:8px}
.quote .src{margin-top:12px;font-size:12px;color:var(--muted);text-align:right}
.quote .src b{color:var(--ink-2);font-weight:400}
.grp{margin-top:6px}
.grp+.grp{margin-top:26px;padding-top:4px;border-top:1px solid var(--ink)}
.colo{margin:34px 20px 0;padding:16px 0 calc(28px + env(safe-area-inset-bottom));border-top:3px double var(--ink);text-align:center;font-size:11px;color:var(--muted);letter-spacing:1px;line-height:1.9}
.colo b{display:block;font-family:var(--serif);font-size:16px;color:var(--ink);letter-spacing:6px}
</style>
</head>
<body>
<div id="sc">
<header class="bar" id="bar">
<button class="bk" id="back" aria-label="返回"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
<div class="tt">孕妈周刊</div>
<span class="ver">效果稿 V1 · 孕妈周刊</span>
</header>
<section class="cover" id="cover"></section>
<nav class="secnav" id="nav"></nav>
<main id="main"></main>
<footer class="colo">
<b>孕妈周刊</b>
第 44 期 · 2026 年 11 月刊 · 由妈妈们共同撰写<br>
本期文章与数字均为示例占位,正式版替换为真实分享
</footer>
</div>
<script src="../../guangchang/topics.js"></script>
<script src="../../guangchang/data.js"></script>
<script>
(function () {
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
var $ = function (s) { return document.querySelector(s); };
var H = location.hash || '';
var COL = { /* 分类 → 杂志栏目名 */
family: { tab: '家庭婚姻', col: '家事 · 围炉', c: '#E0566F' },
work: { tab: '职场', col: '职场 · 手记', c: '#3A72B8' },
baby: { tab: '经验', col: '过来人 · 说', c: '#2E8A7C' }
};
var TABS = ['', 'family', 'work', 'baby'];
var cat = '', tocOpen = false;
function esc(s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); }
function hash(s) { var x = 7; for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); }
var POOL = []; for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
function av(name) { return '../../assets/img/mom/' + POOL[hash(name || '妈妈') % POOL.length] + '.jpg'; }
function fmt(n) { return n >= 10000 ? (n / 10000).toFixed(1) + '万' : String(n); }
function tUrl(id) { return '../../guangchang/?t=' + encodeURIComponent(id) + H; }
function nUrl(id, idx) { return '../../guangchang/?t=' + encodeURIComponent(id) + '&n=' + encodeURIComponent(id + '-' + idx) + H; }
var TBY = {}; T.forEach(function (t) { TBY[t.id] = t; });
/* 所有笔记扁平化 */
var NOTES = [];
T.forEach(function (t) {
var d = D[t.id]; if (!d || !d.notes) return;
d.notes.forEach(function (n, k) { NOTES.push({ t: t, n: n, idx: k + 1 }); });
});
function inCat(x) { return !cat || x.t.cat === cat; }
/* 「全部」时三栏轮流排,看起来像一本综合刊 */
function mix(list) {
if (cat) return list;
var b = { family: [], work: [], baby: [] }, out = [];
list.forEach(function (x) { (b[(x.t || x).cat] || b.family).push(x); });
for (var i = 0; out.length < list.length; i++) ['family', 'work', 'baby'].forEach(function (k) { if (b[k][i]) out.push(b[k][i]); });
return out;
}
function excerpt(body, n) { var s = String(body || '').replace(/\s+/g, ''); return s.length > n ? s.slice(0, n) + '…' : s; }
function pickQuote(body) {
var parts = String(body || '').split(/[。!?\n]/).map(function (p) { return p.trim(); });
var ok = function (p) { return p.length >= 12 && p.length <= 32 && !/[“”"「」::]|分享|办法|姐妹|参考|大家|评论/.test(p); };
for (var i = parts.length - 1; i > parts.length / 2; i--) if (ok(parts[i])) return parts[i];
for (i = 1; i < parts.length; i++) if (ok(parts[i])) return parts[i];
return parts[0].slice(0, 30);
}
var heart = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 20s-7-4.4-7-10a4 4 0 017-2.6A4 4 0 0119 10c0 5.6-7 10-7 10z"/></svg>';
function by(n, likes) {
return '<div class="by"><img loading="lazy" src="' + av(n.author) + '" alt=""><span class="nm">' + esc(n.author) + '</span><span>' + esc(n.stage || '') + '</span>' +
(likes ? '<span class="lk">' + heart + fmt(n.likes || 0) + '</span>' : '') + '</div>';
}
/* ---------- 封面 ---------- */
var COVER_PICK = { '': 'b07', family: 'm07', work: 'w02', baby: 'b08' };
function renderCover() {
var photo = NOTES.filter(function (x) { return x.n.photo && inCat(x); });
var pref = COVER_PICK[cat];
var main = photo.filter(function (x) { return x.t.id === pref; })[0] || photo[0];
if (!main) { $('#cover').innerHTML = ''; return; }
var pool = T.filter(function (t) { return (!cat || t.cat === cat) && t.id !== main.t.id; });
var lines = mix(pool.filter(function (t) { return t.hot; })).concat(pool.filter(function (t) { return !t.hot; })).slice(0, 3);
var m = COL[main.t.cat];
$('#cover').innerHTML =
'<img src="../../guangchang/' + esc(main.n.photo) + '" alt="">' +
'<div class="cv">' +
'<div class="mast"><h1>孕妈周刊</h1><div class="iss"><b>第 44 期</b>11 月刊 · 2026</div></div>' +
'<div class="mast-sub"><span>MAMA WEEKLY</span><span>' + (cat ? COL[cat].tab + '特辑' : '妈妈们自己写的杂志') + '</span></div>' +
'<div class="sp"></div>' +
'<ul class="lines">' + lines.map(function (t) {
return '<li><a href="' + tUrl(t.id) + '"><small>' + esc(COL[t.cat].col) + '</small><span>' + esc(t.name) + '</span></a></li>';
}).join('') + '</ul>' +
'<a class="story" href="' + nUrl(main.t.id, main.idx) + '">' +
'<span class="kick">本期封面故事 · ' + esc(m.tab) + '</span>' +
'<h2>' + esc(main.n.title) + '</h2>' +
'<p>' + esc(excerpt(main.n.body, 60)) + '</p>' +
'<div class="by"><img src="' + av(main.n.author) + '" alt=""><span>文 / ' + esc(main.n.author) + ' · ' + esc(main.n.stage || '') + '</span><span class="rd">阅读全文 →</span></div>' +
'</a>' +
'</div>';
}
/* ---------- 栏目导航 ---------- */
function renderNav() {
$('#nav').innerHTML = TABS.map(function (k) {
return '<button data-c="' + k + '" class="' + (k === cat ? 'on' : '') + '" style="--c:' + (k ? COL[k].c : 'var(--ink)') + '">' + (k ? COL[k].tab : '全部') + '</button>';
}).join('');
}
/* ---------- 正文 ---------- */
function renderMain() {
var topics = mix(T.filter(function (t) { return !cat || t.cat === cat; }));
var shown = tocOpen ? topics : topics.slice(0, 8);
var toc =
'<section class="sec"><div class="hd"><h3>本期目录</h3><em>Contents</em><span class="r">共 ' + topics.length + ' 个话题</span></div>' +
'<ol class="toc">' + shown.map(function (t, i) {
var c = COL[t.cat];
return '<li style="--c:' + c.c + '"><a href="' + tUrl(t.id) + '"><span class="no">' + (i < 9 ? '0' : '') + (i + 1) + '</span><div class="bd">' +
'<div class="col">' + esc(c.col) + (t.hot ? '<span class="hot">热议</span>' : '') + '</div>' +
'<div class="nm">' + esc(t.name) + '</div>' +
'<div class="mt">' + t.n + ' 篇来稿 · ' + fmt(t.talk) + ' 人在聊</div></div></a></li>';
}).join('') + '</ol>' +
(topics.length > 8 ? '<button class="more" id="more">' + (tocOpen ? '收起目录 ↑' : '展开完整目录(' + topics.length + ')↓') + '</button>' : '') +
'</section>';
var call =
'<section class="call"><div class="in"><div class="stamp">入选<br>有奖</div>' +
'<div class="ti">本刊征稿启事<small>CALL FOR STORIES</small></div>' +
'<p>孕期里那些说不出口的委屈、哭笑不得的小事、熬过来的经验,都值得被写下来。挑一个本期话题,写写你的故事,编辑部每期从来稿中选登。</p>' +
'<div class="pay"><div><b>¥30</b><span>现金稿酬</span></div><div><b>500</b><span>兜豆</span></div></div>' +
'<div class="act"><a class="p" href="' + tUrl(topics[0] ? topics[0].id : 'f01') + '">我要投稿</a><a href="../../guangchang/' + H + '">我的投稿</a></div>' +
'</div></section>';
/* 专栏:大图一篇 → 两篇小图并排 → 金句卡,循环 */
var pics = mix(NOTES.filter(function (x) { return x.n.photo && inCat(x); }));
var plain = mix(NOTES.filter(function (x) { return !x.n.photo && inCat(x); }));
var used = {}; var cvId = ($('#cover .story') || {}).getAttribute ? $('#cover .story').getAttribute('href') : '';
pics = pics.filter(function (x) { return cvId.indexOf('n=' + encodeURIComponent(x.t.id + '-' + x.idx)) < 0; });
var groups = [], pi = 0, qi = 0;
while (pi < pics.length && groups.length < 6) {
var g = '', f = pics[pi++], c = COL[f.t.cat];
g += '<a class="feat" style="--c:' + c.c + '" href="' + nUrl(f.t.id, f.idx) + '"><div class="ph"><img loading="lazy" src="../../guangchang/' + esc(f.n.photo) + '" alt=""><span class="tag">' + esc(c.col) + '</span></div>' +
'<h4>' + esc(f.n.title) + '</h4><p>' + esc(excerpt(f.n.body, 90)) + '</p>' + by(f.n, true) + '</a>';
var a = pics[pi], b = pics[pi + 1];
if (a && b) {
pi += 2;
g += '<div class="pair">' + [a, b].map(function (x) {
var cc = COL[x.t.cat];
return '<a style="--c:' + cc.c + '" href="' + nUrl(x.t.id, x.idx) + '"><div class="ph"><img class="cvr" loading="lazy" src="../../guangchang/' + esc(x.n.photo) + '" alt=""></div>' +
'<div class="col">' + esc(cc.col) + '</div><h5>' + esc(x.n.title) + '</h5>' + by(x.n, false) + '</a>';
}).join('') + '</div>';
}
var q = plain[qi++] || pics[pi++];
if (q) {
var qc = COL[q.t.cat];
g += '<a class="quote" style="--c:' + qc.c + '" href="' + nUrl(q.t.id, q.idx) + '"><span class="mk">“</span><q>' + esc(pickQuote(q.n.body)) + '</q>' +
'<div class="src">—— <b>' + esc(q.n.author) + '</b>,《' + esc(q.n.title) + '》</div></a>';
}
groups.push('<div class="grp">' + g + '</div>');
}
var cols =
'<section class="sec"><div class="hd"><h3>' + (cat ? COL[cat].col : '专栏') + '</h3><em>Features</em><span class="r">妈妈们的来稿</span></div>' +
groups.join('') + '</section>';
$('#main').innerHTML = toc + call + cols;
var mb = $('#more'); if (mb) mb.onclick = function () { tocOpen = !tocOpen; renderMain(); };
}
function render() { renderCover(); renderNav(); renderMain(); }
$('#nav').addEventListener('click', function (e) {
var b = e.target.closest('button'); if (!b) return;
var k = b.getAttribute('data-c'); if (k === cat) return;
cat = k; tocOpen = false; render();
var sc = $('#sc'); if (sc.scrollTop > 0) sc.scrollTop = 0;
});
$('#back').onclick = function () { history.length > 1 ? history.back() : (location.href = '../../' + location.hash); };
var bar = $('#bar'), sc = $('#sc');
sc.addEventListener('scroll', function () { bar.classList.toggle('on', sc.scrollTop > 420); }, { passive: true });
/* 禁止下拉回弹:往上找能朝该方向滚的容器,找不到才拦 */
var sx = 0, sy = 0;
document.addEventListener('touchstart', function (e) { if (e.touches.length === 1) { sx = e.touches[0].clientX; sy = e.touches[0].clientY; } }, { passive: true });
document.addEventListener('touchmove', function (e) {
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
if (Math.abs(dy) <= Math.abs(dx)) return;
var el = e.target;
while (el && el !== document.body && el !== document.documentElement) {
if (el.nodeType === 1) {
var oy = getComputedStyle(el).overflowY;
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
if (dy > 0 && el.scrollTop > 0) return;
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
}
}
el = el.parentNode;
}
if (e.cancelable) e.preventDefault();
}, { passive: false });
render();
})();
</script>
</body>
</html>

565
demo/gc-v2/index.html Normal file
View File

@@ -0,0 +1,565 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>孕妈广场</title>
<!-- 效果稿 V2 · 广场地图:首屏是一张俯视小广场插画(SVG),三个分类 = 广场上的三个角落;往下是该角落的话题和笔记。演示页,不接后端。 -->
<style>
:root{
--brand:#F4593C;--ink:#2E2521;--ink-2:#6E625B;--muted:#A08F86;--line:#EFE3D8;
--bg:#FAF4EC;--fam:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
--zc:#F4593C;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
body{background:var(--bg);font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC","Segoe UI",Roboto,sans-serif;
color:var(--ink);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5;-webkit-text-size-adjust:100%}
.hide{display:none!important}
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;background:var(--bg)}
#sc::-webkit-scrollbar{display:none}
/* ---------- 顶栏 ---------- */
.top{position:sticky;top:0;z-index:30;padding-top:env(safe-area-inset-top);background:rgba(250,244,236,.88);-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);transition:box-shadow .2s}
.top.on{box-shadow:0 4px 14px rgba(150,110,80,.10)}
.nav{display:flex;align-items:center;height:46px;padding:0 8px}
.nav .bk{width:36px;height:36px;display:grid;place-items:center;border-radius:50%}
.nav .bk:active{background:rgba(0,0,0,.05)}
.nav h1{flex:1;margin:0;text-align:center;font-size:17px;font-weight:800;letter-spacing:1px}
.nav .mine{height:30px;padding:0 11px;border-radius:15px;font-size:12.5px;font-weight:700;color:#8A6E5E;background:#F1E5D8}
.ver{position:absolute;left:50%;transform:translateX(-50%);bottom:-1px;font-size:11px;color:#C4B2A6;letter-spacing:.5px;white-space:nowrap;line-height:1}
/* ---------- 欢迎语 ---------- */
.hello{padding:8px 18px 2px;display:flex;align-items:flex-end;justify-content:space-between;gap:10px}
.hello h2{margin:0;font-size:20px;font-weight:800;line-height:1.3;letter-spacing:.5px}
.hello h2 em{font-style:normal;color:var(--brand)}
.hello p{margin:3px 0 0;font-size:12.5px;color:var(--muted)}
.hello .wx{flex:none;text-align:right;font-size:11px;color:#B39A8A;line-height:1.35}
.hello .wx b{display:block;font-size:15px;color:#8C6F5C;font-weight:700}
/* ---------- 广场地图 ---------- */
.mapw{position:relative;margin:10px 12px 0;border-radius:26px;overflow:hidden;box-shadow:0 14px 30px -18px rgba(140,90,50,.45),0 0 0 1px rgba(200,170,140,.25);background:#F3E6D5}
.map{position:relative;width:100%;aspect-ratio:351/440}
.map svg.ground{position:absolute;inset:0;width:100%;height:100%;display:block}
.pin{position:absolute;transform:translate(-50%,-50%)}
/* 角落热区 */
.zone{position:absolute;border-radius:50%;transform:translate(-50%,-50%)}
.zone .halo{position:absolute;inset:0;border-radius:50%;border:2px dashed var(--zc);opacity:0;transform:scale(.92);transition:opacity .3s,transform .3s}
.map.f-family .z-family .halo,.map.f-work .z-work .halo,.map.f-baby .z-baby .halo{opacity:.75;transform:scale(1);animation:spin 26s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}
/* 招牌 */
.sign{position:absolute;transform:translate(-50%,-50%);display:flex;flex-direction:column;align-items:center;pointer-events:none;z-index:4}
.sign b{display:block;padding:4px 10px 4px;border-radius:10px;background:#FFFDF9;color:var(--zc);font-size:12.5px;font-weight:800;letter-spacing:.5px;white-space:nowrap;
box-shadow:0 3px 0 rgba(0,0,0,.06),0 6px 14px -6px rgba(110,70,40,.35);border:1.5px solid color-mix(in srgb,var(--zc) 28%,#fff);transition:background .25s,color .25s}
.sign small{margin-top:3px;padding:1px 7px;border-radius:8px;background:rgba(255,253,249,.82);font-size:11px;color:#8C7466;white-space:nowrap}
.map.f-family .s-family b,.map.f-work .s-work b,.map.f-baby .s-baby b,.map.f-all .s-all b{background:var(--zc);color:#fff;border-color:var(--zc)}
/* 妈妈 */
.mom{position:absolute;width:34px;height:34px;margin:-17px 0 0 -17px;z-index:3;transition:filter .3s,opacity .3s}
.mom i{display:block;width:100%;height:100%;border-radius:50%;border:2.5px solid #fff;background:#EADBCB center/cover no-repeat;
box-shadow:0 5px 8px -3px rgba(90,55,30,.45);animation:breathe 3.4s ease-in-out infinite;transform-origin:50% 80%}
.mom::after{content:"";position:absolute;left:50%;bottom:-5px;width:26px;height:7px;margin-left:-13px;border-radius:50%;background:rgba(90,60,30,.18);filter:blur(1.5px);z-index:-1;animation:shadow 3.4s ease-in-out infinite}
.mom.sm{width:28px;height:28px;margin:-14px 0 0 -14px}
@keyframes breathe{0%,100%{transform:translateY(0) scale(1)}50%{transform:translateY(-2px) scale(1.06)}}
@keyframes shadow{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(.85);opacity:.7}}
/* 对话气泡 */
.bub{position:absolute;z-index:6;max-width:150px;padding:6px 10px 7px;border-radius:14px;background:#fff;font-size:12px;line-height:1.42;color:#3F3430;font-weight:600;
box-shadow:0 8px 18px -8px rgba(100,60,30,.4);transition:opacity .35s,transform .35s,filter .3s;pointer-events:none}
.bub::before{content:"";position:absolute;width:10px;height:10px;background:#fff;transform:rotate(45deg);border-radius:2px}
.bub.tl::before{left:12px;bottom:-4px}.bub.tr::before{right:12px;bottom:-4px}.bub.br::before{right:34px;top:-4px}
.bub span{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;position:relative}
.bub em{font-style:normal;color:var(--zc);font-weight:800}
.bub.out span{opacity:.15;transform:translateY(3px)}
.bub span{transition:opacity .3s,transform .3s}
.map:not(.f-all) .dim{opacity:.45;filter:grayscale(.6)}
.map:not(.f-all) .bub.dim{opacity:0;transform:scale(.9)}
/* 喷泉水波 */
.rip{transform-origin:center;transform-box:fill-box;animation:rip 3.6s ease-out infinite}
.rip.r2{animation-delay:1.2s}.rip.r3{animation-delay:2.4s}
@keyframes rip{0%{transform:scale(.35);opacity:.9}100%{transform:scale(1.25);opacity:0}}
.leaf{transform-origin:center;transform-box:fill-box;animation:sway 6s ease-in-out infinite}
@keyframes sway{0%,100%{transform:rotate(0)}50%{transform:rotate(3deg)}}
.bird{animation:peck 2.8s ease-in-out infinite;transform-box:fill-box;transform-origin:center}
@keyframes peck{0%,70%,100%{transform:translate(0,0)}78%{transform:translate(1.5px,1px)}86%{transform:translate(0,0)}}
/* 投稿信箱(地图上) */
.box{position:absolute;z-index:5;display:flex;flex-direction:column;align-items:center;transform:translate(-50%,-50%)}
.box .mb{position:relative;width:46px;height:62px}
.box .mb svg{display:block;width:100%;height:100%;overflow:visible;animation:wob 4.5s ease-in-out infinite;transform-origin:50% 100%}
@keyframes wob{0%,86%,100%{transform:rotate(0)}90%{transform:rotate(-4deg)}94%{transform:rotate(3deg)}}
.box .tag{margin-top:2px;padding:3px 8px;border-radius:9px;background:#fff;font-size:11px;font-weight:800;color:var(--brand);white-space:nowrap;box-shadow:0 4px 10px -5px rgba(120,60,30,.5);line-height:1.35;text-align:center}
.box .tag small{display:block;font-size:11px;font-weight:600;color:#A07C68}
.box:active .mb{transform:scale(.95)}
/* 地图下方路牌(分类快捷切换) */
.posts{display:flex;gap:6px;padding:12px 12px 2px}
.posts button{flex:1;min-width:0;height:36px;border-radius:12px;background:#F2E7DA;color:#8A7468;font-size:13.5px;font-weight:700;display:flex;align-items:center;justify-content:center;gap:4px;transition:all .2s;white-space:nowrap}
.posts button i{width:7px;height:7px;border-radius:50%;background:var(--zc);flex:none}
.posts button.on{background:var(--zc);color:#fff;box-shadow:0 6px 14px -7px var(--zc)}
.posts button.on i{background:#fff}
/* ---------- 列表 ---------- */
.sec{padding:20px 16px 0}
.sec-h{display:flex;align-items:center;gap:8px;margin-bottom:10px}
.sec-h h3{margin:0;font-size:17px;font-weight:800;letter-spacing:.3px;flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sec-h h3 em{font-style:normal;color:var(--zc)}
.live{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);flex:none}
.live .dot{width:7px;height:7px;border-radius:50%;background:#58B37A;box-shadow:0 0 0 3px rgba(88,179,122,.2);animation:pulse 1.8s ease-in-out infinite}
@keyframes pulse{50%{box-shadow:0 0 0 6px rgba(88,179,122,0)}}
.stack{display:flex}
.stack i{width:20px;height:20px;border-radius:50%;border:1.5px solid #fff;margin-left:-6px;background:#EADBCB center/cover}
.stack i:first-child{margin-left:0}
/* 话题:广场石板 */
.tps{display:flex;flex-direction:column;gap:8px}
.tp{display:flex;align-items:center;gap:11px;padding:10px 12px 10px 10px;border-radius:18px;background:#fff;text-align:left;box-shadow:0 1px 0 rgba(160,120,90,.08)}
.tp:active{transform:scale(.99)}
.tp .ph{position:relative;flex:none;width:52px;height:52px;border-radius:14px;overflow:hidden;background:var(--tl)}
.tp .ph img{width:100%;height:100%;object-fit:cover;display:block}
.tp .ph b{position:absolute;inset:0;display:grid;place-items:center;font-size:26px;font-weight:900;color:var(--ti);font-family:"STKaiti","KaiTi","Kaiti SC",serif}
.tp .ph img+b{display:none}
.tp .tx{flex:1;min-width:0}
.tp .nm{font-size:14.5px;font-weight:700;line-height:1.4;color:var(--ink);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.tp .mt{display:flex;align-items:center;gap:6px;margin-top:4px;font-size:11.5px;color:var(--muted)}
.tp .mt .k{padding:0 6px;border-radius:6px;font-weight:700;color:var(--ti);background:var(--tl);line-height:18px}
.tp .mt .hot{color:#E86A3A;font-weight:700}
.tp .go{flex:none;width:28px;height:28px;border-radius:50%;display:grid;place-items:center;background:#F7EFE6;color:#B49C8C}
.more{display:block;width:100%;margin-top:8px;height:38px;border-radius:14px;background:transparent;border:1.5px dashed #E2CFBE;color:#9C8172;font-size:13px;font-weight:700}
/* 笔记:长椅上的分享 */
.nts{display:flex;flex-direction:column;gap:12px}
.nt{display:flex;gap:12px;padding:12px;border-radius:20px;background:#fff;text-align:left;box-shadow:0 1px 0 rgba(160,120,90,.08)}
.nt:active{transform:scale(.99)}
.nt .pic{flex:none;width:104px;height:138px;border-radius:14px;overflow:hidden;background:#EFE4D8;position:relative}
.nt .pic img{width:100%;height:100%;object-fit:cover;display:block}
.nt .cv{flex:none;width:104px;height:138px;border-radius:14px;position:relative;overflow:hidden;padding:12px 10px;background:linear-gradient(160deg,var(--c1),var(--c2));color:var(--ti);display:flex;flex-direction:column;justify-content:flex-end}
.nt .cv b{position:relative;z-index:1;font-size:15px;font-weight:900;line-height:1.3}
.nt .cv small{position:relative;z-index:1;font-size:11px;margin-top:4px;opacity:.8;line-height:1.35}
.nt .cv .wm{position:absolute;right:-6px;top:-10px;font-size:76px;font-weight:900;line-height:1;color:#fff;opacity:.55;font-family:"STKaiti","KaiTi","Kaiti SC",serif}
.nt .bd{flex:1;min-width:0;display:flex;flex-direction:column}
.nt .tg{align-self:flex-start;max-width:100%;font-size:11.5px;font-weight:700;color:var(--ti);background:var(--tl);padding:0 7px;border-radius:7px;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nt h4{margin:6px 0 0;font-size:15px;font-weight:800;line-height:1.42;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.nt p{margin:4px 0 0;font-size:13px;color:var(--ink-2);line-height:1.55;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.nt .ft{margin-top:auto;padding-top:6px;display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted);min-width:0}
.nt .ft i{width:22px;height:22px;border-radius:50%;flex:none;background:#EADBCB center/cover}
.nt .ft .au{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#7A6A61}
.nt .ft .st{flex:none}
.nt .ft .lk{margin-left:auto;flex:none;display:flex;align-items:center;gap:3px}
/* 投稿明信片 */
.card-mail{position:relative;display:flex;align-items:center;gap:12px;width:100%;padding:14px 14px 14px 16px;border-radius:20px;text-align:left;overflow:hidden;
background:repeating-linear-gradient(-45deg,#F4593C 0 8px,#fff 8px 16px,#3A72B8 16px 24px,#fff 24px 32px);}
.card-mail::before{content:"";position:absolute;inset:5px;border-radius:16px;background:#FFFBF5}
.card-mail>*{position:relative}
.card-mail .tx{flex:1;min-width:0}
.card-mail .tx b{display:block;font-size:15px;font-weight:800}
.card-mail .tx span{display:block;margin-top:2px;font-size:12.5px;color:var(--ink-2)}
.card-mail .tx span em{font-style:normal;font-weight:800;color:var(--brand)}
.card-mail .stamp{flex:none;width:62px;height:70px;padding:4px;background:#fff;border-radius:4px;border:2px dashed #F3B9A6;transform:rotate(4deg);box-shadow:0 3px 8px -4px rgba(0,0,0,.2)}
.card-mail .stamp div{height:100%;border-radius:2px;background:linear-gradient(160deg,#FFB08F,#F4593C);color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;line-height:1.15}
.card-mail .stamp b{font-size:17px;font-weight:900}
.card-mail .stamp small{font-size:11px;font-weight:700;opacity:.95}
.foot{padding:22px 16px calc(28px + env(safe-area-inset-bottom));text-align:center;font-size:11px;color:#C1AFA2}
</style>
</head>
<body>
<div id="sc">
<div class="top" id="top">
<div class="nav">
<button class="bk" id="back" aria-label="返回"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#2E2521" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
<h1>孕妈广场</h1>
<button class="mine" id="mine">我的投稿</button>
</div>
<div class="ver">效果稿 V2 · 广场地图</div>
</div>
<div class="hello">
<div>
<h2><span id="tod">午后</span>的小广场,<br>有 <em id="nowN">0</em> 位妈妈在聊</h2>
<p>点亭子、长椅或大树,去那个角落坐坐</p>
</div>
<div class="wx"><b id="clock">14:30</b><span id="wxs">晴 · 微风</span></div>
</div>
<div class="mapw">
<div class="map f-all" id="map">
<svg class="ground" viewBox="0 0 351 440" preserveAspectRatio="none" aria-hidden="true">
<defs>
<pattern id="tile" width="22" height="22" patternUnits="userSpaceOnUse">
<rect width="22" height="22" fill="#F4E8D8"/>
<path d="M0 .5H22M.5 0V22" stroke="#EADAC6" stroke-width="1"/>
<rect x="3" y="3" width="2" height="2" rx="1" fill="#EFE0CD"/>
</pattern>
<pattern id="grass" width="14" height="14" patternUnits="userSpaceOnUse">
<rect width="14" height="14" fill="#CFE3BD"/>
<path d="M3 5l1-2 1 2M10 11l1-2 1 2" stroke="#B9D6A3" stroke-width="1" fill="none" stroke-linecap="round"/>
</pattern>
<pattern id="deck" width="351" height="9" patternUnits="userSpaceOnUse">
<rect width="351" height="9" fill="#EBD3B5"/>
<path d="M0 8.5H351" stroke="#DDBF9C" stroke-width="1"/>
</pattern>
<radialGradient id="water" cx=".42" cy=".38" r=".7">
<stop offset="0" stop-color="#E4F4F4"/><stop offset=".6" stop-color="#BFE1E3"/><stop offset="1" stop-color="#9FCFD3"/>
</radialGradient>
<linearGradient id="roof" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#FAC6CE"/><stop offset="1" stop-color="#EA8C9D"/>
</linearGradient>
<radialGradient id="glow"><stop offset="0" stop-color="#FFF4C8" stop-opacity=".95"/><stop offset="1" stop-color="#FFE59A" stop-opacity="0"/></radialGradient>
<filter id="sh" x="-30%" y="-30%" width="160%" height="160%"><feDropShadow dx="3" dy="5" stdDeviation="3.5" flood-color="#6B4526" flood-opacity=".22"/></filter>
<filter id="sh2" x="-30%" y="-30%" width="160%" height="160%"><feDropShadow dx="2" dy="3" stdDeviation="2" flood-color="#6B4526" flood-opacity=".2"/></filter>
</defs>
<!-- 地砖 -->
<rect width="351" height="440" fill="url(#tile)"/>
<!-- 草坪 -->
<path d="M-10 -10H205C214 30 196 60 170 74C150 88 160 130 150 160C138 196 96 214 56 206C24 200 4 214 -10 230Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
<path d="M-10 268C30 262 70 270 110 280C160 292 190 320 198 360C204 396 196 420 210 450H-10Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
<path d="M262 -10H361V120C340 128 318 118 300 104C282 90 268 60 262 30Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
<path d="M268 330C292 316 330 318 361 326V450H250C244 410 248 352 268 330Z" fill="url(#grass)" stroke="#B2CF9C" stroke-width="2"/>
<!-- 小路 -->
<g fill="none" stroke-linecap="round">
<path d="M176 222C140 190 116 160 92 112M176 222C220 214 260 206 300 200M176 222C150 262 128 300 106 346M176 222C210 270 240 320 300 350" stroke="#E2CCB0" stroke-width="30"/>
<path d="M176 222C140 190 116 160 92 112M176 222C220 214 260 206 300 200M176 222C150 262 128 300 106 346M176 222C210 270 240 320 300 350" stroke="#F6EBDC" stroke-width="25"/>
<path d="M176 222C140 190 116 160 92 112M176 222C150 262 128 300 106 346M176 222C210 270 240 320 300 350" stroke="#EAD8C2" stroke-width="2" stroke-dasharray="1 9"/>
</g>
<!-- 花坛小点 -->
<g>
<circle cx="30" cy="40" r="11" fill="#B6D49F"/><circle cx="26" cy="37" r="2.4" fill="#F7A9B7"/><circle cx="34" cy="42" r="2.4" fill="#FFD27A"/><circle cx="29" cy="45" r="2" fill="#fff"/>
<circle cx="190" cy="30" r="9" fill="#B6D49F"/><circle cx="187" cy="28" r="2.2" fill="#FFD27A"/><circle cx="193" cy="33" r="2.2" fill="#F7A9B7"/>
<circle cx="330" cy="400" r="12" fill="#A9CC92"/><circle cx="326" cy="396" r="2.5" fill="#F7A9B7"/><circle cx="335" cy="402" r="2.5" fill="#fff"/><circle cx="329" cy="406" r="2.2" fill="#FFD27A"/>
<circle cx="24" cy="420" r="10" fill="#A9CC92"/><circle cx="21" cy="417" r="2.2" fill="#fff"/><circle cx="27" cy="422" r="2.2" fill="#F7A9B7"/>
<circle cx="336" cy="30" r="13" fill="#A9CC92" filter="url(#sh2)"/><circle cx="332" cy="26" r="5" fill="#BEDCA8"/>
<circle cx="226" cy="410" r="10" fill="#A9CC92" filter="url(#sh2)"/><circle cx="223" cy="407" r="4" fill="#BEDCA8"/>
</g>
<!-- 中心喷泉 -->
<g>
<circle cx="176" cy="222" r="62" fill="#F1E2CF" stroke="#E3CDB2" stroke-width="2"/>
<circle cx="176" cy="222" r="52" fill="none" stroke="#E9D6BF" stroke-width="12" stroke-dasharray="9 3"/>
<circle cx="176" cy="222" r="38" fill="#EBDAC4" filter="url(#sh2)"/>
<circle cx="176" cy="222" r="33" fill="url(#water)"/>
<circle class="rip" cx="176" cy="222" r="28" fill="none" stroke="#fff" stroke-width="1.4" opacity=".8"/>
<circle class="rip r2" cx="176" cy="222" r="28" fill="none" stroke="#fff" stroke-width="1.4" opacity=".8"/>
<circle class="rip r3" cx="176" cy="222" r="28" fill="none" stroke="#fff" stroke-width="1.4" opacity=".8"/>
<circle cx="176" cy="222" r="10" fill="#F2E5D4" stroke="#E0CBB0" stroke-width="1.5"/>
<circle cx="176" cy="222" r="4.5" fill="#CDEBEE"/>
<circle cx="174.5" cy="220.5" r="1.6" fill="#fff"/>
</g>
<!-- 鸽子 -->
<g class="bird"><ellipse cx="236" cy="252" rx="5" ry="3.4" fill="#C9C3C0"/><circle cx="240.5" cy="250.6" r="2" fill="#A9A19D"/><path d="M242.4 250.6l1.6.4-1.6.6z" fill="#E59A5B"/></g>
<g class="bird" style="animation-delay:1.3s"><ellipse cx="226" cy="262" rx="4.6" ry="3.2" fill="#D6D0CC"/><circle cx="222" cy="260.6" r="1.9" fill="#B2AAA6"/><path d="M220.2 260.6l-1.5.4 1.5.6z" fill="#E59A5B"/></g>
<!-- 家庭婚姻亭(八角亭俯视) -->
<g>
<polygon points="92,58 130,74 146,112 130,150 92,166 54,150 38,112 54,74" fill="#EEDCCB" stroke="#E2CBB3" stroke-width="2" transform="translate(0 2)"/>
<g filter="url(#sh)">
<polygon points="92,66 124,79 137,112 124,145 92,158 60,145 47,112 60,79" fill="url(#roof)"/>
</g>
<g stroke="#DC7487" stroke-width="1.6" opacity=".8">
<path d="M92 112L92 66M92 112L124 79M92 112L137 112M92 112L124 145M92 112L92 158M92 112L60 145M92 112L47 112M92 112L60 79"/>
</g>
<polygon points="92,66 124,79 137,112 124,145 92,158 60,145 47,112 60,79" fill="none" stroke="#FCE3E7" stroke-width="2.5" stroke-linejoin="round"/>
<polygon points="92,90 107.5,96.5 114,112 107.5,127.5 92,134 76.5,127.5 70,112 76.5,96.5" fill="#F8B4C0" opacity=".55"/>
<circle cx="92" cy="112" r="5" fill="#F5D07A" stroke="#E2A94A" stroke-width="1.5"/>
<g fill="#F5D07A"><circle cx="92" cy="66" r="2.2"/><circle cx="124" cy="79" r="2.2"/><circle cx="137" cy="112" r="2.2"/><circle cx="124" cy="145" r="2.2"/><circle cx="92" cy="158" r="2.2"/><circle cx="60" cy="145" r="2.2"/><circle cx="47" cy="112" r="2.2"/><circle cx="60" cy="79" r="2.2"/></g>
</g>
<!-- 职场长椅:木平台 + 遮阳伞 + 两张长椅 + 路灯 -->
<g>
<rect x="246" y="150" width="96" height="106" rx="10" fill="url(#deck)" stroke="#D8B994" stroke-width="2"/>
<!-- 长椅 1(上) -->
<g filter="url(#sh2)">
<rect x="258" y="158" width="72" height="16" rx="3" fill="#C99A6E"/>
<rect x="258" y="158" width="72" height="5" rx="2" fill="#9E7150"/>
<path d="M258 167.5H330M258 171.5H330" stroke="#B5875E" stroke-width="1"/>
</g>
<!-- 长椅 2(下) -->
<g filter="url(#sh2)">
<rect x="258" y="232" width="72" height="16" rx="3" fill="#C99A6E"/>
<rect x="258" y="243" width="72" height="5" rx="2" fill="#9E7150"/>
<path d="M258 236.5H330M258 240.5H330" stroke="#B5875E" stroke-width="1"/>
</g>
<!-- 遮阳伞 -->
<g filter="url(#sh)">
<circle cx="294" cy="203" r="26" fill="#fff"/>
<path d="M294 203L294 177A26 26 0 0 1 312.4 184.6ZM294 203L320 203A26 26 0 0 1 312.4 221.4ZM294 203L294 229A26 26 0 0 1 275.6 221.4ZM294 203L268 203A26 26 0 0 1 275.6 184.6Z" fill="#8EB1DD"/>
<circle cx="294" cy="203" r="26" fill="none" stroke="#6E95C8" stroke-width="1.5"/>
<circle cx="294" cy="203" r="3" fill="#3A72B8"/>
</g>
<!-- 路灯 -->
<circle cx="338" cy="148" r="16" fill="url(#glow)"/>
<circle cx="338" cy="148" r="4.5" fill="#FFF6D8" stroke="#C9B48A" stroke-width="1.5"/>
<!-- 盆栽 -->
<circle cx="252" cy="262" r="8" fill="#B88B66" filter="url(#sh2)"/><circle cx="252" cy="262" r="6.5" fill="#8FC08F"/><circle cx="250" cy="260" r="2.5" fill="#A9D3A3"/>
</g>
<!-- 经验树下:环形长椅 + 大树 -->
<g>
<ellipse cx="112" cy="362" rx="66" ry="60" fill="#5D7F57" opacity=".14"/>
<circle cx="104" cy="352" r="55" fill="none" stroke="#C69C73" stroke-width="9" stroke-dasharray="7 2"/>
<circle cx="104" cy="352" r="59.5" fill="none" stroke="#A97E58" stroke-width="1.2"/>
<g class="leaf" filter="url(#sh)">
<circle cx="104" cy="352" r="44" fill="#7FB394"/>
<circle cx="80" cy="336" r="22" fill="#8CC0A0"/>
<circle cx="124" cy="334" r="20" fill="#8CC0A0"/>
<circle cx="118" cy="374" r="22" fill="#78AC8D"/>
<circle cx="84" cy="372" r="18" fill="#86BA9A"/>
<circle cx="98" cy="344" r="18" fill="#9DCDAF"/>
<circle cx="90" cy="336" r="8" fill="#B4DCC2"/>
<circle cx="120" cy="330" r="6" fill="#B4DCC2"/>
<circle cx="112" cy="366" r="5" fill="#A7D3B6"/>
</g>
<!-- 小灌木 -->
<circle cx="196" cy="326" r="10" fill="#9BC48C" filter="url(#sh2)"/><circle cx="193" cy="323" r="4" fill="#B5D8A6"/>
</g>
<!-- 路灯们 -->
<circle cx="140" cy="178" r="13" fill="url(#glow)"/><circle cx="140" cy="178" r="3.8" fill="#FFF6D8" stroke="#C9B48A" stroke-width="1.4"/>
<circle cx="222" cy="300" r="13" fill="url(#glow)"/><circle cx="222" cy="300" r="3.8" fill="#FFF6D8" stroke="#C9B48A" stroke-width="1.4"/>
</svg>
<!-- 热区 -->
<button class="zone z-family" data-cat="family" style="--zc:var(--fam);left:26.2%;top:25.5%;width:30%;aspect-ratio:1" aria-label="家庭婚姻亭"><i class="halo"></i></button>
<button class="zone z-work" data-cat="work" style="--zc:var(--work);left:83.8%;top:46%;width:33%;aspect-ratio:1" aria-label="职场长椅"><i class="halo"></i></button>
<button class="zone z-baby" data-cat="baby" style="--zc:var(--baby);left:29.6%;top:80%;width:36%;aspect-ratio:1" aria-label="经验树下"><i class="halo"></i></button>
<button class="zone z-all" data-cat="" style="left:50.1%;top:50.5%;width:20%;aspect-ratio:1" aria-label="全部"></button>
<!-- 招牌 -->
<div class="sign s-family" style="--zc:var(--fam);left:26.2%;top:25.5%"><b>家庭婚姻亭</b><small id="cnt-family"></small></div>
<div class="sign s-work" style="--zc:var(--work);left:83.8%;top:37.6%"><b>职场长椅</b><small id="cnt-work"></small></div>
<div class="sign s-baby" style="--zc:var(--baby);left:29.6%;top:80%"><b>经验树下</b><small id="cnt-baby"></small></div>
<div class="sign s-all" style="--zc:var(--brand);left:50.1%;top:50.5%"><b style="font-size:11.5px;padding:2px 8px">全部</b></div>
<div id="moms"></div>
<!-- 投稿信箱 -->
<button class="box" id="mailbox" style="left:80.5%;top:12.5%" aria-label="投稿信箱">
<span class="mb">
<svg viewBox="0 0 46 62">
<ellipse cx="23" cy="59" rx="16" ry="3" fill="rgba(90,50,20,.22)"/>
<rect x="20" y="38" width="6" height="21" rx="1.5" fill="#8C5B3E"/>
<path d="M6 18C6 9 13 4 23 4S40 9 40 18V40H6Z" fill="#F4593C"/>
<path d="M6 18C6 9 13 4 23 4S40 9 40 18V22H6Z" fill="#FF7A58"/>
<rect x="12" y="25" width="22" height="3.5" rx="1.75" fill="#B9361F"/>
<rect x="15" y="20.5" width="16" height="9" rx="1" fill="#FFF7EA" transform="rotate(-6 23 25)"/>
<path d="M15.5 21.2L23 26l7.5-5.8" stroke="#F0B9A6" stroke-width="1" fill="none" transform="rotate(-6 23 25)"/>
<rect x="12" y="25" width="22" height="2" fill="#B9361F" opacity=".0"/>
<text x="23" y="37" text-anchor="middle" font-size="7" font-weight="800" fill="#fff" font-family="sans-serif">投稿</text>
<rect x="40" y="10" width="2.5" height="18" rx="1" fill="#C9472C"/>
<path d="M42.5 10H50V16H42.5Z" fill="#FFD25E"/>
</svg>
</span>
<span class="tag">投稿信箱<small>选中得 ¥30+500兜豆</small></span>
</button>
</div>
</div>
<div class="posts" id="posts"></div>
<div class="sec">
<div class="sec-h"><h3 id="tpH"></h3><span class="live"><span class="stack" id="tpStack"></span></span></div>
<div class="tps" id="tps"></div>
<button class="more hide" id="more"></button>
</div>
<div class="sec">
<div class="sec-h"><h3 id="ntH"></h3><span class="live"><span class="dot"></span><span id="ntLive"></span></span></div>
<div class="nts" id="nts"></div>
</div>
<div class="foot">示例占位内容 · 数字仅作演示</div>
</div>
<script src="../../guangchang/topics.js"></script>
<script src="../../guangchang/data.js"></script>
<script>
(function () {
var $ = function (s) { return document.querySelector(s); };
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
var H = location.hash;
var CAT = {
family: { name: '家庭婚姻亭', short: '家庭婚姻', col: '#E0566F', tl: '#FFEDF1', ti: '#C23A55' },
work: { name: '职场长椅', short: '职场', col: '#3A72B8', tl: '#E9F1FB', ti: '#2F64A8' },
baby: { name: '经验树下', short: '经验', col: '#2E8A7C', tl: '#E3F3EF', ti: '#21705F' }
};
var ORDER = ['family', 'work', 'baby'];
var cur = '';
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var hs = function (s) { var x = 7; for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
var POOL = [];
for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i);
for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
var av = function (name) { return '../../assets/img/mom/' + POOL[hs(name || '妈妈') % POOL.length] + '.jpg'; };
var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : String(n).replace(/\B(?=(\d{3})+$)/g, ','); };
var go = function (q) { location.href = '../../guangchang/' + q + H; };
/* 话题按分类 + 笔记(带 话题id-序号) */
var BY = { family: [], work: [], baby: [] };
T.forEach(function (t) { if (BY[t.cat]) BY[t.cat].push(t); });
var NOTES = { family: [], work: [], baby: [] };
T.forEach(function (t) {
var d = D[t.id]; if (!d || !BY[t.cat]) return;
d.notes.forEach(function (n, k) { NOTES[t.cat].push({ n: n, t: t, id: t.id + '-' + (k + 1), k: k }); });
});
/* 每类:带照片的排前面一些,并按 序号 轮流穿插不同话题 */
ORDER.forEach(function (c) {
NOTES[c].sort(function (a, b) { return (a.k - b.k) || ((b.n.photo ? 1 : 0) - (a.n.photo ? 1 : 0)) || (hs(a.id) % 97 - hs(b.id) % 97); });
});
var talkOf = function (c) { return BY[c].reduce(function (s, t) { return s + t.talk; }, 0); };
/* 统计 */
var all = 0;
ORDER.forEach(function (c) { var n = talkOf(c); all += n; $('#cnt-' + c).textContent = fmt(n) + ' 人在聊'; });
$('#nowN').textContent = fmt(all);
var d0 = new Date(Date.now() + (new Date().getTimezoneOffset() + 480) * 6e4), hh = d0.getHours(); /* 一律按北京时间 */
$('#clock').textContent = (hh < 10 ? '0' : '') + hh + ':' + (d0.getMinutes() < 10 ? '0' : '') + d0.getMinutes();
$('#tod').textContent = hh < 5 ? '深夜' : hh < 9 ? '清晨' : hh < 12 ? '上午' : hh < 14 ? '中午' : hh < 18 ? '午后' : hh < 20 ? '傍晚' : '夜里';
if (hh >= 18 || hh < 5) $('#wxs').textContent = '晚风 · 微凉';
/* ---------- 地图上的妈妈和气泡 ---------- */
/* 坐标:map 宽 351 高 440 的百分比 */
var P = function (x, y) { return 'left:' + (x / 351 * 100).toFixed(2) + '%;top:' + (y / 440 * 100).toFixed(2) + '%'; };
var SPOTS = {
family: { moms: [[42, 176, 0], [80, 186, 1], [150, 148, 0], [30, 70, 1]], bub: { x: 20, y: 54, cls: 'tl', w: 150 } },
work: { moms: [[254, 202, 1], [334, 212, 0], [300, 244, 0]], bub: { x: 194, y: 262, cls: 'br', w: 150 } },
baby: { moms: [[192, 380, 0], [56, 408, 1], [150, 410, 1]], bub: { x: 178, y: 360, cls: 'tl', w: 150 } }
};
var BUBIX = { family: 0, work: 0, baby: 0 };
var momsHTML = '';
ORDER.forEach(function (c) {
var s = SPOTS[c], ns = NOTES[c];
s.moms.forEach(function (m, j) {
var a = ns[(j * 5 + 2) % ns.length].n.author;
momsHTML += '<span class="mom' + (m[2] ? ' sm' : '') + ' m-' + c + '" style="' + P(m[0], m[1]) + '"><i style="background-image:url(' + av(a) + ');animation-delay:' + (-(j * 0.9 + ORDER.indexOf(c) * 0.5)).toFixed(1) + 's"></i></span>';
});
var b = s.bub;
/* 气泡锚点:tl = 尾巴在左下,框在锚点右上方;tr = 尾巴在右下 */
var st = 'left:' + (b.x / 351 * 100).toFixed(2) + '%;' + (b.cls === 'br' ? 'top:' + (b.y / 440 * 100).toFixed(2) + '%' : 'bottom:' + ((440 - b.y) / 440 * 100).toFixed(2) + '%');
momsHTML += '<div class="bub ' + b.cls + ' b-' + c + '" style="--zc:' + CAT[c].col + ';' + st + ';width:' + b.w + 'px"><span></span></div>';
});
$('#moms').innerHTML = momsHTML;
function setBub(c) {
var list = BY[c], t = list[BUBIX[c] % list.length];
var el = $('.b-' + c + ' span');
el.innerHTML = '<em>#</em>' + esc(t.name);
}
ORDER.forEach(setBub);
var tick = 0;
setInterval(function () {
var c = ORDER[tick++ % 3];
if (cur && c !== cur) c = cur;
var b = $('.b-' + c); b.classList.add('out');
setTimeout(function () { BUBIX[c]++; setBub(c); b.classList.remove('out'); }, 320);
}, 2200);
/* ---------- 路牌 ---------- */
$('#posts').innerHTML = [['', '全部', '#F4593C']].concat(ORDER.map(function (c) { return [c, CAT[c].short, CAT[c].col]; })).map(function (x) {
return '<button data-cat="' + x[0] + '" style="--zc:' + x[2] + '"><i></i>' + x[1] + '</button>';
}).join('');
/* ---------- 列表 ---------- */
var expanded = false;
function topicRow(t) {
var c = CAT[t.cat], d = D[t.id];
var who = d ? d.notes.slice(0, 3).map(function (n) { return '<i style="background-image:url(' + av(n.author) + ')"></i>'; }).join('') : '';
return '<button class="tp" data-t="' + t.id + '" style="--tl:' + c.tl + ';--ti:' + c.ti + '">' +
'<span class="ph">' + (t.ph ? '<img loading="lazy" src="../../' + t.ph + '" alt="">' : '') + '<b>' + esc(t.g) + '</b></span>' +
'<span class="tx"><span class="nm">' + esc(t.name) + '</span>' +
'<span class="mt">' + (cur ? '' : '<span class="k">' + c.short + '</span>') + (t.hot ? '<span class="hot">热聊</span>' : '') +
'<span class="stack">' + who + '</span><span>' + fmt(t.talk) + ' 人在聊</span></span></span>' +
'<span class="go"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round"><path d="M9 5l7 7-7 7"/></svg></span></button>';
}
function noteCard(o) {
var n = o.n, t = o.t, c = CAT[t.cat];
var vis = n.photo ? '<span class="pic"><img loading="lazy" src="../../guangchang/' + n.photo + '" alt=""></span>'
: '<span class="cv" style="--c1:' + t.c[0] + ';--c2:' + t.c[1] + '"><span class="wm">' + esc(t.g) + '</span><b>' + esc(n.cover) + '</b><small>' + esc(n.coverSub || '') + '</small></span>';
return '<button class="nt" data-t="' + t.id + '" data-n="' + o.id + '" style="--tl:' + c.tl + ';--ti:' + c.ti + '">' + vis +
'<span class="bd"><span class="tg"># ' + esc(t.name) + '</span><h4>' + esc(n.title) + '</h4><p>' + esc((n.body || '').replace(/\n/g, ' ')) + '</p>' +
'<span class="ft"><i style="background-image:url(' + av(n.author) + ')"></i><span class="au">' + esc(n.author) + '</span><span class="st">· ' + esc(n.stage) + '</span>' +
'<span class="lk"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z"/></svg>' + fmt(n.likes) + '</span></span></span></button>';
}
var MAIL = '<button class="card-mail" id="mailcard"><span class="tx"><b>给广场写一封信</b><span>你的故事被选中,送 <em>¥30 现金 + 500 兜豆</em></span></span><span class="stamp"><div><b>¥30</b><small>+500兜豆</small></div></span></button>';
function render() {
var map = $('#map');
map.className = 'map f-' + (cur || 'all');
ORDER.forEach(function (c) {
var dim = cur && c !== cur;
document.querySelectorAll('.m-' + c + ',.b-' + c).forEach(function (el) { el.classList.toggle('dim', !!dim); });
});
document.querySelectorAll('#posts button').forEach(function (b) { b.classList.toggle('on', b.dataset.cat === cur); });
var col = cur ? CAT[cur].col : '#F4593C';
document.documentElement.style.setProperty('--zc', col);
var tops;
if (cur) tops = BY[cur].slice().sort(function (a, b) { return b.hot - a.hot || b.talk - a.talk; });
else { tops = []; for (var k = 0; k < 10; k++) ORDER.forEach(function (c) { var l = BY[c].slice().sort(function (a, b) { return b.hot - a.hot || b.talk - a.talk; }); if (l[k]) tops.push(l[k]); }); }
var lim = expanded ? tops.length : 4;
$('#tpH').innerHTML = cur ? '此刻在<em>' + CAT[cur].name + '</em>聊' : '此刻<em>广场上</em>在聊';
var tl = (cur ? BY[cur] : T).slice(0, 4);
$('#tpStack').innerHTML = tl.map(function (t) { return '<i style="background-image:url(' + av(t.id + t.name) + ')"></i>'; }).join('');
$('#tps').innerHTML = tops.slice(0, lim).map(topicRow).join('');
var mb = $('#more');
mb.classList.toggle('hide', tops.length <= 4);
mb.textContent = expanded ? '收起' : '这个角落还有 ' + (tops.length - 4) + ' 个话题';
var ns;
if (cur) ns = NOTES[cur].slice(0, 18);
else { ns = []; for (k = 0; ns.length < 21; k++) { var any = false; ORDER.forEach(function (c) { if (NOTES[c][k]) { ns.push(NOTES[c][k]); any = true; } }); if (!any) break; } }
$('#ntH').innerHTML = cur ? '坐在' + CAT[cur].short + '角落的分享' : '大家刚写下的';
$('#ntLive').textContent = fmt(cur ? Math.round(talkOf(cur) / 37) : Math.round(all / 37)) + ' 人正在看';
var h = ns.map(noteCard);
h.splice(Math.min(3, h.length), 0, MAIL);
$('#nts').innerHTML = h.join('');
}
function setCat(c) {
if (c === cur) c = c ? '' : c;
cur = c; expanded = false; render();
if (cur) { BUBIX[cur]++; setBub(cur); }
}
document.addEventListener('click', function (e) {
var z = e.target.closest('[data-cat]');
if (z) { setCat(z.dataset.cat); return; }
var n = e.target.closest('[data-n]');
if (n) { go('?t=' + n.dataset.t + '&n=' + n.dataset.n); return; }
var t = e.target.closest('[data-t]');
if (t) { go('?t=' + t.dataset.t); return; }
if (e.target.closest('#more')) { expanded = !expanded; render(); return; }
if (e.target.closest('#mailbox,#mailcard')) { go(cur ? '?c=' + cur : ''); return; }
});
$('#mine').addEventListener('click', function () { go('?mine=1'); });
$('#back').addEventListener('click', function () { history.length > 1 ? history.back() : location.href = '../../' + location.hash; });
var sc = $('#sc');
sc.addEventListener('scroll', function () { $('#top').classList.toggle('on', sc.scrollTop > 4); }, { passive: true });
/* 禁止下拉回弹:往上找能朝该方向滚的容器,找不到才拦 */
var sx = 0, sy = 0;
document.addEventListener('touchstart', function (e) { if (e.touches.length !== 1) return; sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
document.addEventListener('touchmove', function (e) {
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
if (Math.abs(dy) <= Math.abs(dx)) return;
var el = e.target;
while (el && el !== document.body && el !== document.documentElement) {
if (el.nodeType === 1) {
var oy = getComputedStyle(el).overflowY;
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
if (dy > 0 && el.scrollTop > 0) return;
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
}
}
el = el.parentNode;
}
if (e.cancelable) e.preventDefault();
}, { passive: false });
render();
})();
</script>
</body>
</html>

346
demo/gc-v3/index.html Normal file
View File

@@ -0,0 +1,346 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>孕妈广场 · 留言墙</title>
<!-- 效果稿 V3 · 留言墙(软木板便签):仅演示列表页视觉,点话题/笔记跳现版广场详情。数据读 guangchang/topics.js + data.js -->
<style>
:root{
--brand:#F4593C;--ink:#3A2A1E;--ink2:#6E5846;
--fam:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
--hand:"Kaiti SC","STKaiti","KaiTi","BiauKai","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Segoe UI",Roboto,sans-serif;
color:var(--ink);-webkit-font-smoothing:antialiased;font-size:14px;line-height:1.5;-webkit-text-size-adjust:100%;background:#C99D70}
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
/* ---------- 软木板:唯一滚动容器 ---------- */
.cork{background-color:#CFA273;
background-image:
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .35 0 0 0 0 .2 0 0 0 0 .08 0 0 0 1.6 -.55'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E"),
radial-gradient(rgba(255,236,200,.35) 1px,transparent 1.6px),
radial-gradient(rgba(110,60,25,.28) 1.2px,transparent 1.8px);
background-size:180px 180px,13px 11px,9px 12px;
background-position:0 0,3px 5px,0 0}
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none}
#sc::-webkit-scrollbar{display:none}
#sc::before{content:"";position:fixed;inset:0;pointer-events:none;z-index:0;
background:radial-gradient(120% 70% at 50% 30%,rgba(255,230,190,.18),rgba(70,35,10,.22) 100%)}
/* ---------- 顶部:木框横梁 + 标签夹 ---------- */
.top{position:sticky;top:0;z-index:30;padding-top:env(safe-area-inset-top)}
.rail{position:relative;height:50px;display:flex;align-items:center;padding:0 8px;
background:linear-gradient(180deg,#9A6A43,#80542F 70%,#6E4627);
box-shadow:inset 0 1px 0 rgba(255,220,180,.35),inset 0 -2px 0 rgba(0,0,0,.18),0 3px 6px rgba(60,30,10,.35)}
.rail::before{content:"";position:absolute;inset:0;opacity:.35;pointer-events:none;
background:repeating-linear-gradient(178deg,rgba(255,220,170,.0) 0 5px,rgba(255,220,170,.18) 6px,rgba(60,30,10,.0) 7px 11px,rgba(60,30,10,.25) 12px 13px)}
.bk{position:relative;width:36px;height:36px;display:grid;place-items:center;border-radius:50%;color:#FFF3E2}
.bk:active{background:rgba(0,0,0,.15)}
.bk svg{width:22px;height:22px}
.ttl{position:relative;flex:1;display:flex;justify-content:center}
.ttl b{display:inline-block;padding:4px 14px 3px;background:#F7EEDC;color:#5A3A22;font-size:17px;font-weight:900;letter-spacing:2px;
transform:rotate(-1.2deg);box-shadow:0 2px 3px rgba(0,0,0,.3);border-radius:1px}
.ttl b::after{content:"";position:absolute}
.vtag{position:relative;width:60px;text-align:right;font-size:11px;line-height:1.2;color:rgba(255,240,220,.7);white-space:nowrap}
.bk{margin-right:24px}
.tabs{position:relative;display:flex;gap:8px;padding:12px 12px 6px;justify-content:space-between}
.tabs::before{content:"";position:absolute;left:0;right:0;top:0;height:6px;background:linear-gradient(rgba(50,25,8,.35),transparent)}
.tab{position:relative;flex:1;min-width:0;height:44px;margin-top:6px;border-radius:2px 2px 4px 4px;background:#F6EEDD;color:#6A5240;
font-size:14px;font-weight:800;display:flex;align-items:center;justify-content:center;gap:4px;
box-shadow:0 1px 1px rgba(0,0,0,.15),0 6px 8px -4px rgba(60,30,10,.45);transition:transform .18s,background .18s,color .18s}
.tab:nth-child(1){transform:rotate(-1.5deg)}
.tab:nth-child(2){transform:rotate(1deg)}
.tab:nth-child(3){transform:rotate(-.8deg)}
.tab:nth-child(4){transform:rotate(1.4deg)}
.tab i{font-style:normal;width:8px;height:8px;border-radius:50%;background:var(--tc);flex:none}
.tab.on{background:var(--tc);color:#fff;transform:translateY(3px) rotate(0) scale(1.04)}
.tab.on i{background:#fff}
/* 黑色长尾夹 */
.tab .clip{position:absolute;top:-10px;left:50%;width:26px;height:12px;margin-left:-13px;border-radius:3px 3px 1px 1px;
background:linear-gradient(#4A4A4E,#1F1F22);box-shadow:0 2px 2px rgba(0,0,0,.35)}
.tab .clip::before{content:"";position:absolute;left:5px;right:5px;top:-7px;height:10px;border:2px solid #A9ABB0;border-bottom:0;border-radius:6px 6px 0 0}
.tab.on .clip{background:linear-gradient(#F27A5A,#C9452B)}
/* ---------- 墙面 ---------- */
main{position:relative;z-index:1;padding:8px 12px calc(30px + env(safe-area-inset-bottom))}
.hint{display:flex;justify-content:center;margin:6px 0 16px}
.hint span{display:inline-block;padding:5px 12px;background:rgba(255,248,235,.85);font-family:var(--hand);font-size:14px;color:#6A4A30;
transform:rotate(-.8deg);box-shadow:0 2px 4px rgba(60,30,10,.25)}
.hint em{font-style:normal;color:var(--brand);font-weight:800}
.wall{display:flex;gap:14px;align-items:flex-start}
.col{flex:1;min-width:0;display:flex;flex-direction:column;gap:22px}
.col:nth-child(2){padding-top:18px}
.it{position:relative;display:block;width:100%;text-align:left;color:var(--ink);transform:rotate(var(--r,0deg));transition:transform .15s}
.it:active{transform:rotate(0) scale(.97)}
/* 便签纸:话题 */
.note{padding:20px 13px 12px;min-height:150px;background:linear-gradient(170deg,var(--n1),var(--n2));border-radius:1px 1px 2px 14px/1px 1px 2px 10px;
box-shadow:0 1px 1px rgba(0,0,0,.12),0 10px 14px -8px rgba(55,25,5,.55),inset 0 -14px 18px -14px rgba(120,70,20,.18);overflow:hidden}
.note::after{content:"";position:absolute;right:0;bottom:0;width:26px;height:22px;
background:linear-gradient(135deg,rgba(0,0,0,0) 48%,rgba(90,50,20,.18) 50%,rgba(255,255,255,.55) 60%,var(--n2) 100%)}
.note .wm{position:absolute;right:6px;bottom:4px;font-size:64px;line-height:1;font-weight:900;color:var(--k);opacity:.08;font-family:var(--hand)}
.note .lb{position:relative;display:inline-block;font-size:11px;font-weight:800;color:var(--k);padding:0 6px;border:1.5px solid var(--k);border-radius:3px;line-height:17px;opacity:.9}
.note h3{position:relative;margin:8px 0 12px;font-size:15px;line-height:1.45;font-weight:900;color:#3A2618;letter-spacing:.2px}
.note h3::before{content:"# ";color:var(--k)}
.note .mt{position:relative;font-size:11px;color:#7A6250;display:flex;align-items:center;gap:6px}
.note .mt b{color:var(--k);font-weight:800}
.note .join{position:relative;display:inline-block;margin-top:8px;font-family:var(--hand);font-size:14px;color:var(--k);border-bottom:1.5px dashed var(--k);line-height:1.3}
.hot{position:absolute;top:10px;right:10px;width:32px;height:32px;border-radius:50%;border:2px solid rgba(214,58,40,.75);color:rgba(214,58,40,.85);
font-size:12px;font-weight:900;display:grid;place-items:center;transform:rotate(14deg);font-family:var(--hand)}
.hot::before{content:"";position:absolute;inset:2px;border:1px dashed rgba(214,58,40,.55);border-radius:50%}
/* 胶带(半透明 + 锯齿边) */
.tape{position:absolute;z-index:2;top:-9px;left:50%;width:62px;height:20px;margin-left:-31px;transform:rotate(var(--tr,-4deg));
background:var(--tp,rgba(255,252,240,.55));box-shadow:0 1px 2px rgba(0,0,0,.12);
-webkit-clip-path:polygon(0 8%,4% 0,8% 10%,12% 0,16% 8%,20% 0,80% 0,84% 9%,88% 0,92% 8%,96% 0,100% 10%,100% 92%,96% 100%,92% 90%,88% 100%,84% 92%,80% 100%,20% 100%,16% 90%,12% 100%,8% 92%,4% 100%,0 90%);
clip-path:polygon(0 8%,4% 0,8% 10%,12% 0,16% 8%,20% 0,80% 0,84% 9%,88% 0,92% 8%,96% 0,100% 10%,100% 92%,96% 100%,92% 90%,88% 100%,84% 92%,80% 100%,20% 100%,16% 90%,12% 100%,8% 92%,4% 100%,0 90%)}
.tape.w1{--tp:repeating-linear-gradient(45deg,rgba(255,180,190,.6) 0 6px,rgba(255,255,255,.45) 6px 12px)}
.tape.w2{--tp:repeating-linear-gradient(90deg,rgba(150,200,240,.55) 0 4px,rgba(255,255,255,.4) 4px 8px)}
.tape.w3{--tp:rgba(170,225,205,.6)}
.tape.cn{top:-6px;left:-10px;margin:0;width:46px;height:16px;--tr:-38deg}
/* 图钉 */
.pin{position:absolute;z-index:3;top:-7px;left:50%;width:16px;height:16px;margin-left:-8px;border-radius:50%;
background:radial-gradient(circle at 34% 30%,rgba(255,255,255,.9) 0 2px,var(--pc,#E2483A) 3.5px,var(--pd,#9B2418) 100%);
box-shadow:3px 4px 3px -1px rgba(40,15,0,.45)}
.pin.b{--pc:#3F7FD0;--pd:#1D4A86}.pin.g{--pc:#36A08F;--pd:#17594E}.pin.y{--pc:#F2B632;--pd:#A8740C}
/* 拍立得 */
.pola{background:#FCFAF5;padding:8px 8px 10px;border-radius:2px;
box-shadow:0 1px 1px rgba(0,0,0,.14),0 12px 16px -8px rgba(55,25,5,.55)}
.pola .ph{position:relative;aspect-ratio:4/5;overflow:hidden;background:#E8DFD2}
.pola .ph img{width:100%;height:100%;object-fit:cover;display:block;filter:saturate(.92) contrast(1.02)}
.pola .ph::after{content:"";position:absolute;inset:0;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06),inset 0 0 18px rgba(80,50,20,.18)}
.pola .cap{margin:8px 2px 0;font-family:var(--hand);font-size:15px;line-height:1.4;color:#2E2118;font-weight:700;
display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.by{display:flex;align-items:center;gap:6px;margin:8px 2px 0;font-size:11px;color:#8A7564;min-width:0}
.by img{width:18px;height:18px;border-radius:50%;object-fit:cover;flex:none}
.by .nm{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.by .lk{flex:none;display:flex;align-items:center;gap:2px}
.by .lk svg{width:12px;height:12px}
.ctag{position:absolute;z-index:2;left:14px;top:14px;font-size:11px;font-weight:800;color:#fff;padding:0 6px;line-height:18px;border-radius:2px;background:var(--k);box-shadow:0 1px 2px rgba(0,0,0,.25)}
/* 横格卡片:无图笔记 */
.card{background:#FFFDF7;padding:18px 12px 12px 22px;border-radius:2px;
background-image:linear-gradient(90deg,transparent 14px,rgba(224,86,111,.45) 14px,rgba(224,86,111,.45) 15px,transparent 15px),
repeating-linear-gradient(180deg,transparent 0 23px,rgba(70,120,190,.18) 23px 24px);
background-position:0 0,0 10px;
box-shadow:0 1px 1px rgba(0,0,0,.12),0 10px 14px -8px rgba(55,25,5,.5)}
.card .big{font-family:var(--hand);font-size:19px;font-weight:800;line-height:24px;color:var(--k)}
.card .sub{font-family:var(--hand);font-size:14px;line-height:24px;color:#5E4A3A}
.card .tt{margin-top:6px;font-size:13px;line-height:1.5;color:#3A2A1E;font-weight:600;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
/* 投稿:一叠空白便签 */
.stack{position:relative;margin:8px 4px 6px 2px;text-align:left}
.stack .sh{position:absolute;inset:0;background:#FFE58A;border-radius:1px;box-shadow:0 8px 10px -6px rgba(55,25,5,.5)}
.stack .sh.a{transform:rotate(5deg) translate(5px,4px);background:#FFD7A8}
.stack .sh.b{transform:rotate(-3.5deg) translate(-3px,3px);background:#FFF0B0}
.stack .tp{position:relative;padding:22px 12px 12px;background:linear-gradient(170deg,#FFF6C4,#FFE98E);transform:rotate(-1deg);
box-shadow:0 1px 1px rgba(0,0,0,.12),0 10px 14px -8px rgba(55,25,5,.55);
background-image:linear-gradient(170deg,#FFF6C4,#FFE98E)}
.stack .ln{height:22px;border-bottom:1.5px dashed rgba(150,100,30,.35)}
.stack .wr{font-family:var(--hand);font-size:19px;font-weight:800;color:#5A3A1A;line-height:26px;display:flex;align-items:center;gap:6px}
.stack .wr svg{width:20px;height:20px;color:var(--brand);flex:none}
.stack .rw{margin-top:8px;font-size:12px;color:#7A5A3A;line-height:1.5}
.stack .rw b{display:block;font-size:17px;color:var(--brand);font-weight:900;letter-spacing:.3px;line-height:1.35}
.stack .go{display:inline-flex;align-items:center;margin-top:8px;padding:0 10px;height:26px;border-radius:13px;background:var(--brand);color:#fff;font-size:12px;font-weight:800;box-shadow:0 2px 4px rgba(200,60,30,.35)}
.more{display:block;margin:26px auto 4px;padding:9px 18px;background:#F7EEDC;color:#5A3A22;font-size:14px;font-weight:800;transform:rotate(-1deg);box-shadow:0 6px 10px -5px rgba(55,25,5,.55)}
.foot{margin-top:18px;text-align:center;font-size:11px;color:rgba(60,30,10,.65)}
/* 投稿规则便签弹层 */
.mask{position:fixed;inset:0;z-index:50;background:rgba(40,20,5,.45);display:none;align-items:center;justify-content:center;padding:24px}
.mask.show{display:flex}
.rule{position:relative;width:100%;max-width:320px;padding:28px 20px 20px;background:linear-gradient(170deg,#FFF8D6,#FFEDA6);transform:rotate(-1deg);box-shadow:0 18px 30px -10px rgba(0,0,0,.5)}
.rule h3{margin:0 0 6px;font-family:var(--hand);font-size:22px;color:#4A2E14}
.rule .rb{font-size:13px;color:#7A5A3A}.rule .rb b{color:var(--brand);font-size:20px;font-weight:900}
.rule ol{margin:12px 0 16px;padding-left:20px;font-size:14px;line-height:1.7;color:#4A3828}
.rule .ok{display:block;width:100%;height:42px;border-radius:21px;background:var(--brand);color:#fff;font-size:15px;font-weight:800}
.rule .x{position:absolute;right:8px;top:8px;width:32px;height:32px;font-size:20px;color:#8A6A4A}
</style>
</head>
<body>
<div id="sc" class="cork">
<header class="top cork">
<div class="rail">
<button class="bk" id="back" type="button" aria-label="返回"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
<div class="ttl"><b>孕妈广场</b></div>
<div class="vtag">效果稿<br>V3·留言墙</div>
</div>
<nav class="tabs" id="tabs"></nav>
</header>
<main>
<div class="hint"><span id="hint"></span></div>
<div class="wall" id="wall"><div class="col"></div><div class="col"></div></div>
<button class="more hide" id="more" type="button">再往下翻一面墙</button>
<div class="foot">墙上内容为示例占位 · 篇数、在聊、点赞均为演示数字</div>
</main>
</div>
<div class="mask" id="mask">
<div class="rule">
<span class="tape" style="--tr:3deg"></span>
<button class="x" id="rx" type="button" aria-label="关闭">×</button>
<h3>写一张贴上来</h3>
<div class="rb">投稿被选中,每篇奖励 <b>¥30</b> 现金 + <b>500</b> 兜豆</div>
<ol><li>挑一张你有话说的话题便签</li><li>写下你的真实经历,配图更好</li><li>编辑挑中后贴上墙,奖励发给你</li></ol>
<button class="ok" id="rgo" type="button">去写我的故事</button>
</div>
</div>
<script src="../../guangchang/topics.js"></script>
<script src="../../guangchang/data.js"></script>
<script>
(function () {
var $ = function (s) { return document.querySelector(s); };
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var hs = function (s) { var x = 7; s = String(s); for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
var AV = []; for (var i = 1; i <= 22; i++) AV.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) AV.push('p' + (i < 10 ? '0' : '') + i);
var avSrc = function (n) { return '../../assets/img/mom/' + AV[hs(n) % AV.length] + '.jpg'; };
var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1) + '万' : String(n); };
var CATS = [['', '全部', '#F4593C'], ['family', '家庭婚姻', '#E0566F'], ['work', '职场', '#3A72B8'], ['baby', '经验', '#2E8A7C']];
var CN = { family: '家庭婚姻', work: '职场', baby: '经验' };
var K = { family: '#C23A55', work: '#2F64A8', baby: '#21705F' };
var PAPER = {
family: [['#FFE3E8', '#FFC9D4'], ['#FFF1C2', '#FFE08A'], ['#FFE6D6', '#FFCDB0']],
work: [['#E2EEFC', '#C3D9F4'], ['#FFF4C6', '#FFE495'], ['#E8E6FA', '#D1CDF2']],
baby: [['#DDF4EC', '#BDE6D8'], ['#F4F7C8', '#E5EC9C'], ['#FFF1C2', '#FFE08A']]
};
var PINS = ['', 'b', 'g', 'y'], TAPES = ['', 'w1', 'w2', 'w3'];
var heart = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M12 20s-7-4.4-9.2-9A5 5 0 0 1 12 6.2 5 5 0 0 1 21.2 11C19 15.6 12 20 12 20z"/></svg>';
var cat = new URLSearchParams(location.search).get('c') || '';
if (!CN[cat]) cat = '';
var LIMIT = 28, shown = LIMIT, ITEMS = [];
function go(t, n) {
location.href = '../../guangchang/?t=' + encodeURIComponent(t) + (n ? '&n=' + encodeURIComponent(n) : '') + location.hash;
}
$('#back').onclick = function () { if (history.length > 1) history.back(); else location.href = '../../' + location.hash; };
function renderTabs() {
$('#tabs').innerHTML = CATS.map(function (c) {
return '<button type="button" class="tab' + (c[0] === cat ? ' on' : '') + '" data-c="' + c[0] + '" style="--tc:' + c[2] + '"><span class="clip"></span>' + (c[0] ? '<i></i>' : '') + c[1] + '</button>';
}).join('');
}
/* 墙上元素顺序:热门话题先贴;每个话题后面钉 1 张它的笔记(有照片→拍立得,无照片→横格卡),第二轮再补剩下的笔记 */
function build() {
var list = T.filter(function (t) { return !cat || t.cat === cat; });
if (!cat) { /* 全部:三类轮流排,热门在前 */
var by = ['family', 'work', 'baby'].map(function (c) { return list.filter(function (t) { return t.cat === c; }).sort(function (a, b) { return b.hot - a.hot; }); });
list = []; for (var r = 0; r < 20; r++) by.forEach(function (a) { if (a[r]) list.push(a[r]); });
} else list = list.slice().sort(function (a, b) { return b.hot - a.hot; });
var out = [{ k: 'stack' }], rest = [];
list.forEach(function (t) {
var ns = ((D[t.id] || {}).notes || []).map(function (n, i) { return { k: 'n', t: t, n: n, i: i }; });
ns.sort(function (a, b) { return (b.n.photo ? 1 : 0) - (a.n.photo ? 1 : 0); });
out.push({ k: 't', t: t });
if (ns[0]) out.push(ns[0]);
rest = rest.concat(ns.slice(1));
});
/* 剩下的笔记:拍立得和横格卡交替钉,墙面不单调 */
var byL = function (a, b) { return b.n.likes - a.n.likes; };
var ph = rest.filter(function (o) { return o.n.photo; }).sort(byL), tx = rest.filter(function (o) { return !o.n.photo; }).sort(byL), mix = [];
while (ph.length || tx.length) { if (tx.length) mix.push(tx.shift()); if (ph.length) mix.push(ph.shift()); }
/* 话题便签 + 首篇 为主线,每 3 张插一张补充笔记,横格卡不会全挤到墙底 */
var res = [out.shift()], j = 0;
while (out.length) { res.push(out.shift()); if (++j % 3 === 0 && mix.length) res.push(mix.shift()); }
return res.concat(mix);
}
function rot(seed, amp) { return ((hs(seed) % 1000) / 1000 * 2 - 1) * amp; }
function html(o, idx) {
if (o.k === 'stack') {
return '<button type="button" class="it stack" data-w="1"><span class="sh a"></span><span class="sh b"></span><div class="tp">' +
'<span class="pin"></span><div class="wr"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20l4-1 11-11-3-3L5 16z"/><path d="M14 6l3 3"/></svg>写一张贴上来</div>' +
'<div class="ln"></div><div class="rw">被选中奖励<b>¥30 + 500 兜豆</b></div><span class="go">怎么参与 ›</span></div></button>';
}
var t = o.t, k = K[t.cat];
if (o.k === 't') {
var p = PAPER[t.cat][hs(t.id) % 3];
var tp = TAPES[hs(t.id + 'tp') % 4];
return '<button type="button" class="it note" data-t="' + t.id + '" style="--r:' + rot(t.id, 2.6).toFixed(2) + 'deg;--n1:' + p[0] + ';--n2:' + p[1] + ';--k:' + k + '">' +
'<span class="tape ' + tp + '" style="--tr:' + rot(t.id + 'r', 6).toFixed(1) + 'deg"></span>' +
'<span class="wm">' + esc(t.g) + '</span>' + (t.hot ? '<span class="hot">热</span>' : '') +
'<span class="lb">' + CN[t.cat] + '</span><h3>' + esc(t.name) + '</h3>' +
'<div class="mt"><span><b>' + t.n + '</b> 篇</span><span>·</span><span><b>' + fmt(t.talk) + '</b> 人在聊</span></div>' +
'<span class="join">+ 我也说两句</span></button>';
}
var n = o.n, nid = t.id + '-' + (o.i + 1), pin = PINS[hs(nid) % 4];
var by = '<div class="by"><img loading="lazy" src="' + avSrc(n.author) + '" alt=""><span class="nm">' + esc(n.author) + '</span><span class="lk">' + heart + fmt(n.likes) + '</span></div>';
if (n.photo) {
return '<button type="button" class="it pola" data-t="' + t.id + '" data-n="' + nid + '" style="--r:' + rot(nid, 3).toFixed(2) + 'deg;--k:' + k + '">' +
'<span class="pin ' + pin + '"></span><div class="ph"><img loading="lazy" src="../../guangchang/' + esc(n.photo) + '" alt=""></div>' +
'<span class="ctag">' + CN[t.cat] + '</span><div class="cap">' + esc(n.title) + '</div>' + by + '</button>';
}
return '<button type="button" class="it card" data-t="' + t.id + '" data-n="' + nid + '" style="--r:' + rot(nid, 2.4).toFixed(2) + 'deg;--k:' + k + '">' +
'<span class="tape cn ' + TAPES[hs(nid) % 4] + '"></span>' +
'<div class="big">' + esc(n.cover || '') + '</div>' + (n.coverSub ? '<div class="sub">' + esc(n.coverSub) + '</div>' : '') +
'<div class="tt">' + esc(n.title) + '</div>' + by + '</button>';
}
function renderWall(reset) {
var cols = document.querySelectorAll('#wall .col');
if (reset) { cols[0].innerHTML = cols[1].innerHTML = ''; ITEMS = build(); shown = Math.min(LIMIT, ITEMS.length); }
var start = reset ? 0 : +($('#wall').dataset.n || 0);
for (var i = start; i < shown; i++) {
var c = i === 0 ? cols[0] : (cols[0].offsetHeight <= cols[1].offsetHeight + 18 ? cols[0] : cols[1]);
c.insertAdjacentHTML('beforeend', html(ITEMS[i], i));
}
$('#wall').dataset.n = shown;
$('#more').classList.toggle('hide', shown >= ITEMS.length);
$('#more').style.display = shown >= ITEMS.length ? 'none' : '';
var nt = T.filter(function (t) { return !cat || t.cat === cat; }).length;
$('#hint').innerHTML = (cat ? '「' + CN[cat] + '」' : '墙上') + '贴着 <em>' + nt + '</em> 个话题 · 挑一张聊聊';
}
$('#tabs').addEventListener('click', function (e) {
var b = e.target.closest('[data-c]'); if (!b || b.dataset.c === cat) return;
cat = b.dataset.c; renderTabs(); renderWall(true); $('#sc').scrollTop = 0;
var q = new URLSearchParams(location.search); if (cat) q.set('c', cat); else q.delete('c');
var s = q.toString(); history.replaceState(history.state, '', location.pathname + (s ? '?' + s : '') + location.hash);
});
$('#wall').addEventListener('click', function (e) {
var b = e.target.closest('.it'); if (!b) return;
if (b.dataset.w) { $('#mask').classList.add('show'); return; }
go(b.dataset.t, b.dataset.n || '');
});
$('#more').onclick = function () { shown = Math.min(ITEMS.length, shown + LIMIT); renderWall(false); };
$('#rx').onclick = function () { $('#mask').classList.remove('show'); };
$('#mask').addEventListener('click', function (e) { if (e.target === this) this.classList.remove('show'); });
$('#rgo').onclick = function () { location.href = '../../guangchang/' + location.search.replace(/[?&]c=[^&]*/, '').replace(/^&/, '?') + location.hash; };
renderTabs(); renderWall(true);
/* 禁止下拉回弹:往上找能朝该方向滚的容器,找不到才拦 */
var sx = 0, sy = 0;
document.addEventListener('touchstart', function (e) { sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
document.addEventListener('touchmove', function (e) {
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
if (Math.abs(dy) <= Math.abs(dx)) return;
var el = e.target;
while (el && el !== document.body && el !== document.documentElement) {
if (el.nodeType === 1) {
var oy = getComputedStyle(el).overflowY;
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
if (dy > 0 && el.scrollTop > 0) return;
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
}
}
el = el.parentNode;
}
if (e.cancelable) e.preventDefault();
}, { passive: false });
})();
</script>
</body>
</html>

346
demo/gc-v4/index.html Normal file
View File

@@ -0,0 +1,346 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>孕妈广场</title>
<!-- 效果稿 V4 · 聊天广场:每个话题是一个「聊天室」,直接露出 2~3 条气泡;分类 = 顶部频道胶囊;投稿 = 底部输入条。演示页,不接后端。 -->
<style>
:root{
--brand:#F4593C;--bg:#F5F6F8;--card:#fff;--ink:#1F2329;--ink2:#5B6170;--ink3:#9AA0AC;--line:#ECEDF1;
--bub:#F3F4F7;--safe-t:env(safe-area-inset-top);--safe-b:env(safe-area-inset-bottom);
}
.k-family{--kf:#E0566F;--kl:#FDECEF}
.k-work{--kf:#3A72B8;--kl:#E9F0FA}
.k-baby{--kf:#2E8A7C;--kl:#E4F3F0}
.k-all{--kf:#F4593C;--kl:#FEEDE8}
*{box-sizing:border-box;margin:0;padding:0;-webkit-tap-highlight-color:transparent}
html,body{height:100%;overflow:hidden;background:var(--bg)}
body{font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Segoe UI",Roboto,sans-serif;color:var(--ink);font-size:14px;-webkit-font-smoothing:antialiased}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
img{display:block}
#sc{position:fixed;inset:0;overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
/* ---------- 顶部 ---------- */
.top{position:sticky;top:0;z-index:20;padding-top:var(--safe-t);background:rgba(255,255,255,.88);-webkit-backdrop-filter:blur(16px) saturate(170%);backdrop-filter:blur(16px) saturate(170%);transition:box-shadow .2s}
.top.on{box-shadow:0 1px 0 var(--line),0 6px 18px rgba(30,35,45,.05)}
.nav{height:46px;display:flex;align-items:center;padding:0 12px 0 6px;position:relative}
.back{width:38px;height:38px;display:flex;align-items:center;justify-content:center;border-radius:50%}
.back:active{background:rgba(0,0,0,.05)}
.nav h1{font-size:17px;font-weight:700;margin-left:2px;letter-spacing:.5px}
.nav .ver{position:absolute;right:12px;top:50%;transform:translateY(-50%);font-size:11px;color:#B5BAC4;letter-spacing:.3px}
/* 频道胶囊 */
.chs{display:flex;gap:8px;padding:2px 14px 10px;overflow-x:auto;scrollbar-width:none}
.chs::-webkit-scrollbar{display:none}
.ch{flex:none;height:32px;padding:0 14px 0 11px;border-radius:16px;background:#F1F2F5;color:var(--ink2);font-size:14px;font-weight:600;display:flex;align-items:center;gap:3px;transition:background .2s,color .2s}
.ch i{font-style:normal;font-weight:800;color:var(--kf);opacity:.85}
.ch small{font-size:11px;font-weight:500;color:var(--ink3);margin-left:3px}
.ch.on{background:var(--kf);color:#fff;box-shadow:0 4px 12px -4px var(--kf)}
.ch.on i,.ch.on small{color:rgba(255,255,255,.85);opacity:1}
/* ---------- 此刻在线 ---------- */
.live{margin:12px 14px 4px;padding:14px 14px 13px;border-radius:18px;background:#fff;position:relative;overflow:hidden}
.live::before{content:"";position:absolute;right:-30px;top:-40px;width:150px;height:150px;border-radius:50%;background:radial-gradient(circle,rgba(244,89,60,.10),rgba(244,89,60,0) 70%)}
.lv-h{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink2);position:relative}
.dot{width:8px;height:8px;border-radius:50%;background:#2BC266;position:relative;flex:none}
.dot::after{content:"";position:absolute;inset:-4px;border-radius:50%;background:#2BC266;opacity:.35;animation:pulse 1.8s ease-out infinite}
@keyframes pulse{0%{transform:scale(.4);opacity:.5}100%{transform:scale(1.4);opacity:0}}
.lv-h b{font-size:20px;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:.3px}
.lv-h .u{color:var(--ink)}
.lv-row{display:flex;align-items:flex-end;gap:6px;justify-content:space-between;margin-top:12px;overflow:hidden;position:relative}
.sp{flex:none;width:48px;display:flex;flex-direction:column;align-items:center;gap:5px}
.sp .av{width:44px;height:44px;border-radius:50%;object-fit:cover;background:#eee;border:2px solid #fff;box-shadow:0 0 0 2px #EFEFF2}
.sp.talk .av{box-shadow:0 0 0 2px #2BC266}
.sp span{font-size:11px;color:var(--ink3);max-width:52px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sp .wv{position:absolute;margin:30px 0 0 30px;width:18px;height:18px;border-radius:50%;background:#2BC266;border:2px solid #fff;display:flex;align-items:center;justify-content:center;gap:1.5px}
.sp .wv i{width:2px;height:6px;border-radius:1px;background:#fff;animation:wv .9s ease-in-out infinite}
.sp .wv i:nth-child(2){animation-delay:.15s}.sp .wv i:nth-child(3){animation-delay:.3s}
@keyframes wv{0%,100%{transform:scaleY(.45)}50%{transform:scaleY(1.15)}}
.sp{position:relative}
.lv-tk{margin-top:12px;height:20px;overflow:hidden;font-size:12px;color:var(--ink3);position:relative}
.lv-tk div{height:20px;line-height:20px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:transform .5s}
.lv-tk b{color:var(--ink2);font-weight:600}
/* ---------- 分区标题 ---------- */
.sec{display:flex;align-items:baseline;justify-content:space-between;padding:16px 18px 8px}
.sec h2{font-size:16px;font-weight:700}
.sec span{font-size:12px;color:var(--ink3)}
/* ---------- 聊天室卡片 ---------- */
.feed{padding:0 12px}
.room{background:#fff;border-radius:20px;margin-bottom:12px;padding:14px 14px 0;position:relative;overflow:hidden}
.room:active{transform:scale(.995)}
.rh{display:flex;gap:10px;align-items:flex-start;padding-bottom:12px;border-bottom:1px solid var(--line)}
.rh .ic{flex:none;width:40px;height:40px;border-radius:13px;background:var(--kl);color:var(--kf);display:flex;align-items:center;justify-content:center;font-size:19px;font-weight:800;position:relative}
.rh .ic em{position:absolute;right:-3px;top:-3px;font-style:normal;font-size:10px;line-height:15px;height:15px;padding:0 4px;border-radius:8px;background:var(--brand);color:#fff;font-weight:700;border:1.5px solid #fff}
.rh .tt{flex:1;min-width:0}
.rh h3{font-size:15px;font-weight:700;line-height:1.4;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rh .mt{margin-top:3px;font-size:12px;color:var(--ink3);display:flex;align-items:center;gap:6px;white-space:nowrap}
.rh .mt .chn{color:var(--kf);font-weight:600}
.rh .mt .on{display:inline-flex;align-items:center;gap:4px}
.rh .mt .on::before{content:"";width:6px;height:6px;border-radius:50%;background:#2BC266}
.msgs{padding:12px 0 4px}
.m{display:flex;gap:9px;margin-bottom:12px}
.m .av{flex:none;width:34px;height:34px;border-radius:50%;object-fit:cover;background:#eee}
.m .bd{min-width:0;flex:1;display:flex;flex-direction:column;align-items:flex-start}
.m .who{font-size:12px;color:var(--ink3);margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.m .who b{color:var(--ink2);font-weight:600;margin-right:6px}
.m .who .wk{display:inline-block;font-size:11px;line-height:16px;padding:0 6px;border-radius:8px;background:var(--kl);color:var(--kf);font-weight:600}
.bb{position:relative;max-width:92%;background:var(--bub);border-radius:4px 16px 16px 16px;padding:9px 12px;font-size:14px;line-height:1.55;color:var(--ink)}
.bb .q{font-weight:700;display:block;margin-bottom:2px}
.bb .s{color:var(--ink2);display:-webkit-box;-webkit-line-clamp:var(--cl,2);-webkit-box-orient:vertical;overflow:hidden}
.bb.rp{font-size:14px}
.bb.rp .at{color:var(--kf);font-weight:600;margin-right:3px}
.pic{position:relative;margin-top:6px;width:108px;height:144px;border-radius:4px 14px 14px 14px;overflow:hidden;background:#EDEEF1}
.pic img{width:100%;height:100%;object-fit:cover}
.pic::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px rgba(0,0,0,.04)}
.lk{margin-top:5px;font-size:11px;color:var(--ink3);display:flex;align-items:center;gap:3px}
.lk svg{width:12px;height:12px}
.rf{display:flex;align-items:center;justify-content:space-between;padding:10px 0 13px;border-top:1px dashed var(--line)}
.typing{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--ink3);min-width:0}
.stack{display:flex;flex:none}
.stack img{width:20px;height:20px;border-radius:50%;object-fit:cover;border:1.5px solid #fff;margin-left:-6px;background:#eee}
.stack img:first-child{margin-left:0}
.typing .tx{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.typing .tx b{color:var(--ink2);font-weight:600}
.dots{display:inline-flex;gap:2px;margin-left:2px;vertical-align:middle}
.dots i{width:3px;height:3px;border-radius:50%;background:var(--ink3);animation:db 1.2s infinite}
.dots i:nth-child(2){animation-delay:.2s}.dots i:nth-child(3){animation-delay:.4s}
@keyframes db{0%,60%,100%{opacity:.25}30%{opacity:1}}
.go{flex:none;height:30px;padding:0 12px;border-radius:15px;background:var(--kl);color:var(--kf);font-size:13px;font-weight:700;display:flex;align-items:center;gap:2px}
.go svg{width:12px;height:12px}
.foot{padding:6px 0 20px;text-align:center;font-size:11px;color:#B5BAC4}
.pad{height:calc(84px + var(--safe-b))}
/* ---------- 底部输入条 ---------- */
.bar{position:fixed;left:0;right:0;bottom:0;z-index:30;padding:8px 12px calc(8px + var(--safe-b));background:rgba(255,255,255,.92);-webkit-backdrop-filter:blur(16px) saturate(170%);backdrop-filter:blur(16px) saturate(170%);box-shadow:0 -1px 0 var(--line)}
.ipt{display:flex;align-items:center;gap:8px;height:44px}
.ipt .me{flex:none;width:34px;height:34px;border-radius:50%;background:linear-gradient(135deg,#FFD9CF,#FFB8A6);display:flex;align-items:center;justify-content:center;color:#fff}
.ipt .me svg{width:18px;height:18px}
.field{flex:1;min-width:0;height:40px;border-radius:20px;background:#F1F2F5;display:flex;align-items:center;padding:0 6px 0 14px;gap:6px;text-align:left}
.field .ph{flex:1;min-width:0;font-size:13.5px;color:var(--ink3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.field .ph em{font-style:normal;color:var(--brand);font-weight:700}
.field .cur{width:1.5px;height:16px;background:var(--brand);animation:blink 1s steps(1) infinite;flex:none;margin-right:-2px}
@keyframes blink{50%{opacity:0}}
.send{flex:none;height:30px;padding:0 13px;border-radius:15px;background:var(--brand);color:#fff;font-size:13px;font-weight:700;display:flex;align-items:center}
/* ---------- 弹层 ---------- */
.mask{position:fixed;inset:0;z-index:50;background:rgba(20,22,28,.42);opacity:0;pointer-events:none;transition:opacity .25s}
.mask.on{opacity:1;pointer-events:auto}
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:51;background:#fff;border-radius:22px 22px 0 0;padding:10px 18px calc(18px + var(--safe-b));transform:translateY(105%);transition:transform .3s cubic-bezier(.2,.8,.2,1)}
.sheet.on{transform:none}
.sheet .gb{width:36px;height:4px;border-radius:2px;background:#E1E3E8;margin:0 auto 14px}
.sheet h3{font-size:17px;font-weight:700;text-align:center}
.rw{margin:14px 0;padding:14px;border-radius:16px;background:#FFF3EF;display:flex;align-items:center;gap:12px}
.rw b{font-size:24px;color:var(--brand);font-weight:800;white-space:nowrap}
.rw b small{font-size:14px;font-weight:700;margin:0 2px}
.rw span{font-size:12px;color:var(--ink2);line-height:1.5}
.sheet ol{padding-left:18px;font-size:13px;color:var(--ink2);line-height:1.8}
.sheet .btn{margin-top:16px;width:100%;height:46px;border-radius:23px;background:var(--brand);color:#fff;font-size:15px;font-weight:700}
</style>
</head>
<body>
<div id="sc">
<header class="top" id="top">
<div class="nav">
<button class="back" id="back" type="button" aria-label="返回"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#1F2329" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 5l-7 7 7 7"/></svg></button>
<h1>孕妈广场</h1>
<span class="ver">效果稿 V4 · 聊天广场</span>
</div>
<nav class="chs" id="chs"></nav>
</header>
<section class="live">
<div class="lv-h"><span class="dot"></span>此刻在线 <b id="onl">12,486</b> <span class="u">位孕妈</span></div>
<div class="lv-row" id="spk"></div>
<div class="lv-tk" id="tk"></div>
</section>
<div class="sec"><h2 id="secT">大家正在聊</h2><span id="secN"></span></div>
<main class="feed" id="feed"></main>
<div class="foot">话题与内容为示例占位</div>
<div class="pad"></div>
</div>
<div class="bar">
<div class="ipt">
<button class="field" id="post" type="button"><span class="cur"></span><span class="ph">说说你的故事,被选中 <em>¥30+500 兜豆</em></span><span class="send">投稿</span></button>
</div>
</div>
<div class="mask" id="mask"></div>
<div class="sheet" id="sheet">
<div class="gb"></div>
<h3>说说你的故事</h3>
<div class="rw"><b>¥<small></small>30<small>+</small>500</b><span>投稿被选中,每篇奖励 30 元现金 + 500 兜豆</span></div>
<ol>
<li>挑一个话题,写下你自己的真实经历</li>
<li>提交后进入审核,通过即展示在广场</li>
<li>被选中的稿件,工作人员会尽快发放奖励</li>
</ol>
<button class="btn" id="goPost" type="button">去投稿</button>
</div>
<script src="../../guangchang/topics.js"></script>
<script src="../../guangchang/data.js"></script>
<script>
(function () {
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
var $ = function (s) { return document.querySelector(s); };
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var hs = function (s) { var x = 7; s = String(s); for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
var POOL = [];
for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i);
for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
var av = function (name) { return '../../assets/img/mom/' + POOL[hs(name) % POOL.length] + '.jpg'; };
var fmt = function (n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ','); };
var first = function (b) { var s = String(b || '').split('\n')[0]; var m = s.match(/^[^。!?!?]*[。!?!?]/); s = m ? m[0] : s; return s.length > 60 ? s.slice(0, 58) + '…' : s; };
var CH = [['all', '全部'], ['family', '家庭婚姻'], ['work', '职场'], ['baby', '经验']];
var CHN = { family: '家庭婚姻', work: '职场', baby: '经验' };
var cur = 'all';
var heart = '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 21s-7.5-4.6-9.6-9.2C.9 8.4 3 4.5 6.7 4.5c2.1 0 3.6 1.1 4.3 2.4h2c.7-1.3 2.2-2.4 4.3-2.4 3.7 0 5.8 3.9 4.3 7.3C19.5 16.4 12 21 12 21z"/></svg>';
var arrow = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5l7 7-7 7"/></svg>';
var detail = function (tid, idx) { return '../../guangchang/?t=' + tid + (idx ? '&n=' + tid + '-' + idx : '') + location.hash; };
/* 频道 */
function renderCh() {
$('#chs').innerHTML = CH.map(function (c) {
return '<button type="button" class="ch k-' + c[0] + (cur === c[0] ? ' on' : '') + '" data-c="' + c[0] + '"><i>#</i>' + c[1] + '</button>';
}).join('');
}
$('#chs').addEventListener('click', function (e) {
var b = e.target.closest('.ch'); if (!b || b.dataset.c === cur) return;
cur = b.dataset.c; renderCh(); renderFeed(); renderLive();
var top = $('.sec').offsetTop - $('#top').offsetHeight;
if ($('#sc').scrollTop > top) $('#sc').scrollTop = top;
});
/* 列表:全部 = 三块轮流排、热门在前 */
function list() {
var by = { family: [], work: [], baby: [] };
T.forEach(function (t) { (by[t.cat] = by[t.cat] || []).push(t); });
Object.keys(by).forEach(function (k) { by[k].sort(function (a, b) { return b.hot - a.hot || b.talk - a.talk; }); });
if (cur !== 'all') return by[cur] || [];
var out = [], ks = ['family', 'work', 'baby'], mx = Math.max(by.family.length, by.work.length, by.baby.length);
for (var i = 0; i < mx; i++) ks.forEach(function (k) { if (by[k][i]) out.push(by[k][i]); });
return out;
}
function msg(name, stage, inner, tid, idx) {
return '<div class="m" data-t="' + tid + '"' + (idx ? ' data-n="' + idx + '"' : '') + '>' +
'<img class="av" loading="lazy" src="' + av(name) + '" alt="">' +
'<div class="bd"><div class="who"><b>' + esc(name) + '</b>' + (stage ? '<span class="wk">' + esc(stage.replace(/\s+/g, '')) + '</span>' : '') + '</div>' + inner + '</div></div>';
}
function room(t) {
var d = D[t.id] || { notes: [], comments: [] }, ns = d.notes || [], h = '';
/* 第一条:带照片的笔记优先,文字气泡 + 图片消息 */
var order = ns.map(function (n, i) { return i; }).sort(function (a, b) { return (ns[b].photo ? 1 : 0) - (ns[a].photo ? 1 : 0); });
var a = order[0], b = order[1];
if (ns[a]) {
var n = ns[a];
h += msg(n.author, n.stage,
'<div class="bb"><span class="q">' + esc(n.title) + '</span><span class="s">' + esc(first(n.body)) + '</span></div>' +
(n.photo ? '<div class="pic"><img loading="lazy" src="../../guangchang/' + n.photo + '" alt=""></div>' : '') +
'<div class="lk">' + heart + fmt(n.likes) + ' 人抱抱</div>', t.id, a + 1);
}
/* 第二条:一句评论回复,像群里接话 */
var cm = (d.comments || [])[hs(t.id) % Math.max(1, (d.comments || []).length)];
if (cm && ns[a]) {
h += msg(cm.n, cm.s, '<div class="bb rp"><span class="at">@' + esc(ns[a].author) + '</span>' + esc(cm.t) + '</div>', t.id, a + 1);
}
/* 第三条:另一篇笔记 */
if (ns[b]) {
var m = ns[b];
h += msg(m.author, m.stage, '<div class="bb" style="--cl:1"><span class="q">' + esc(m.title) + '</span><span class="s">' + esc(first(m.body)) + '</span></div>', t.id, b + 1);
}
var tp = (d.comments || []).slice(0, 3).map(function (c) { return c.n; });
var who = tp[(hs(t.id) >> 3) % Math.max(1, tp.length)] || '有人';
return '<article class="room k-' + t.cat + '" data-t="' + t.id + '">' +
'<div class="rh"><span class="ic">' + esc(t.g) + (t.hot ? '<em>热</em>' : '') + '</span>' +
'<div class="tt"><h3>' + esc(t.name) + '</h3><div class="mt"><span class="chn"># ' + CHN[t.cat] + '</span><span class="on">' + fmt(Math.round(t.talk / 9)) + ' 人在线</span><span>' + fmt(t.n) + ' 篇</span></div></div></div>' +
'<div class="msgs">' + h + '</div>' +
'<div class="rf"><div class="typing"><span class="stack">' + tp.map(function (n) { return '<img loading="lazy" src="' + av(n) + '" alt="">'; }).join('') + '</span>' +
'<span class="tx">还有 <b>' + fmt(t.talk) + '</b> 人在聊<span class="dots"><i></i><i></i><i></i></span></span></div>' +
'<span class="go">进去听听' + arrow + '</span></div></article>';
}
function renderFeed() {
var L = list();
$('#feed').innerHTML = L.map(room).join('');
$('#secT').textContent = cur === 'all' ? '大家正在聊' : '# ' + CHN[cur] + ' 频道';
$('#secN').textContent = L.length + ' 个聊天室';
}
$('#feed').addEventListener('click', function (e) {
var r = e.target.closest('.room'); if (!r) return;
var m = e.target.closest('.m');
location.href = detail(r.dataset.t, m && m.dataset.n);
});
/* 此刻在线:正在说话的头像 + 滚动播报 */
var tkTimer = null;
function renderLive() {
var L = list(), seen = {}, sp = [];
L.forEach(function (t) { (D[t.id] && D[t.id].notes || []).forEach(function (n) { if (!seen[n.author] && sp.length < 7) { seen[n.author] = 1; sp.push({ n: n.author, t: t }); } }); });
sp = sp.slice(0, 6);
$('#spk').innerHTML = sp.map(function (s, i) {
return '<button type="button" class="sp' + (i < 3 ? ' talk' : '') + '" data-t="' + s.t.id + '"><img class="av" src="' + av(s.n) + '" alt="">' +
(i < 3 ? '<span class="wv"><i></i><i></i><i></i></span>' : '') + '<span>' + esc(s.n) + '</span></button>';
}).join('');
var base = cur === 'all' ? 12486 : { family: 5210, work: 3874, baby: 3402 }[cur];
$('#onl').textContent = fmt(base);
var lines = [];
L.slice(0, 8).forEach(function (t) { var c = (D[t.id] && D[t.id].comments || [])[0]; if (c) lines.push('<b>' + esc(c.n) + '</b> 在「' + esc(t.name) + '」里说:' + esc(c.t)); });
var tk = $('#tk'), k = 0;
tk.innerHTML = '<div>' + (lines[0] || '') + '</div>';
clearInterval(tkTimer);
tkTimer = setInterval(function () {
k = (k + 1) % lines.length;
var d = document.createElement('div'); d.innerHTML = lines[k];
tk.appendChild(d);
[].forEach.call(tk.children, function (c) { c.style.transform = 'translateY(-20px)'; });
setTimeout(function () { if (tk.children.length > 1) tk.removeChild(tk.children[0]); [].forEach.call(tk.children, function (c) { c.style.transition = 'none'; c.style.transform = 'none'; c.offsetHeight; c.style.transition = ''; }); }, 520);
}, 3200);
}
$('#spk').addEventListener('click', function (e) { var b = e.target.closest('.sp'); if (b) location.href = detail(b.dataset.t); });
/* 投稿 */
var openS = function (on) { $('#mask').classList.toggle('on', on); $('#sheet').classList.toggle('on', on); };
$('#post').addEventListener('click', function () { openS(true); });
$('#mask').addEventListener('click', function () { openS(false); });
$('#goPost').addEventListener('click', function () { location.href = '../../guangchang/' + location.hash; });
$('#back').addEventListener('click', function () { history.length > 1 ? history.back() : location.href = '../../' + location.hash; });
var sc = $('#sc');
sc.addEventListener('scroll', function () { $('#top').classList.toggle('on', sc.scrollTop > 4); }, { passive: true });
/* 禁止下拉回弹:从手指下往上找还能朝该方向滚的容器,找不到才拦 */
var sx = 0, sy = 0;
document.addEventListener('touchstart', function (e) { if (e.touches.length !== 1) return; sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
document.addEventListener('touchmove', function (e) {
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
if (Math.abs(dy) <= Math.abs(dx)) return;
var el = e.target;
while (el && el !== document.body && el !== document.documentElement) {
if (el.nodeType === 1) {
var oy = getComputedStyle(el).overflowY;
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
if (dy > 0 && el.scrollTop > 0) return;
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
}
}
el = el.parentNode;
}
if (e.cancelable) e.preventDefault();
}, { passive: false });
renderCh(); renderFeed(); renderLive();
})();
</script>
</body>
</html>

436
demo/gc-v5/index.html Normal file
View File

@@ -0,0 +1,436 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<title>孕妈广场 · 效果稿 V5</title>
<!-- 效果稿 V5 · 今日广场:今日一问 + 故事卡堆 + 话题榜。演示页,独立文件,不接后端。 -->
<style>
:root{
--brand:#F4593C;--brand-2:#FF8A5B;--ink:#231B18;--ink-2:#5E534E;--muted:#9A8C86;--line:#EFE6E1;
--bg:#FBF7F4;--card:#fff;
--family:#E0566F;--work:#3A72B8;--baby:#2E8A7C;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;padding:0;height:100%;overflow:hidden;overscroll-behavior:none}
body{background:var(--bg);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","Noto Sans CJK SC","Source Han Sans SC","Segoe UI",Roboto,sans-serif;
font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%}
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
a{color:inherit;text-decoration:none}
.ic{width:16px;height:16px;flex:none;display:inline-block;vertical-align:middle}
#sc{position:fixed;inset:0;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:none;background:var(--bg)}
#sc::-webkit-scrollbar{display:none}
/* ---------- 顶栏 ---------- */
.top{position:sticky;top:0;z-index:30;padding-top:env(safe-area-inset-top);background:rgba(251,247,244,.88);-webkit-backdrop-filter:blur(14px) saturate(160%);backdrop-filter:blur(14px) saturate(160%);transition:box-shadow .2s}
.top.on{box-shadow:0 1px 0 var(--line)}
.nav{position:relative;display:flex;align-items:center;height:48px;padding:0 8px}
.nav .bk{width:38px;height:38px;display:grid;place-items:center;border-radius:50%}
.nav .bk:active{background:rgba(0,0,0,.05)}
.nav .bk .ic{width:22px;height:22px}
.nav .tt{margin-left:2px;display:flex;align-items:baseline;gap:8px;min-width:0}
.nav .tt b{font-size:18px;font-weight:900;letter-spacing:.5px}
.nav .tt small{font-size:12px;font-weight:700;color:var(--muted);white-space:nowrap}
.ver{position:absolute;right:12px;max-width:40%;white-space:nowrap;top:50%;transform:translateY(-50%);font-size:11px;color:#BBADA6;letter-spacing:.3px}
/* ---------- 区块标题(编号 + 标题,做节奏) ---------- */
.sh{display:flex;align-items:flex-end;gap:8px;margin:26px 18px 12px}
.sh .no{font-size:12px;font-weight:900;color:var(--brand);letter-spacing:1px;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif;padding-bottom:3px}
.sh h2{margin:0;font-size:20px;font-weight:900;letter-spacing:.5px;line-height:1.2}
.sh small{margin-left:auto;font-size:12px;font-weight:600;color:var(--muted);white-space:nowrap;padding-bottom:2px}
/* ---------- 01 今日一问 ---------- */
.q{position:relative;margin:6px 14px 0;padding:20px 18px 18px;border-radius:26px;overflow:hidden;color:#fff;
background:radial-gradient(180px 160px at 108% -10%,rgba(255,175,120,.55),transparent 70%),radial-gradient(200px 150px at -10% 110%,rgba(244,89,60,.45),transparent 70%),linear-gradient(160deg,#3A2A25,#231B18 70%);
box-shadow:0 18px 34px -20px rgba(35,27,24,.75)}
.q .wm{position:absolute;right:-6px;bottom:-34px;font-size:150px;font-weight:900;line-height:1;color:rgba(255,255,255,.05);pointer-events:none}
.q .hd{display:flex;align-items:center;gap:8px}
.q .tag{display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 10px;border-radius:99px;background:var(--brand);font-size:12px;font-weight:800;letter-spacing:.5px}
.q .tag i{width:6px;height:6px;border-radius:50%;background:#fff;animation:blink 1.6s infinite}
@keyframes blink{50%{opacity:.25}}
.q .dt{font-size:12px;color:rgba(255,255,255,.6);font-weight:600}
.q .cat{margin-left:auto;font-size:12px;font-weight:700;color:rgba(255,255,255,.75)}
.q h3{position:relative;margin:14px 0 4px;font-size:23px;line-height:1.35;font-weight:900;letter-spacing:.3px}
.q .sub{position:relative;margin:0;font-size:13px;color:rgba(255,255,255,.66)}
.q .ops{position:relative;display:flex;flex-direction:column;gap:10px;margin-top:16px}
.op{position:relative;display:flex;align-items:center;gap:10px;min-height:50px;padding:0 14px;border-radius:16px;overflow:hidden;text-align:left;
background:rgba(255,255,255,.1);border:1.5px solid rgba(255,255,255,.16);font-size:15px;font-weight:800;transition:transform .15s}
.op:active{transform:scale(.98)}
.op .bar{position:absolute;left:0;top:0;bottom:0;width:0;background:rgba(255,255,255,.12);transition:width .7s cubic-bezier(.2,.8,.2,1)}
.op .lt{position:relative;width:24px;height:24px;flex:none;display:grid;place-items:center;border-radius:8px;background:rgba(255,255,255,.16);font-size:12px;font-weight:900}
.op .tx{position:relative;flex:1;min-width:0;line-height:1.35;padding:12px 0}
.op .pc{position:relative;font-size:16px;font-weight:900;opacity:0;transition:opacity .4s .3s;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif}
.q.done .op .pc{opacity:1}
.q.done .op.me{border-color:#FFB08F}
.q.done .op.me .bar{background:linear-gradient(90deg,#F4593C,#FF8A5B)}
.q.done .op.me .lt{background:#fff;color:var(--brand)}
.q .ft{position:relative;display:flex;align-items:center;gap:10px;margin-top:16px;min-height:34px}
.q .avs{display:flex}
.q .avs img{width:26px;height:26px;border-radius:50%;object-fit:cover;border:2px solid #2E221E;margin-left:-8px}
.q .avs img:first-child{margin-left:0}
.q .ft small{font-size:12px;color:rgba(255,255,255,.7);flex:1;min-width:0}
.q .go{display:none;align-items:center;gap:3px;height:34px;padding:0 14px;border-radius:99px;background:#fff;color:var(--ink);font-size:13px;font-weight:900;white-space:nowrap}
.q.done .go{display:inline-flex;animation:pop .35s}
.q .go .ic{width:14px;height:14px;color:var(--brand)}
@keyframes pop{from{transform:scale(.85);opacity:0}}
/* ---------- 02 故事卡堆 ---------- */
.stk-wrap{position:relative;margin:0 14px}
.stk{position:relative;height:440px;touch-action:pan-y;user-select:none;-webkit-user-select:none}
.sc{position:absolute;left:0;right:0;top:0;height:410px;border-radius:26px;overflow:hidden;background:#E9DED8;
box-shadow:0 18px 30px -18px rgba(60,35,25,.55);transform-origin:50% 100%;will-change:transform;transition:transform .45s cubic-bezier(.2,.8,.2,1),opacity .35s}
.sc img.ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;pointer-events:none}
.sc .sh2{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.28) 0,rgba(0,0,0,0) 26%,rgba(0,0,0,0) 46%,rgba(20,10,6,.82) 100%)}
.sc .kt{position:absolute;left:14px;top:14px;display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 10px;border-radius:99px;background:rgba(255,255,255,.92);font-size:12px;font-weight:800}
.sc .kt i{width:7px;height:7px;border-radius:50%}
.sc .lk{position:absolute;right:14px;top:14px;display:inline-flex;align-items:center;gap:4px;height:26px;padding:0 10px;border-radius:99px;background:rgba(0,0,0,.32);color:#fff;font-size:12px;font-weight:700;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.sc .lk .ic{width:13px;height:13px}
.sc .bt{position:absolute;left:0;right:0;bottom:0;padding:0 18px 18px;color:#fff}
.sc .tp{font-size:12px;font-weight:700;color:rgba(255,255,255,.75);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sc h4{margin:6px 0 12px;font-size:20px;line-height:1.38;font-weight:900;letter-spacing:.2px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;text-shadow:0 1px 8px rgba(0,0,0,.25)}
.sc .au{display:flex;align-items:center;gap:9px}
.sc .au img{width:32px;height:32px;border-radius:50%;object-fit:cover;border:2px solid rgba(255,255,255,.85)}
.sc .au b{font-size:14px;font-weight:800}
.sc .au span{display:inline-flex;align-items:center;height:22px;padding:0 8px;border-radius:99px;background:rgba(255,255,255,.2);font-size:12px;font-weight:700;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.sc .au .rd{margin-left:auto;display:inline-flex;align-items:center;gap:2px;font-size:12.5px;font-weight:800;color:#FFD9C9}
.sc .au .rd .ic{width:13px;height:13px}
/* 最后一张:轮到你了 */
.sc.you{background:radial-gradient(220px 180px at 100% 0,rgba(255,255,255,.35),transparent 70%),radial-gradient(240px 200px at 0 100%,rgba(255,206,120,.4),transparent 70%),linear-gradient(155deg,#FF8A5B,#F4593C 55%,#E2402F);color:#fff}
.you .in{position:absolute;inset:0;display:flex;flex-direction:column;padding:24px 22px 22px}
.you .big{font-size:40px;font-weight:900;line-height:1.1;letter-spacing:1px;margin-top:10px}
.you .lede{margin:12px 0 0;font-size:14.5px;line-height:1.6;color:rgba(255,255,255,.92)}
.you .rw{margin-top:auto;padding:14px 16px;border-radius:18px;background:rgba(255,255,255,.18);border:1px dashed rgba(255,255,255,.55)}
.you .rw small{display:block;font-size:12px;font-weight:700;opacity:.9}
.you .rw b{display:block;margin-top:2px;font-size:18px;font-weight:900;white-space:nowrap}
.you .rw b em{font-style:normal;font-size:24px;color:#FFF3B8;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif}
.you .cta{display:flex;align-items:center;justify-content:center;gap:4px;margin-top:12px;height:48px;border-radius:99px;background:#fff;color:#E2402F;font-size:16px;font-weight:900}
.you .pen{position:absolute;right:18px;top:20px;width:58px;height:58px;border-radius:18px;background:rgba(255,255,255,.2);display:grid;place-items:center;transform:rotate(8deg)}
.you .pen .ic{width:30px;height:30px}
.you .k{font-size:12px;font-weight:800;letter-spacing:2px;opacity:.85}
/* 卡堆下方控制条 */
.stk-ctl{display:flex;align-items:center;gap:10px;margin:2px 4px 0}
.stk-ctl .pg{font-size:13px;font-weight:800;color:var(--ink-2);font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif;min-width:52px}
.stk-ctl .pg b{color:var(--brand);font-size:18px}
.stk-ctl .tr{flex:1;height:4px;border-radius:99px;background:#EDE2DC;overflow:hidden}
.stk-ctl .tr i{display:block;height:100%;width:0;border-radius:99px;background:linear-gradient(90deg,#FF8A5B,#F4593C);transition:width .35s}
.stk-ctl button{width:38px;height:38px;border-radius:50%;display:grid;place-items:center;background:#fff;box-shadow:0 4px 12px -6px rgba(90,50,30,.35);color:var(--ink)}
.stk-ctl button:active{transform:scale(.94)}
.stk-ctl button:disabled{opacity:.35}
.stk-ctl button .ic{width:18px;height:18px}
.hint{margin:8px 4px 0;font-size:12px;color:var(--muted);text-align:center}
/* ---------- 03 话题榜 ---------- */
.tabs{position:sticky;top:calc(48px + env(safe-area-inset-top));z-index:20;display:flex;gap:8px;padding:10px 14px;background:rgba(251,247,244,.92);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);overflow-x:auto}
.tabs::-webkit-scrollbar{display:none}
.tabs button{flex:none;display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 15px;border-radius:99px;background:#fff;border:1.5px solid var(--line);font-size:14px;font-weight:800;color:var(--ink-2);transition:all .2s}
.tabs button i{width:8px;height:8px;border-radius:50%;background:var(--k)}
.tabs button.on{background:var(--k);border-color:var(--k);color:#fff}
.tabs button.on i{background:#fff}
.rank{margin:4px 14px 0;padding:6px 0;border-radius:24px;background:#fff;box-shadow:0 10px 26px -20px rgba(90,50,30,.5)}
.rk{display:flex;align-items:center;gap:12px;padding:12px 16px;position:relative}
.rk + .rk:before{content:"";position:absolute;left:60px;right:16px;top:0;height:1px;background:var(--line)}
.rk:active{background:#FBF5F2}
.rk .n{width:30px;flex:none;text-align:center;font-size:22px;font-weight:900;font-style:italic;color:#CDBFB8;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif;line-height:1}
.rk.t1 .n,.rk.t2 .n,.rk.t3 .n{color:var(--brand)}
.rk.t1 .n{font-size:28px}
.rk .bd{flex:1;min-width:0}
.rk .nm{display:flex;align-items:center;gap:6px}
.rk .nm b{font-size:15px;font-weight:800;line-height:1.4;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;min-width:0}
.rk .kc{flex:none;font-size:11px;font-weight:800;color:var(--k);line-height:1}
.rk .hot{flex:none;height:18px;padding:0 5px;border-radius:5px;background:#FFE7DF;color:var(--brand);font-size:11px;font-weight:900;line-height:18px}
.rk .mt{display:flex;align-items:center;gap:8px;margin-top:7px}
.rk .hb{flex:1;height:6px;border-radius:99px;background:#F4ECE8;overflow:hidden}
.rk .hb i{display:block;height:100%;border-radius:99px;background:linear-gradient(90deg,var(--k2),var(--k));width:0;transition:width .8s cubic-bezier(.2,.8,.2,1)}
.rk .tk{flex:none;font-size:12px;font-weight:700;color:var(--muted);min-width:66px;text-align:right}
.rk .tk em{font-style:normal;color:var(--ink-2);font-weight:900}
.rk .th{width:52px;height:52px;flex:none;border-radius:12px;object-fit:cover;background:#EEE}
.rk-ft{display:flex;align-items:center;justify-content:center;gap:4px;margin:12px 14px 0;height:44px;border-radius:16px;border:1.5px dashed #E6D7D0;font-size:13px;font-weight:700;color:var(--ink-2)}
.foot{margin:22px 18px 0;padding-bottom:calc(30px + env(safe-area-inset-bottom));text-align:center;font-size:11px;color:#BBADA6;line-height:1.7}
/* 小弹层:投稿说明 */
.mask{position:fixed;inset:0;z-index:50;background:rgba(20,12,8,.45);opacity:0;pointer-events:none;transition:opacity .25s}
.mask.on{opacity:1;pointer-events:auto}
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:51;padding:22px 20px calc(22px + env(safe-area-inset-bottom));border-radius:24px 24px 0 0;background:#fff;transform:translateY(105%);transition:transform .3s cubic-bezier(.2,.8,.2,1)}
.sheet.on{transform:none}
.sheet h3{margin:0;font-size:19px;font-weight:900}
.sheet p{margin:8px 0 0;font-size:14px;color:var(--ink-2);line-height:1.65}
.sheet .rb{margin-top:14px;padding:14px;border-radius:16px;background:#FFF1EB;text-align:center}
.sheet .rb small{display:block;font-size:12px;color:#B5634C;font-weight:700}
.sheet .rb b{font-size:18px;font-weight:900;color:var(--ink)}
.sheet .rb em{font-style:normal;color:var(--brand);font-size:22px}
.sheet .pk{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.sheet .pk a{display:inline-flex;align-items:center;height:32px;padding:0 12px;border-radius:99px;background:#F7F1EE;font-size:13px;font-weight:700;color:var(--ink-2);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sheet .bt2{display:flex;align-items:center;justify-content:center;margin-top:16px;height:48px;border-radius:99px;background:linear-gradient(135deg,#FF8A5B,#F4593C);color:#fff;font-size:16px;font-weight:900}
</style>
</head>
<body>
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
<symbol id="i-back" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-right" viewBox="0 0 24 24"><path d="M9 5l7 7-7 7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-left" viewBox="0 0 24 24"><path d="M15 5l-7 7 7 7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-heart" viewBox="0 0 24 24"><path d="M12 20s-7-4.4-7-10a4 4 0 0 1 7-2.6A4 4 0 0 1 19 10c0 5.6-7 10-7 10z" fill="currentColor"/></symbol>
<symbol id="i-pen" viewBox="0 0 24 24"><path d="M4 20l4-1 10-10-3-3L5 16l-1 4zM14 7l3 3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-redo" viewBox="0 0 24 24"><path d="M4 12a8 8 0 1 0 2.3-5.6M4 4v4h4" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
</svg>
<div id="sc">
<header class="top" id="top">
<div class="nav">
<button class="bk" id="back" type="button" aria-label="返回"><svg class="ic"><use href="#i-back"/></svg></button>
<div class="tt"><b>孕妈广场</b><small id="today"></small></div>
<span class="ver">效果稿 V5 · 今日广场</span>
</div>
</header>
<!-- 01 今日一问 -->
<section class="q" id="q"></section>
<!-- 02 故事卡堆 -->
<div class="sh"><span class="no">02</span><h2>她们的故事</h2><small>左右滑,看下一张</small></div>
<div class="stk-wrap">
<div class="stk" id="stk"></div>
<div class="stk-ctl">
<span class="pg" id="pg"></span>
<span class="tr"><i id="tr"></i></span>
<button type="button" id="prev" aria-label="上一张"><svg class="ic"><use href="#i-left"/></svg></button>
<button type="button" id="next" aria-label="下一张"><svg class="ic"><use href="#i-right"/></svg></button>
</div>
</div>
<!-- 03 话题榜 -->
<div class="sh"><span class="no">03</span><h2>话题榜</h2><small id="rkSub">按在聊人数</small></div>
<nav class="tabs" id="tabs" role="tablist"></nav>
<div class="rank" id="rank"></div>
<a class="rk-ft" id="rkMore">进入广场看全部话题<svg class="ic" style="width:13px;height:13px"><use href="#i-right"/></svg></a>
<div class="foot">篇数、在聊人数、投票比例均为示例占位<br>效果稿 V5 · 今日广场</div>
</div>
<div class="mask" id="mask"></div>
<div class="sheet" id="sheet"></div>
<script src="../../guangchang/topics.js"></script>
<script src="../../guangchang/data.js"></script>
<script>
(function () {
'use strict';
var $ = function (s) { return document.querySelector(s); };
var T = window.GC_TOPICS || [], D = window.GC_DATA || {};
var TBY = {}; T.forEach(function (t) { TBY[t.id] = t; });
var HASH = location.hash || '';
var CAT = { family: { name: '家庭婚姻', k: '#E0566F', k2: '#F7A3B2' }, work: { name: '职场', k: '#3A72B8', k2: '#9CC0EA' }, baby: { name: '经验', k: '#2E8A7C', k2: '#93D3C7' } };
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var hs = function (s) { var x = 7; s = String(s); for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
var AV = []; for (var i = 1; i <= 22; i++) AV.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) AV.push('p' + (i < 10 ? '0' : '') + i);
var avSrc = function (name) { return '../../assets/img/mom/' + AV[hs(name) % AV.length] + '.jpg'; };
var fmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
var topicUrl = function (id) { return '../../guangchang/?t=' + id + HASH; };
var noteUrl = function (id, k) { return '../../guangchang/?t=' + id + '&n=' + id + '-' + k + HASH; };
/* 返回 */
$('#back').addEventListener('click', function () { history.length > 1 ? history.back() : (location.href = '../../' + location.hash); });
var now = new Date();
$('#today').textContent = (now.getMonth() + 1) + '月' + now.getDate() + '日';
$('#sc').addEventListener('scroll', function () { $('#top').classList.toggle('on', this.scrollTop > 4); }, { passive: true });
/* ================= 01 今日一问:按日期从精选题里轮一个 ================= */
var QS = [
{ t: 'f02', q: '长辈按老经验叮嘱你时,你通常会?', a: '笑着应下,转头照自己的来', b: '当场讲道理,说清楚更省心' },
{ t: 'w01', q: '怀孕的事,你是什么时候告诉领导的?', a: '过了 12 周、稳了再说', b: '一确认就说,早安排早轻松' },
{ t: 'm10', q: '他觉得你在家养胎很轻松,你会?', a: '列给他看,我一天都在忙什么', b: '算了,懒得解释' },
{ t: 'b03', q: '刷孕期内容越刷越慌,你会?', a: '卸载 / 屏蔽,眼不见心不慌', b: '继续看,只是换成靠谱来源' },
{ t: 'f09', q: '过节亲戚围着肚子问东问西,你会?', a: '笑笑带过,熬过这顿饭', b: '找个理由,早点溜回房间' },
{ t: 'w02', q: '请产检假,你会提前多久开口?', a: '提前一周,正式发邮件', b: '前一天口头说一声就行' },
{ t: 'm06', q: '孕期最打动你的,是哪一种在意?', a: '一份用心挑的礼物', b: '一盆泡好的洗脚水' }
];
var dayIdx = Math.floor((now - new Date(now.getFullYear(), 0, 0)) / 864e5);
var Q = QS[dayIdx % QS.length], QT = TBY[Q.t] || T[0];
var pa = 38 + hs(Q.t + 'v') % 27; /* 占位比例 38~64 */
var votes = 1200 + hs(Q.q) % 3800;
var VK = 'gcv5-vote-' + Q.t + '-' + dayIdx;
function renderQ() {
var cat = CAT[QT.cat];
var avs = [0, 1, 2, 3].map(function (k) { return '<img loading="lazy" src="' + avSrc(Q.t + k) + '" alt="">'; }).join('');
$('#q').innerHTML = '<span class="wm">' + esc(QT.g) + '</span>' +
'<div class="hd"><span class="tag"><i></i>今日一问</span><span class="dt">01</span><span class="cat">#' + cat.name + '</span></div>' +
'<h3>' + esc(Q.q) + '</h3><p class="sub">来自话题「' + esc(QT.name) + '」</p>' +
'<div class="ops">' +
'<button class="op" type="button" data-v="a"><span class="bar"></span><span class="lt">A</span><span class="tx">' + esc(Q.a) + '</span><span class="pc">' + pa + '%</span></button>' +
'<button class="op" type="button" data-v="b"><span class="bar"></span><span class="lt">B</span><span class="tx">' + esc(Q.b) + '</span><span class="pc">' + (100 - pa) + '%</span></button>' +
'</div>' +
'<div class="ft"><span class="avs">' + avs + '</span><small id="qn">' + fmt(votes) + ' 位妈妈已表态,你呢?</small>' +
'<a class="go" href="' + topicUrl(QT.id) + '">看看大家怎么说<svg class="ic"><use href="#i-right"/></svg></a></div>';
var saved = null; try { saved = localStorage.getItem(VK); } catch (e) {}
if (saved) vote(saved, true);
}
function vote(v, quiet) {
var q = $('#q'); if (q.classList.contains('done')) return;
q.classList.add('done');
var A = pa, B = 100 - pa;
q.querySelectorAll('.op').forEach(function (b) {
var me = b.dataset.v === v; b.classList.toggle('me', me);
setTimeout(function () { b.querySelector('.bar').style.width = (b.dataset.v === 'a' ? A : B) + '%'; }, quiet ? 0 : 30);
});
$('#qn').textContent = (v === 'a' ? A : B) + '% 的妈妈和你想的一样';
if (!quiet) try { localStorage.setItem(VK, v); } catch (e) {}
}
renderQ();
$('#q').addEventListener('click', function (e) { var b = e.target.closest('.op'); if (b) vote(b.dataset.v); });
/* ================= 02 故事卡堆:带真实照片的笔记,按分类轮流排 ================= */
var POOL = { family: [], work: [], baby: [] };
T.forEach(function (t) {
var d = D[t.id]; if (!d || !d.notes) return;
d.notes.forEach(function (n, k) { if (n.photo) POOL[t.cat].push({ t: t, n: n, k: k + 1 }); });
});
var STORIES = [], order = ['family', 'work', 'baby'], guard = 0;
while (STORIES.length < 12 && guard++ < 60) order.forEach(function (c) { var p = POOL[c]; if (p.length && STORIES.length < 12) STORIES.push(p.splice(hs(c + guard) % p.length, 1)[0]); });
var TOTAL = STORIES.length + 1; /* +1:最后一张「轮到你了」 */
var cur = 0;
function storyHTML(s) {
var c = CAT[s.t.cat];
return '<img class="ph" loading="lazy" src="../../guangchang/' + esc(s.n.photo) + '" alt="">' +
'<div class="sh2"></div>' +
'<span class="kt"><i style="background:' + c.k + '"></i>' + c.name + '</span>' +
'<span class="lk"><svg class="ic"><use href="#i-heart"/></svg>' + fmt(s.n.likes || 0) + '</span>' +
'<div class="bt"><div class="tp"># ' + esc(s.t.name) + '</div><h4>' + esc(s.n.title) + '</h4>' +
'<div class="au"><img loading="lazy" src="' + avSrc(s.n.author) + '" alt=""><b>' + esc(s.n.author) + '</b><span>' + esc(s.n.stage || '') + '</span>' +
'<em class="rd">读全文<svg class="ic"><use href="#i-right"/></svg></em></div></div>';
}
var YOU = '<div class="in"><span class="pen"><svg class="ic"><use href="#i-pen"/></svg></span>' +
'<span class="k">STORY ' + TOTAL + ' / ' + TOTAL + '</span><div class="big">轮到你了</div>' +
'<p class="lede">看完她们的故事,<br>你也有一段想说的经历吗?<br>挑一个话题,写下来就好。</p>' +
'<div class="rw"><small>投稿被选中,每篇奖励</small><b><em>¥30</em> 现金 + <em>500</em> 兜豆</b></div>' +
'<button class="cta" type="button" data-join="1"><svg class="ic"><use href="#i-pen"/></svg>写我的故事</button></div>';
var stk = $('#stk'), cards = [];
STORIES.forEach(function (s, i) {
var el = document.createElement('a'); el.className = 'sc'; el.href = noteUrl(s.t.id, s.k); el.draggable = false;
el.innerHTML = storyHTML(s); stk.appendChild(el); cards.push(el);
});
var you = document.createElement('div'); you.className = 'sc you'; you.innerHTML = YOU; stk.appendChild(you); cards.push(you);
function layout(dx) {
cards.forEach(function (el, i) {
var d = i - cur, tf, op = 1, z = 100 - Math.abs(d);
if (d < 0) { tf = 'translate3d(-130%,0,0) rotate(-14deg)'; op = 0; }
else if (d === 0) { tf = 'translate3d(' + (dx || 0) + 'px,0,0) rotate(' + ((dx || 0) / 22) + 'deg)'; }
else if (d <= 2) {
var p = dx ? Math.min(Math.abs(dx) / 160, 1) : 0, dd = d - p;
tf = 'translate3d(0,' + (dd * 14) + 'px,0) scale(' + (1 - dd * 0.05) + ')';
op = d === 2 ? 0.9 : 1;
} else { tf = 'translate3d(0,28px,0) scale(.9)'; op = 0; }
el.style.transform = tf; el.style.opacity = op; el.style.zIndex = z;
el.style.pointerEvents = d === 0 ? 'auto' : 'none';
});
$('#pg').innerHTML = '<b>' + (cur + 1) + '</b> / ' + TOTAL;
$('#tr').style.width = ((cur + 1) / TOTAL * 100) + '%';
$('#prev').disabled = cur === 0; $('#next').disabled = cur === TOTAL - 1;
}
function go(n) { cur = Math.max(0, Math.min(TOTAL - 1, n)); layout(0); }
layout(0);
$('#prev').addEventListener('click', function () { go(cur - 1); });
$('#next').addEventListener('click', function () { go(cur + 1); });
/* 拖拽滑卡(触摸 + 鼠标),水平位移大才算滑,否则当点击 */
var drag = null, moved = false;
function pt(e) { var t = e.touches ? e.touches[0] : e; return { x: t.clientX, y: t.clientY }; }
function onDown(e) { if (e.target.closest('[data-join]')) return; var p = pt(e); drag = { x: p.x, y: p.y, dx: 0, lock: '' }; moved = false; }
function onMove(e) {
if (!drag) return; var p = pt(e), dx = p.x - drag.x, dy = p.y - drag.y;
if (!drag.lock && (Math.abs(dx) > 6 || Math.abs(dy) > 6)) drag.lock = Math.abs(dx) > Math.abs(dy) ? 'x' : 'y';
if (drag.lock !== 'x') return;
if (e.cancelable) e.preventDefault();
moved = true; drag.dx = dx;
cards[cur].style.transition = 'none'; layout(dx);
}
function onUp() {
if (!drag) return; var dx = drag.dx; drag = null;
cards[cur].style.transition = '';
if (dx < -70 && cur < TOTAL - 1) go(cur + 1);
else if (dx > 70 && cur > 0) go(cur - 1);
else layout(0);
}
stk.addEventListener('touchstart', onDown, { passive: true });
stk.addEventListener('touchmove', onMove, { passive: false });
stk.addEventListener('touchend', onUp); stk.addEventListener('touchcancel', onUp);
stk.addEventListener('mousedown', function (e) { e.preventDefault(); onDown(e); });
window.addEventListener('mousemove', onMove); window.addEventListener('mouseup', onUp);
stk.addEventListener('click', function (e) {
if (moved) { e.preventDefault(); moved = false; return; }
if (e.target.closest('[data-join]')) { e.preventDefault(); openJoin(); }
});
/* 投稿说明弹层 */
function openJoin() {
var hot = T.filter(function (t) { return t.hot; }).slice(0, 6);
$('#sheet').innerHTML = '<h3>写下你的孕期故事</h3><p>选一个你有感触的话题,真实经历就好,不用写得很长。</p>' +
'<div class="rb"><small>投稿被选中,每篇奖励</small><b><em>¥30</em> 现金 + <em>500</em> 兜豆</b></div>' +
'<div class="pk">' + hot.map(function (t) { return '<a href="' + topicUrl(t.id) + '"># ' + esc(t.name) + '</a>'; }).join('') + '</div>' +
'<a class="bt2" href="../../guangchang/' + HASH + '">去广场投稿</a>';
$('#mask').classList.add('on'); $('#sheet').classList.add('on');
}
$('#mask').addEventListener('click', function () { $('#mask').classList.remove('on'); $('#sheet').classList.remove('on'); });
/* ================= 03 话题榜 ================= */
var catF = 'all';
var TABS = [['all', '全部', '#F4593C'], ['family', '家庭婚姻', CAT.family.k], ['work', '职场', CAT.work.k], ['baby', '经验', CAT.baby.k]];
function renderTabs() {
$('#tabs').innerHTML = TABS.map(function (x) {
return '<button type="button" role="tab" data-c="' + x[0] + '" style="--k:' + x[2] + '" class="' + (catF === x[0] ? 'on' : '') + '" aria-selected="' + (catF === x[0]) + '"><i></i>' + x[1] + '</button>';
}).join('');
}
function renderRank() {
var byTalk = function (a, b) { return b.talk - a.talk; }, list;
if (catF === 'all') { /* 全部:各分类各取前几名再合排,避免整榜都是一个分类 */
var q = { family: 4, work: 3, baby: 3 }; list = [];
Object.keys(q).forEach(function (c) { list = list.concat(T.filter(function (t) { return t.cat === c; }).sort(byTalk).slice(0, q[c])); });
list.sort(byTalk);
} else list = T.filter(function (t) { return t.cat === catF; }).sort(byTalk).slice(0, 10);
var max = list.length ? list[0].talk : 1;
$('#rank').innerHTML = list.map(function (t, i) {
var c = CAT[t.cat];
return '<a class="rk t' + (i + 1) + '" href="' + topicUrl(t.id) + '" style="--k:' + c.k + ';--k2:' + c.k2 + '">' +
'<span class="n">' + (i + 1) + '</span>' +
'<span class="bd"><span class="nm"><b>' + esc(t.name) + '</b></span>' +
'<span class="mt">' + (catF === 'all' ? '<span class="kc">' + c.name + '</span>' : '') + (t.hot ? '<span class="hot">热</span>' : '') + '<span class="hb"><i data-w="' + Math.max(12, Math.round(t.talk / max * 100)) + '"></i></span><span class="tk"><em>' + fmt(t.talk) + '</em> 在聊</span></span></span>' +
(t.ph ? '<img class="th" loading="lazy" src="../../' + esc(t.ph) + '" alt="">' : '') + '</a>';
}).join('');
$('#rkSub').textContent = (catF === 'all' ? '全部话题' : CAT[catF].name) + ' · 按在聊人数';
requestAnimationFrame(function () { requestAnimationFrame(function () {
document.querySelectorAll('#rank .hb i').forEach(function (b) { b.style.width = b.dataset.w + '%'; });
}); });
}
renderTabs(); renderRank();
$('#rkMore').href = '../../guangchang/' + HASH;
$('#tabs').addEventListener('click', function (e) {
var b = e.target.closest('button[data-c]'); if (!b || b.dataset.c === catF) return;
catF = b.dataset.c; renderTabs(); renderRank();
});
/* ================= 禁止下拉回弹 ================= */
var sx = 0, sy = 0;
document.addEventListener('touchstart', function (e) { if (e.touches.length === 1) { sx = e.touches[0].clientX; sy = e.touches[0].clientY; } }, { passive: true });
document.addEventListener('touchmove', function (e) {
if (e.touches.length !== 1) { if (e.cancelable) e.preventDefault(); return; }
var dx = e.touches[0].clientX - sx, dy = e.touches[0].clientY - sy;
if (Math.abs(dy) <= Math.abs(dx)) return;
var el = e.target;
while (el && el !== document.body && el !== document.documentElement) {
if (el.nodeType === 1) {
var oy = getComputedStyle(el).overflowY;
if ((oy === 'auto' || oy === 'scroll') && el.scrollHeight > el.clientHeight + 1) {
if (dy > 0 && el.scrollTop > 0) return;
if (dy < 0 && el.scrollTop + el.clientHeight < el.scrollHeight - 1) return;
}
}
el = el.parentNode;
}
if (e.cancelable) e.preventDefault();
}, { passive: false });
})();
</script>
</body>
</html>

43
demo/gc/index.html Normal file
View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>孕妈广场 · 五版效果稿</title>
<!-- 11-01 用户:「孕妈广场这个页面重新做一版…做五版,效果图给我带链接的,点击可以直接查看」。演示汇总页,图是各版首屏长截图,点图/按钮进对应演示页(带上 hash 身份) -->
<style>
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
body{margin:0;background:#F6F1EC;font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;color:#2B2320}
header{padding:calc(22px + env(safe-area-inset-top)) 18px 8px}
h1{margin:0;font-size:22px;font-weight:900}
header p{margin:6px 0 0;font-size:13px;color:#8A7570}
.list{display:grid;gap:22px;padding:14px 14px 40px;max-width:900px;margin:0 auto}
@media(min-width:760px){.list{grid-template-columns:repeat(2,1fr)}}
.it{background:#fff;border-radius:20px;overflow:hidden;box-shadow:0 10px 30px -18px rgba(120,70,50,.45)}
.hd{display:flex;align-items:center;gap:10px;padding:14px 16px}
.hd b{flex:none;width:34px;height:34px;border-radius:11px;background:#F4593C;color:#fff;display:grid;place-items:center;font-size:15px;font-weight:900}
.hd div{flex:1;min-width:0}
.hd h2{margin:0;font-size:16px;font-weight:900}
.hd small{display:block;font-size:12px;color:#8A7570;margin-top:2px;line-height:1.45}
.pic{display:block;height:560px;overflow:hidden;border-top:1px solid #F1E7E1;border-bottom:1px solid #F1E7E1;position:relative}
.pic img{width:100%;display:block}
.pic::after{content:"";position:absolute;left:0;right:0;bottom:0;height:70px;background:linear-gradient(transparent,#fff)}
.go{display:flex;align-items:center;justify-content:center;height:46px;margin:12px 16px 16px;border-radius:14px;background:#2B2320;color:#fff;font-size:14.5px;font-weight:800;text-decoration:none}
</style></head><body>
<header><h1>孕妈广场 · 五版效果稿</h1><p>点图片或按钮直接打开那一版,可以切分类、点进文章看看。</p></header>
<div class="list" id="list"></div>
<script>
var V = [
['孕妈周刊', '整页像一本当期杂志:封面故事、本期目录、专栏图文混排,投稿是「征稿启事」'],
['广场地图', '俯视小广场插画,三个分类是三个角落,妈妈们站着聊天;投稿是广场上的信箱'],
['留言墙', '软木板上的便签和拍立得,话题是彩色便签,照片笔记是相片;投稿是一叠空白便签'],
['聊天广场', '每个话题像一个聊天室,直接看到大家在说什么;底部输入条就是投稿入口'],
['今日广场', '今日一问投票 + 左右滑的故事卡堆 + 话题榜;卡堆最后一张「轮到你了」投稿']
];
var h = location.hash;
document.getElementById('list').innerHTML = V.map(function (v, i) {
var u = '../gc-v' + (i + 1) + '/' + h;
return '<div class="it"><div class="hd"><b>V' + (i + 1) + '</b><div><h2>' + v[0] + '</h2><small>' + v[1] + '</small></div></div>' +
'<a class="pic" href="' + u + '"><img src="v' + (i + 1) + '.jpg?2" alt="' + v[0] + '" loading="lazy"></a>' +
'<a class="go" href="' + u + '">打开 V' + (i + 1) + ' ' + v[0] + '</a></div>';
}).join('');
</script>
</body></html>

BIN
demo/gc/v1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
demo/gc/v2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
demo/gc/v3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

BIN
demo/gc/v4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

BIN
demo/gc/v5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
demo/gch/all.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

43
demo/gch/index.html Normal file
View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>首页「孕妈广场」· 五版效果稿</title>
<!-- 11-02 用户:要的是首页里的孕妈广场模块。点图/按钮打开首页 ?gcv=N(首页里那块换成第 N 版并滚到它),带上 hash 身份 -->
<style>
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
body{margin:0;background:#F6F1EC;font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;color:#2B2320}
header{padding:calc(22px + env(safe-area-inset-top)) 18px 8px}
h1{margin:0;font-size:21px;font-weight:900}
header p{margin:6px 0 0;font-size:13px;color:#8A7570;line-height:1.55}
.list{display:grid;gap:22px;padding:14px 14px 40px;max-width:1000px;margin:0 auto}
@media(min-width:760px){.list{grid-template-columns:repeat(2,1fr)}}
.it{background:#fff;border-radius:20px;overflow:hidden;box-shadow:0 10px 30px -18px rgba(120,70,50,.45)}
.hd{display:flex;align-items:center;gap:10px;padding:14px 16px}
.hd b{flex:none;width:34px;height:34px;border-radius:11px;background:#F2627E;color:#fff;display:grid;place-items:center;font-size:15px;font-weight:900}
.hd div{flex:1;min-width:0}
.hd h2{margin:0;font-size:16px;font-weight:900}
.hd small{display:block;font-size:12px;color:#8A7570;margin-top:2px;line-height:1.45}
.pic{display:block;border-top:1px solid #F1E7E1;border-bottom:1px solid #F1E7E1}
.pic img{width:100%;display:block}
.go{display:flex;align-items:center;justify-content:center;height:46px;margin:12px 16px 16px;border-radius:14px;background:#2B2320;color:#fff;font-size:14.5px;font-weight:800;text-decoration:none}
</style></head><body>
<header><h1>首页「孕妈广场」· 效果稿</h1><p>点图片或按钮会打开真实首页,并自动滚到孕妈广场这一块,可以直接点、切分类、左右滑。</p></header>
<div class="list" id="list"></div>
<script>
var V = [
['广场头条', '左边一张大照片故事,右边「本期要目」3 条话题,像杂志封面'],
['广场人群', '一块空地上站着十几位妈妈,头上轮流冒出话题气泡;「你」的空位就是投稿'],
['话题弹幕', '「此刻最热」小卡 + 三行慢慢飘过的话题弹幕,按住暂停、点了进话题'],
['故事卡堆', '一叠真实照片故事卡,左右滑翻页,最后一张「轮到你了」投稿'],
['今日一问', '每天一道投票题,点完看比例;下面一排横滑的话题照片卡'],
['合并版(推荐)', '孕妈广场 + 其他妈妈也在搜合成一块:上面 V4 故事卡堆(压矮、字更清楚,左右手滑或点箭头翻),中间两个测一测(素色卡),下面 6 个热搜问题']
];
var h = location.hash;
document.getElementById('list').innerHTML = V.slice().reverse().map(function (v, j) { var i = V.length - 1 - j;
var u = '../../?gcv=' + (i + 1) + h;
return '<div class="it"><div class="hd"><b>V' + (i + 1) + '</b><div><h2>' + v[0] + '</h2><small>' + v[1] + '</small></div></div>' +
'<a class="pic" href="' + u + '"><img src="v' + (i + 1) + '.jpg?3" alt="' + v[0] + '" loading="lazy"></a>' +
'<a class="go" href="' + u + '">在首页打开 V' + (i + 1) + ' ' + v[0] + '</a></div>';
}).join('');
</script>
</body></html>

41
demo/gch/qz.html Normal file
View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
<title>孕妈广场「测一测」· 四版效果稿</title>
<!-- 11-02 用户:「测一测这个,给我出三版效果让我选择,点击链接可以去预览」。点图/按钮打开首页 ?gcv=6&qz=N -->
<style>
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
body{margin:0;background:#F6F1EC;font-family:-apple-system,BlinkMacSystemFont,"PingFang SC","Microsoft YaHei",sans-serif;color:#2B2320}
header{padding:calc(22px + env(safe-area-inset-top)) 18px 8px}
h1{margin:0;font-size:21px;font-weight:900}
header p{margin:6px 0 0;font-size:13px;color:#8A7570;line-height:1.55}
.list{display:grid;gap:22px;padding:14px 14px 40px;max-width:1100px;margin:0 auto}
@media(min-width:760px){.list{grid-template-columns:repeat(2,1fr)}}
.it{background:#fff;border-radius:20px;overflow:hidden;box-shadow:0 10px 30px -18px rgba(120,70,50,.45)}
.hd{display:flex;align-items:center;gap:10px;padding:14px 16px}
.hd b{flex:none;width:34px;height:34px;border-radius:11px;background:#F2627E;color:#fff;display:grid;place-items:center;font-size:14px;font-weight:900}
.hd div{flex:1;min-width:0}
.hd h2{margin:0;font-size:16px;font-weight:900}
.hd small{display:block;font-size:12px;color:#8A7570;margin-top:2px;line-height:1.45}
.pic{display:block;border-top:1px solid #F1E7E1;border-bottom:1px solid #F1E7E1}
.pic img{width:100%;display:block}
.go{display:flex;align-items:center;justify-content:center;height:46px;margin:12px 16px 16px;border-radius:14px;background:#2B2320;color:#fff;font-size:14.5px;font-weight:800;text-decoration:none}
</style></head><body>
<header><h1>孕妈广场「测一测」· 四版效果稿</h1><p>预览首页(不带参数)现在默认就是第 1 版。点图片或按钮会打开真实首页,自动滚到孕妈广场,「测一测」两个测试,放在「其他妈妈也在搜」下面(模块最底部)。</p></header>
<div class="list" id="list"></div>
<script>
var V = [
['插画白卡', '两张并排白卡,上半插画横幅,下半标题 + 人数 + 「开始测」;最直观'],
['小胶囊', '两颗矮胶囊,圆形小插画 + 两行字,浅米底;最省地方、最安静'],
['你 & 他', '一张合体卡,左边测你、右边测他,中间 & 连起来;最有话题感'],
['彩色卡(更明显)', '紫 / 橙彩色底 + 类型小标签 + 实心「去测试」按钮 + 右下圆形插画;最醒目']
];
var h = location.hash;
document.getElementById('list').innerHTML = V.map(function (v, i) {
var u = '../../?gcv=6&qz=' + (i + 1) + h;
return '<div class="it"><div class="hd"><b>' + (i + 1) + '</b><div><h2>' + v[0] + '</h2><small>' + v[1] + '</small></div></div>' +
'<a class="pic" href="' + u + '"><img src="qz' + (i + 1) + '.jpg?3" alt="' + v[0] + '" loading="lazy"></a>' +
'<a class="go" href="' + u + '">在首页打开 第' + (i + 1) + '版 ' + v[0] + '</a></div>';
}).join('');
</script>
</body></html>

BIN
demo/gch/qz1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
demo/gch/qz2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
demo/gch/qz3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
demo/gch/qz4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

67
demo/gch/v1.css Normal file
View File

@@ -0,0 +1,67 @@
/* 效果稿 V1 · 广场头条(杂志式精选) */
#gcHome.gv1{margin:16px -26px 0;padding:20px 24px 16px;border-radius:26px;position:relative;z-index:0;background-color:#fff}
#gcHome.gv1 button{font:inherit;border:0;background:none;padding:0;margin:0;color:inherit;text-align:left;cursor:pointer;-webkit-tap-highlight-color:transparent}
#gcHome.gv1 .v1-mark{position:absolute;top:8px;right:16px;font-size:11px;color:#C9BDB8;letter-spacing:.5px}
#gcHome.gv1 .v1-head{display:flex;align-items:flex-end;justify-content:space-between;gap:10px}
#gcHome.gv1 .v1-title{flex:none;margin:0;font-size:21px;font-weight:900;letter-spacing:.5px;color:#2A1E1E;line-height:1.2}
#gcHome.gv1 .v1-title span{background:linear-gradient(transparent 58%,#FFD0DC 58%,#FFD0DC 92%,transparent 92%);padding:0 3px}
#gcHome.gv1 .v1-tabs{display:flex;gap:2px;padding-bottom:1px}
#gcHome.gv1 .v1-tabs button{position:relative;height:26px;padding:0 6px;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;font-weight:600;color:#A2938E;white-space:nowrap;transition:color .2s}
#gcHome.gv1 .v1-tabs button::after{content:'';position:absolute;left:50%;bottom:0;width:0;height:2px;border-radius:2px;background:#F2627E;transform:translateX(-50%);transition:width .25s}
#gcHome.gv1 .v1-tabs button.on{color:#2A1E1E;font-weight:800}
#gcHome.gv1 .v1-tabs button.on::after{width:16px}
#gcHome.gv1 .v1-kicker{display:flex;align-items:center;gap:8px;margin:14px 0 10px;font-size:11px;color:#B3A39D;letter-spacing:1px}
#gcHome.gv1 .v1-kicker span{font-weight:800;color:#F4593C}
#gcHome.gv1 .v1-kicker i{flex:1;height:1px;background:linear-gradient(90deg,#F3D9D2,#F7E9E4)}
#gcHome.gv1 .v1-kicker em{font-style:normal;font-family:Georgia,'Times New Roman',serif;letter-spacing:.5px}
#gcHome.gv1 .v1-body{display:flex;gap:14px;align-items:stretch}
#gcHome.gv1 .v1-body.in .v1-lead,#gcHome.gv1 .v1-body.in .v1-item{animation:v1In .45s cubic-bezier(.2,.7,.2,1) both}
#gcHome.gv1 .v1-body.in .v1-item:nth-of-type(2){animation-delay:.05s}
#gcHome.gv1 .v1-body.in .v1-item:nth-of-type(3){animation-delay:.1s}
#gcHome.gv1 .v1-body.in .v1-item:nth-of-type(4){animation-delay:.15s}
@keyframes v1In{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
#gcHome.gv1 .v1-lead{position:relative;flex:0 0 53%;min-height:240px;align-self:stretch;border-radius:18px;overflow:hidden;background:#EADFD9;box-shadow:0 12px 22px -16px rgba(60,30,20,.55);isolation:isolate}
#gcHome.gv1 .v1-ph{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s}
#gcHome.gv1 .v1-lead:active .v1-ph{transform:scale(1.03)}
#gcHome.gv1 .v1-shade{position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,.12) 0,rgba(0,0,0,0) 26%,rgba(0,0,0,0) 42%,rgba(28,14,10,.78) 100%)}
#gcHome.gv1 .v1-badge{position:absolute;top:10px;left:10px;display:flex;align-items:center;gap:5px;height:20px;padding:0 8px 0 4px;border-radius:10px;background:rgba(255,255,255,.92);font-size:11px;font-weight:800;color:var(--ink)}
#gcHome.gv1 .v1-badge b{display:flex;align-items:center;justify-content:center;height:14px;padding:0 4px;border-radius:7px;background:var(--ink);color:#fff;font-family:Georgia,serif;font-size:11px;font-weight:700;line-height:1}
#gcHome.gv1 .v1-cap{position:absolute;left:0;right:0;bottom:0;padding:0 12px 12px;display:flex;flex-direction:column;gap:8px}
#gcHome.gv1 .v1-lt{font-size:15px;font-weight:800;line-height:1.4;color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.25);display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden}
#gcHome.gv1 .v1-by{display:flex;align-items:center;gap:6px;min-width:0;font-size:11px;color:rgba(255,255,255,.92)}
#gcHome.gv1 .v1-by img{flex:none;width:20px;height:20px;border-radius:50%;object-fit:cover;border:1.5px solid rgba(255,255,255,.9)}
#gcHome.gv1 .v1-by{justify-content:flex-start}
#gcHome.gv1 .v1-au{flex:0 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:700}
#gcHome.gv1 .v1-st{flex:none;opacity:.8}
#gcHome.gv1 .v1-st::before{content:'·';margin-right:4px}
#gcHome.gv1 .v1-list{flex:1;min-width:0;display:flex;flex-direction:column}
#gcHome.gv1 .v1-lh{font-size:11px;font-weight:800;letter-spacing:2px;color:#2A1E1E;padding-bottom:6px;border-bottom:2px solid #2A1E1E}
#gcHome.gv1 .v1-item{flex:1;display:flex;padding:9px 0 8px;border-bottom:1px solid #F1E4DF;min-height:0}
#gcHome.gv1 .v1-item:last-child{border-bottom:0;padding-bottom:0}
#gcHome.gv1 .v1-row{display:flex;align-items:center;gap:6px}
#gcHome.gv1 .v1-no{flex:none;font-family:Georgia,'Times New Roman',serif;font-size:15px;font-style:italic;line-height:16px;color:var(--ink);opacity:.85}
#gcHome.gv1 .v1-it{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
#gcHome.gv1 .v1-tag{font-size:11px;font-weight:800;line-height:16px;padding:0 5px;border-radius:4px;color:var(--ink);background:color-mix(in srgb,var(--ink) 10%,#fff)}
#gcHome.gv1 .v1-name{font-size:13px;font-weight:700;line-height:1.38;color:#2E2321;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden}
#gcHome.gv1 .v1-talk{display:flex;align-items:center;gap:4px;font-size:11px;color:#A2938E}
#gcHome.gv1 .v1-talk i{width:5px;height:5px;border-radius:50%;background:#43C27F;box-shadow:0 0 0 2px rgba(67,194,127,.18)}
#gcHome.gv1 .v1-foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:14px;padding-top:11px;border-top:1px dashed #EFDCD5}
#gcHome.gv1 .v1-live{display:flex;align-items:center;gap:6px;min-width:0;overflow:hidden;font-size:11.5px;color:#8C7D78;white-space:nowrap}
#gcHome.gv1 .v1-live b{color:#E0566F;font-weight:800}
#gcHome.gv1 .v1-avs{display:flex;flex:none}
#gcHome.gv1 .v1-avs img{width:18px;height:18px;border-radius:50%;object-fit:cover;border:1.5px solid #fff;margin-left:-6px}
#gcHome.gv1 .v1-avs img:first-child{margin-left:0}
#gcHome.gv1 .v1-gift{flex:none;display:flex;align-items:center;gap:3px;font-size:11.5px;color:#8C7D78;white-space:nowrap}
#gcHome.gv1 .v1-gift b{color:#F4593C;font-weight:800}
#gcHome.gv1 .v1-gift i{font-style:normal;font-weight:800;color:#F4593C;margin-left:1px}
@media (prefers-reduced-motion:reduce){
#gcHome.gv1 *{animation:none!important;transition:none!important}
}
#gcHome.gv1 .v1-lv{min-width:0;overflow:hidden;text-overflow:ellipsis}

BIN
demo/gch/v1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

88
demo/gch/v1.js Normal file
View File

@@ -0,0 +1,88 @@
/* 11-02 首页「孕妈广场」效果稿 V1 · 广场头条(杂志式精选):左大图故事卡 + 右「本期要目」3 条,细文字 tab 切换分类 */
(function () {
var sec = document.getElementById('gcHome');
var T = window.GC_TOPICS;
if (!sec || !T || !T.length) return;
var esc = function (s) { return String(s).replace(/[&<>"']/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]; }); };
var kfmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
var fmtNum = function (n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ','); };
var byId = {}; T.forEach(function (t) { byId[t.id] = t; });
var CAT = { family: { name: '家庭婚姻', ink: '#E0566F' }, work: { name: '职场', ink: '#3A72B8' }, baby: { name: '经验', ink: '#2E8A7C' } };
/* 精选头条(摘自 guangchang/data.js 各话题第一篇照片笔记,占位) */
var LEAD = {
all: { t: 'f01', title: '怀孕后我妈每天三个电话,第四个是我爸打的', author: '栗子慢慢', stage: '孕 22 周', av: 'm03', photo: 'guangchang/img/d9d596acde1f.jpg' },
family: { t: 'm01', title: '孕12周起,倒垃圾和换猫砂彻底归他了', author: '小满月', stage: '孕 26 周', av: 'm08', photo: 'guangchang/img/e0118088acf0.jpg' },
work: { t: 'w01', title: '孕 11 周还没告诉领导,周会上差点没忍住吐出来', author: '青柠半杯', stage: '孕 16 周', av: 'm12', photo: 'guangchang/img/874abee3d741.jpg' },
baby: { t: 'b08', title: '孕32周,大家都在期待,我却在被窝里偷偷哭了一次', author: '胆小的兔', stage: '孕 33 周', av: 'p05', photo: 'guangchang/img/ee5ea71da8c3.jpg' }
};
var LIST = {
all: ['m10', 'w10', 'b01'],
family: ['f02', 'f05', 'm06'],
work: ['w02', 'w10', 'w04'],
baby: ['b01', 'b03', 'b05']
};
var talkAll = T.reduce(function (a, t) { return a + (t.talk || 0); }, 0);
var d = new Date(Date.now() + (new Date().getTimezoneOffset() + 480) * 6e4); /* 北京时间 */
var tabs = [['', '全部'], ['family', '家庭婚姻'], ['work', '职场'], ['baby', '经验']].map(function (c, i) {
return '<button type="button" role="tab" data-cat="' + c[0] + '"' + (i ? '' : ' class="on" aria-selected="true"') + '>' + c[1] + '</button>';
}).join('');
sec.innerHTML =
'<div class="v1-head">' +
'<h2 class="v1-title"><span>孕妈广场</span></h2>' +
'<nav class="v1-tabs" role="tablist" aria-label="话题分类">' + tabs + '</nav>' +
'</div>' +
'<div class="v1-kicker"><span>本期头条</span><i></i><em>' + (d.getMonth() + 1) + '月' + d.getDate() + '日 · 效果稿 V1</em></div>' +
'<div class="v1-body" id="v1Body"></div>' +
'<div class="v1-foot">' +
'<button type="button" class="v1-live" data-go="all"><span class="v1-avs" aria-hidden="true">' +
['m05', 'p02'].map(function (a) { return '<img src="assets/img/mom/' + a + '.jpg" alt="" loading="lazy">'; }).join('') +
'</span><span class="v1-lv"><b>' + fmtNum(talkAll) + '</b> 位妈妈在聊</span></button>' +
'<button type="button" class="v1-gift" data-go="all">投稿选中 <b>¥30+500兜豆</b><i aria-hidden="true">›</i></button>' +
'</div>';
sec.classList.remove('hide');
sec.classList.add('gv1');
var body = sec.querySelector('#v1Body');
function render(cat) {
var k = cat || 'all', L = LEAD[k], lt = byId[L.t], lc = CAT[lt.cat];
var items = LIST[k].map(function (id, i) {
var t = byId[id], c = CAT[t.cat];
return '<button type="button" class="v1-item" data-t="' + t.id + '" style="--ink:' + c.ink + '">' +
'<span class="v1-it"><span class="v1-row"><span class="v1-no">0' + (i + 2) + '</span><span class="v1-tag">' + c.name + '</span></span>' +
'<span class="v1-name">' + esc(t.name) + '</span>' +
'<span class="v1-talk"><i></i>' + kfmt(t.talk) + ' 在聊</span></span></button>';
}).join('');
body.innerHTML =
'<button type="button" class="v1-lead" data-t="' + lt.id + '" style="--ink:' + lc.ink + '">' +
'<img class="v1-ph" src="' + L.photo + '" alt="" loading="lazy">' +
'<span class="v1-shade"></span>' +
'<span class="v1-badge"><b>01</b>' + lc.name + '</span>' +
'<span class="v1-cap">' +
'<span class="v1-lt">' + esc(L.title) + '</span>' +
'<span class="v1-by"><img src="assets/img/mom/' + L.av + '.jpg" alt="" loading="lazy"><span class="v1-au">' + esc(L.author) + '</span><span class="v1-st">' + L.stage.replace(/ /g, '') + '</span></span>' +
'</span>' +
'</button>' +
'<div class="v1-list"><span class="v1-lh">本期要目</span>' + items + '</div>';
body.classList.remove('in'); void body.offsetWidth; body.classList.add('in');
}
render('');
sec.addEventListener('click', function (e) {
var b = e.target.closest('button');
if (!b || !sec.contains(b)) return;
if (b.hasAttribute('data-cat')) {
if (b.classList.contains('on')) return;
sec.querySelectorAll('.v1-tabs button').forEach(function (x) { x.classList.remove('on'); x.removeAttribute('aria-selected'); });
b.classList.add('on'); b.setAttribute('aria-selected', 'true');
render(b.getAttribute('data-cat'));
} else if (b.hasAttribute('data-t')) {
location.href = 'guangchang/?t=' + b.getAttribute('data-t') + location.hash;
} else if (b.hasAttribute('data-go')) {
location.href = 'guangchang/' + location.hash;
}
});
})();

68
demo/gch/v2.css Normal file
View File

@@ -0,0 +1,68 @@
/* 首页「孕妈广场」效果稿 V2 · 广场人群(只在 ?gcv=2 时加载,全部限定在 #gcHome.gv2) */
#gcHome.gv2{padding:16px 26px 12px;background:#fff}
#gcHome.gv2 .g2-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
#gcHome.gv2 .g2-title{margin:0;font-size:21px;font-weight:900;letter-spacing:.5px;color:#2A1E1E}
#gcHome.gv2 .g2-title span{background:linear-gradient(transparent 58%,#FFD0DC 58%,#FFD0DC 92%,transparent 92%);padding:0 3px}
#gcHome.gv2 .g2-more{flex:none;display:flex;align-items:center;gap:2px;height:28px;padding:0 12px;border:0;border-radius:14px;background:linear-gradient(120deg,#FF8FA3,#F2627E);color:#fff;font:inherit;font-size:13px;font-weight:800;box-shadow:0 6px 14px -8px #F2627E}
#gcHome.gv2 .g2-more i{font-style:normal;font-size:15px;line-height:1;margin-top:-1px}
#gcHome.gv2 .g2-sub{display:flex;align-items:center;gap:6px;margin:6px 0 10px;font-size:12px;color:#8A7470}
#gcHome.gv2 .g2-sub b{color:#E0566F;font-weight:900;font-size:13px}
#gcHome.gv2 .g2-live{width:7px;height:7px;border-radius:50%;background:#3CC48A;box-shadow:0 0 0 3px rgba(60,196,138,.18)}
/* 空地:上远下近,暖色地面 + 透视地砖 + 中间一圈浅色圆环 */
#gcHome.gv2 .g2-ground{position:relative;height:330px;margin:0 -12px;border-radius:22px;overflow:hidden;
background:radial-gradient(120% 60% at 50% 105%,#FFE3D8 0%,rgba(255,227,216,0) 70%),linear-gradient(180deg,#FFF8F2 0%,#FFF0E8 55%,#FFE8DE 100%);
box-shadow:inset 0 0 0 1px rgba(242,98,126,.08)}
#gcHome.gv2 .g2-floor{position:absolute;left:-40%;right:-40%;top:18%;bottom:-30%;pointer-events:none;transform:perspective(260px) rotateX(58deg);transform-origin:50% 0;
background:repeating-linear-gradient(90deg,rgba(232,150,130,.13) 0 1px,transparent 1px 38px),repeating-linear-gradient(0deg,rgba(232,150,130,.13) 0 1px,transparent 1px 38px);
-webkit-mask-image:linear-gradient(180deg,transparent,#000 35%);mask-image:linear-gradient(180deg,transparent,#000 35%)}
#gcHome.gv2 .g2-ground::after{content:"";position:absolute;left:50%;top:178px;width:250px;height:100px;margin-left:-125px;border-radius:50%;pointer-events:none;
border:2px dashed rgba(244,89,60,.12);background:radial-gradient(closest-side,rgba(255,255,255,.55),rgba(255,255,255,0))}
/* 头像 */
#gcHome.gv2 .g2-mom{position:absolute;width:var(--s);height:var(--s);margin:calc(var(--s)/-2) 0 0 calc(var(--s)/-2);padding:0;border:0;background:none;z-index:2;
animation:g2bob var(--d) ease-in-out var(--dl) infinite;-webkit-tap-highlight-color:transparent}
#gcHome.gv2 .g2-mom.near{z-index:3}
#gcHome.gv2 .g2-face{position:relative;display:block;width:100%;height:100%;border-radius:50%;overflow:hidden;border:2px solid #fff;box-sizing:border-box;background:#F6E3DC;
box-shadow:0 4px 10px -4px rgba(150,70,60,.45);transition:transform .35s ease,opacity .35s ease,box-shadow .35s ease}
#gcHome.gv2 .g2-face img{width:100%;height:100%;object-fit:cover;object-position:50% 22%;display:block}
#gcHome.gv2 .g2-mom:not(.near) .g2-face{opacity:.86;filter:saturate(.85)}
#gcHome.gv2 .g2-shadow{position:absolute;left:12%;right:12%;bottom:calc(var(--s)*-.16);height:calc(var(--s)*.18);border-radius:50%;background:rgba(170,90,70,.16);filter:blur(2px)}
#gcHome.gv2 .g2-mom.talk .g2-face{transform:scale(1.1);box-shadow:0 0 0 2px var(--ring,#F2627E),0 6px 14px -4px rgba(150,70,60,.5)}
#gcHome.gv2 .g2-ground.swap .g2-face{opacity:0;transform:scale(.6)}
@keyframes g2bob{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
/* 话题气泡 */
#gcHome.gv2 .g2-bub{position:absolute;width:158px;box-sizing:border-box;padding:7px 9px 8px;border-radius:14px;z-index:5;cursor:pointer;
background:linear-gradient(160deg,#fff 30%,var(--bg,#FFF0F3));border:1.5px solid var(--bc,#FFD0DC);box-shadow:0 8px 18px -10px rgba(150,70,60,.45);
opacity:0;transform:translateY(6px) scale(.96);transform-origin:var(--tx,50%) 100%;transition:opacity .4s ease,transform .4s ease;pointer-events:none}
#gcHome.gv2 .g2-bub.on{opacity:1;transform:none;pointer-events:auto}
#gcHome.gv2 .g2-bub-cat{display:block;font-size:11px;font-weight:800;line-height:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#gcHome.gv2 .g2-bub-t{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;margin-top:2px;font-size:12px;line-height:16px;font-weight:800;color:#2A1E1E}
#gcHome.gv2 .g2-tail{position:absolute;left:var(--tx,50%);bottom:-6px;width:10px;height:10px;margin-left:-5px;background:var(--bg,#FFF0F3);
border-right:1.5px solid var(--bc,#FFD0DC);border-bottom:1.5px solid var(--bc,#FFD0DC);transform:rotate(45deg);border-bottom-right-radius:3px}
/* 空位(投稿入口) */
#gcHome.gv2 .g2-seat{position:absolute;right:10px;bottom:14px;z-index:4;display:flex;align-items:center;gap:7px;padding:5px 11px 5px 5px;border:0;border-radius:30px;
background:rgba(255,255,255,.72);box-shadow:0 6px 14px -10px rgba(244,89,60,.6);font:inherit;text-align:left;-webkit-tap-highlight-color:transparent}
#gcHome.gv2 .g2-seat-o{flex:none;width:40px;height:40px;border-radius:50%;border:2px dashed #F4A08C;box-sizing:border-box;display:flex;align-items:center;justify-content:center;
font-size:15px;font-weight:900;color:#F4593C;background:#FFF5F1;animation:g2seat 2.8s ease-in-out infinite}
#gcHome.gv2 .g2-seat-t{display:flex;flex-direction:column;line-height:16px}
#gcHome.gv2 .g2-seat-t b{font-size:12.5px;font-weight:900;color:#2A1E1E}
#gcHome.gv2 .g2-seat-t em{font-style:normal;font-size:11px;font-weight:800;color:#F4593C}
@keyframes g2seat{0%,100%{border-color:#F4A08C}50%{border-color:#F4593C}}
/* 分类胶囊 */
#gcHome.gv2 .g2-foot{display:flex;align-items:center;gap:8px;margin-top:10px}
#gcHome.gv2 .g2-cats{flex:1;min-width:0;display:flex;gap:7px;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:2px 0}
#gcHome.gv2 .g2-cats::-webkit-scrollbar{display:none}
#gcHome.gv2 .g2-cats button{flex:none;height:28px;padding:0 13px;display:flex;align-items:center;justify-content:center;text-align:center;border:1px solid #F3E2DC;border-radius:14px;background:#FFFAF7;
font:inherit;font-size:12.5px;font-weight:700;color:#8A7470;white-space:nowrap;transition:background .25s,color .25s,border-color .25s}
#gcHome.gv2 .g2-cats button.on{background:var(--ck,#F2627E);border-color:var(--ck,#F2627E);color:#fff;font-weight:800;box-shadow:0 5px 12px -8px var(--ck,#F2627E)}
#gcHome.gv2 .g2-mark{margin-left:auto;font-size:11px;color:#C4B5B1}
@media (prefers-reduced-motion:reduce){
#gcHome.gv2 .g2-mom,#gcHome.gv2 .g2-seat-o{animation:none}
#gcHome.gv2 .g2-bub,#gcHome.gv2 .g2-face{transition:none}
}
#gcHome.gv2 *{text-wrap:balance}

BIN
demo/gch/v2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

149
demo/gch/v2.js Normal file
View File

@@ -0,0 +1,149 @@
/* 首页「孕妈广场」效果稿 V2 · 广场人群:一块俯视的广场空地,十几位妈妈近大远小站着,3 位头上冒话题气泡轮换;
下方分类胶囊切换时人群换一批;右下角一个虚线「空位」是投稿入口。只在 ?gcv=2 时加载。 */
(function () {
var sec = document.getElementById('gcHome');
var ALL = window.GC_TOPICS;
if (!sec || !ALL || !ALL.length) return;
var esc = function (s) { return String(s).replace(/[&<>"']/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]; }); };
var fmt = function (n) { return n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
var go = function (id) { location.href = (id ? 'guangchang/?t=' + id : 'guangchang/') + location.hash; };
var CATS = [['', '全部'], ['family', '家庭婚姻'], ['work', '职场'], ['baby', '经验']];
var CATN = { family: '家庭婚姻', work: '职场', baby: '经验' };
var MOMS = [];
for (var i = 1; i <= 22; i++) MOMS.push('m' + (i < 10 ? '0' : '') + i);
for (i = 1; i <= 14; i++) MOMS.push('p' + (i < 10 ? '0' : '') + i);
var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
/* 站位(x 为宽度百分比,y 为头像中心距空地顶 px,s 为直径):上远小、下近大;z 为气泡区 A 左上 / B 右上 / C 前排 */
var SLOTS = [
{ x: 9, y: 22, s: 24 }, { x: 33, y: 16, s: 22 }, { x: 54, y: 30, s: 26 }, { x: 76, y: 15, s: 22 },
{ x: 20, y: 74, s: 28 }, { x: 78, y: 82, s: 28 },
{ x: 11, y: 148, s: 40, z: 'A' }, { x: 36, y: 154, s: 40, z: 'A' }, { x: 63, y: 140, s: 40, z: 'B' }, { x: 88, y: 152, s: 40, z: 'B' },
{ x: 58, y: 222, s: 40 }, { x: 87, y: 212, s: 34 },
{ x: 12, y: 278, s: 50, z: 'C' }, { x: 35, y: 264, s: 48, z: 'C' }
];
var BW = 158, PAD = 5; // 气泡宽(按空地宽度再收窄)、离空地边距
var hash = function (s) { var x = 7; for (var k = 0; k < s.length; k++) x = (x * 31 + s.charCodeAt(k)) | 0; return Math.abs(x); };
var shuffle = function (arr, seed) { var a = arr.slice(), r = seed || 1; for (var k = a.length - 1; k > 0; k--) { r = (r * 9301 + 49297) % 233280; var j = Math.floor(r / 233280 * (k + 1)); var t = a[k]; a[k] = a[j]; a[j] = t; } return a; };
var cat = '', pool = [], qi = 0, faces = [], topicOf = [], speak = { A: -1, B: -1, C: -1 }, timer = 0, turn = 0, batch = 0;
sec.classList.add('gv2');
sec.classList.remove('hide');
sec.innerHTML =
'<div class="g2-head">' +
'<h2 class="g2-title"><span>孕妈广场</span></h2>' +
'<button type="button" class="g2-more" data-go="">去逛逛<i aria-hidden="true">›</i></button>' +
'</div>' +
'<div class="g2-sub"><i class="g2-live" aria-hidden="true"></i><b id="g2Cnt"></b> 位妈妈正在广场上聊<span class="g2-mark">效果稿 V2</span></div>' +
'<div class="g2-ground" id="g2Ground">' +
'<div class="g2-floor" aria-hidden="true"></div>' +
SLOTS.map(function (p, k) {
return '<button type="button" class="g2-mom' + (p.z ? ' near' : '') + '" data-k="' + k + '" style="left:' + p.x + '%;top:' + p.y + 'px;--s:' + p.s + 'px;--d:' + (2.6 + (k % 5) * 0.45).toFixed(2) + 's;--dl:-' + (k * 0.37 % 2.4).toFixed(2) + 's">' +
'<i class="g2-shadow" aria-hidden="true"></i><span class="g2-face"><img alt="" loading="lazy" decoding="async"></span></button>';
}).join('') +
'<div class="g2-bub" data-z="A"></div><div class="g2-bub" data-z="B"></div><div class="g2-bub" data-z="C"></div>' +
'<button type="button" class="g2-seat" data-go=""><span class="g2-seat-o">你</span><span class="g2-seat-t"><b>坐下来说说</b><em>¥30+500兜豆</em></span></button>' +
'</div>' +
'<div class="g2-foot">' +
'<div class="g2-cats" role="tablist" aria-label="话题分类">' +
CATS.map(function (c) { return '<button type="button" role="tab" data-cat="' + c[0] + '"' + (c[0] ? ' style="--ck:' + ({ family: '#E0566F', work: '#3A72B8', baby: '#2E8A7C' })[c[0]] + '"' : '') + '>' + c[1] + '</button>'; }).join('') +
'</div>' +
'</div>';
var ground = sec.querySelector('#g2Ground');
var moms = [].slice.call(sec.querySelectorAll('.g2-mom'));
var bubs = {}; [].forEach.call(sec.querySelectorAll('.g2-bub'), function (b) { bubs[b.getAttribute('data-z')] = b; });
function nextTopic() { var t = pool[qi % pool.length]; qi++; return t; }
function bubbleHTML(t) {
return '<span class="g2-bub-cat" style="color:' + t.ink + '">' + CATN[t.cat] + ' · ' + fmt(t.talk) + ' 在聊</span>' +
'<span class="g2-bub-t">' + esc(t.name) + '</span><i class="g2-tail" aria-hidden="true"></i>';
}
function place(z, k) {
var b = bubs[z], p = SLOTS[k], W = ground.clientWidth || 340, cx = W * p.x / 100;
BW = Math.min(158, Math.floor((W - PAD * 3) / 2));
b.style.width = BW + 'px';
var left = z === 'A' ? PAD : z === 'B' ? W - PAD - BW : Math.max(PAD, Math.min(W - PAD - BW, cx - BW / 2));
var t = topicOf[k];
b.innerHTML = bubbleHTML(t);
b.style.left = left + 'px';
b.style.bottom = (ground.clientHeight - (p.y - p.s / 2) + 7) + 'px';
b.style.setProperty('--tx', Math.max(14, Math.min(BW - 14, cx - left)) + 'px');
b.style.setProperty('--bc', t.c[1]);
b.style.setProperty('--bg', t.c[0]);
b.setAttribute('data-k', k);
b.setAttribute('role', 'button');
b.setAttribute('aria-label', t.name);
moms.forEach(function (m) { if (+m.getAttribute('data-k') === k) { m.classList.add('talk'); m.style.setProperty('--ring', t.ink); } });
}
function candidates(z) { var r = []; SLOTS.forEach(function (p, k) { if (p.z === z) r.push(k); }); return r; }
function rotate(z, first) {
var b = bubs[z], old = speak[z], c = candidates(z), k;
do { k = c[Math.floor(Math.random() * c.length)]; } while (c.length > 1 && k === old);
if (first) k = c[(batch + (z === 'B' ? 1 : 0)) % c.length];
var show = function () {
if (old >= 0) moms[old].classList.remove('talk');
topicOf[k] = nextTopic();
speak[z] = k;
place(z, k);
b.classList.add('on');
};
if (first || reduce) { show(); return; }
b.classList.remove('on');
setTimeout(show, 420);
}
function setCat(c, first) {
cat = c;
batch++;
pool = shuffle(ALL.filter(function (t) { return !c || t.cat === c; }), hash(c || 'all') + batch);
qi = 0;
var picks = shuffle(MOMS, hash('m' + c) + batch * 7);
[].forEach.call(sec.querySelectorAll('.g2-cats button'), function (b) { var on = b.getAttribute('data-cat') === c; b.classList.toggle('on', on); b.setAttribute('aria-selected', on ? 'true' : 'false'); });
sec.querySelector('#g2Cnt').textContent = pool.reduce(function (a, t) { return a + t.talk; }, 0).toLocaleString('en-US');
var apply = function () {
moms.forEach(function (m, k) {
faces[k] = picks[k % picks.length];
topicOf[k] = nextTopic();
m.querySelector('img').src = 'assets/img/mom/' + faces[k] + '.jpg';
m.classList.remove('talk');
m.setAttribute('aria-label', topicOf[k].name);
});
speak = { A: -1, B: -1, C: -1 };
['A', 'B', 'C'].forEach(function (z) { rotate(z, true); });
ground.classList.remove('swap');
};
if (first || reduce) { apply(); return; }
ground.classList.add('swap');
['A', 'B', 'C'].forEach(function (z) { bubs[z].classList.remove('on'); });
setTimeout(apply, 380);
}
function loop() {
clearInterval(timer);
if (reduce) return;
timer = setInterval(function () {
if (document.hidden) return;
rotate(['A', 'C', 'B'][turn++ % 3]);
}, 3200);
}
sec.addEventListener('click', function (e) {
var el = e.target.closest('[data-cat],[data-go],.g2-mom,.g2-bub');
if (!el || !sec.contains(el)) return;
if (el.hasAttribute('data-cat')) { var c = el.getAttribute('data-cat'); if (c !== cat) { setCat(c); loop(); } return; }
if (el.hasAttribute('data-go')) { go(''); return; }
var k = +el.getAttribute('data-k');
if (topicOf[k]) go(topicOf[k].id);
});
setCat('', true);
loop();
})();

72
demo/gch/v3.css Normal file
View File

@@ -0,0 +1,72 @@
/* 11-02 首页「孕妈广场」效果稿 V3 · 话题弹幕流(只在 ?gcv=3 时加载,全部限定在 #gcHome.gv3) */
#gcHome.gv3{position:relative;z-index:0;margin:16px -26px 0;border-radius:26px;padding:16px 26px 14px;background:linear-gradient(180deg,#fff 0%,#FFFAF6 100%);box-shadow:0 10px 26px -18px rgba(214,120,110,.35);overflow:hidden}
#gcHome.gv3 button{font:inherit;-webkit-tap-highlight-color:transparent}
#gcHome.gv3 .v3-head{display:flex;align-items:center;gap:8px}
#gcHome.gv3 .v3-title{flex:none;margin:0;font-size:21px;font-weight:900;letter-spacing:.5px;color:#2A1E1E}
#gcHome.gv3 .v3-title span{background:linear-gradient(transparent 58%,#FFD0DC 58%,#FFD0DC 92%,transparent 92%);padding:0 3px}
#gcHome.gv3 .v3-live{display:inline-flex;align-items:center;gap:5px;min-width:0;font-size:11px;color:#A48C86;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
#gcHome.gv3 .v3-live i{flex:none;width:6px;height:6px;border-radius:50%;background:#4CC38A;box-shadow:0 0 0 3px rgba(76,195,138,.18)}
#gcHome.gv3 .v3-more{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:2px;height:26px;padding:0 4px 0 10px;border:0;border-radius:99px;background:linear-gradient(135deg,#FF8A9E,#F2627E);font-size:12px;font-weight:800;color:#fff;box-shadow:0 4px 10px rgba(242,98,126,.28)}
#gcHome.gv3 .v3-more i{font-style:normal;font-size:15px;line-height:1;padding:0 4px 1px 1px}
#gcHome.gv3 .v3-cat{display:flex;margin:12px 0 0;padding:2px;border-radius:99px;background:rgba(240,222,214,.6)}
#gcHome.gv3 .v3-cat button{flex:1;min-width:0;height:28px;padding:0 4px;border:0;border-radius:99px;background:none;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;font-weight:700;color:#9A7F78;white-space:nowrap;transition:background .2s,color .2s}
#gcHome.gv3 .v3-cat button.on{background:#fff;color:#D9466A;box-shadow:0 1px 4px rgba(190,110,120,.18)}
/* 此刻最热 */
#gcHome.gv3 .v3-hot{display:block;width:100%;margin:12px 0 0;padding:0;border:0;background:none;text-align:left}
#gcHome.gv3 .v3-hot-in{display:flex;align-items:center;gap:11px;padding:8px 10px 8px 8px;border-radius:18px;background:linear-gradient(120deg,#FFF3EC,#FFEFF2);box-shadow:inset 0 0 0 1px rgba(244,89,60,.08);transition:opacity .3s,transform .3s}
#gcHome.gv3 .v3-hot.out .v3-hot-in{opacity:0;transform:translateY(4px)}
#gcHome.gv3 .v3-hot:active .v3-hot-in{transform:scale(.98)}
#gcHome.gv3 .v3-ph{flex:none;width:60px;height:72px;border-radius:13px;object-fit:cover;background:#F0E2DA;display:grid;place-items:center;font-size:26px;font-weight:900}
#gcHome.gv3 .v3-hb{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
#gcHome.gv3 .v3-hk{display:flex;align-items:center;gap:5px;font-size:11px;font-weight:800;color:#C2705A;letter-spacing:.3px;white-space:nowrap}
#gcHome.gv3 .v3-hk em{font-style:normal;height:16px;padding:0 5px;border-radius:5px;background:linear-gradient(135deg,#FF7A45,#F4433C);color:#fff;font-size:11px;line-height:16px}
#gcHome.gv3 .v3-hk i{width:5px;height:5px;border-radius:50%;margin-left:4px;opacity:.8}
#gcHome.gv3 .v3-hk i+*{color:#A48C86}
#gcHome.gv3 .v3-hn{font-size:14px;font-weight:900;line-height:1.35;color:#2F2424;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-wrap:balance}
#gcHome.gv3 .v3-hm{display:flex;align-items:center;gap:6px;font-size:11px;color:#9A817B;font-variant-numeric:tabular-nums}
#gcHome.gv3 .v3-avs{display:flex}
#gcHome.gv3 .v3-avs img{width:16px;height:16px;border-radius:50%;object-fit:cover;border:1.5px solid #fff;margin-left:-5px;background:#FFE3D3}
#gcHome.gv3 .v3-avs img:first-child{margin-left:0}
#gcHome.gv3 .v3-go{flex:none;font-size:18px;color:#E7A796;line-height:1}
/* 弹幕区:三行,左右渐隐;整块外扩到卡片边缘 */
#gcHome.gv3 .v3-dm{position:relative;margin:12px -26px 0;padding:2px 0;display:flex;flex-direction:column;gap:8px;overflow:hidden;overscroll-behavior-x:contain;touch-action:pan-y;
-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 34px,#000 calc(100% - 34px),transparent 100%);mask-image:linear-gradient(90deg,transparent 0,#000 34px,#000 calc(100% - 34px),transparent 100%);transition:opacity .26s}
#gcHome.gv3 .v3-dm.swap{opacity:0}
#gcHome.gv3 .v3-row{overflow:hidden;height:32px}
#gcHome.gv3 .v3-track{display:flex;width:max-content;animation:v3Flow 60s linear infinite;will-change:transform}
#gcHome.gv3 .v3-track.rev{animation-name:v3FlowR}
#gcHome.gv3 .v3-row:nth-child(2) .v3-track{padding-left:40px}
#gcHome.gv3 .v3-dm.hold .v3-track{animation-play-state:paused}
@keyframes v3Flow{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
@keyframes v3FlowR{from{transform:translate3d(-50%,0,0)}to{transform:translate3d(0,0,0)}}
#gcHome.gv3 .v3-grp{display:flex;flex:none}
#gcHome.gv3 .v3-chip{flex:none;display:inline-flex;align-items:center;gap:6px;height:32px;margin-right:10px;padding:0 11px 0 4px;border:0;border-radius:99px;
background:linear-gradient(90deg,#fff 30%,var(--c1));box-shadow:inset 0 0 0 1px rgba(0,0,0,.035),0 2px 6px -3px rgba(180,120,110,.25);color:#5A4743}
#gcHome.gv3 .v3-row:nth-child(2) .v3-chip{background:#fff}
#gcHome.gv3 .v3-chip:active{transform:scale(.96)}
#gcHome.gv3 .v3-chip img{flex:none;width:24px;height:24px;border-radius:50%;object-fit:cover;background:#FFE3D3}
#gcHome.gv3 .v3-chip span{min-width:0;font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#gcHome.gv3 .v3-chip em{flex:none;font-style:normal;font-size:11px;font-weight:800;color:#F4593C}
#gcHome.gv3 .v3-chip i{flex:none;width:6px;height:6px;border-radius:50%;background:var(--cc);opacity:.65}
/* 投稿入口:细长一条 */
#gcHome.gv3 .v3-post{display:flex;align-items:center;gap:7px;width:100%;height:38px;margin:14px 0 0;padding:0 8px 0 6px;border:1px dashed #F5BFAE;border-radius:99px;background:#FFF8F4;text-align:left}
#gcHome.gv3 .v3-post:active{background:#FFEFE7}
#gcHome.gv3 .v3-post b{flex:none;width:26px;height:26px;border-radius:50%;display:grid;place-items:center;background:linear-gradient(135deg,#FF8A5B,#F4593C);color:#fff}
#gcHome.gv3 .v3-post b svg{width:14px;height:14px}
#gcHome.gv3 .v3-post span{flex:none;font-size:12.5px;font-weight:800;color:#6B4A40}
#gcHome.gv3 .v3-post em{flex:1;min-width:0;font-style:normal;font-size:11px;font-weight:700;color:#E2553A;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:-.1px}
#gcHome.gv3 .v3-post em::before{content:"·";margin-right:5px;color:#D9B3A6}
#gcHome.gv3 .v3-post i{flex:none;font-style:normal;font-size:16px;color:#E7A796}
#gcHome.gv3 .v3-tag{display:block;margin:8px 0 0;text-align:right;font-size:11px;color:#C9BDB9}
@media (prefers-reduced-motion: reduce){
#gcHome.gv3 .v3-track{animation:none!important}
#gcHome.gv3 .v3-row{overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none}
#gcHome.gv3 .v3-row::-webkit-scrollbar{display:none}
#gcHome.gv3 .v3-dm{touch-action:auto}
#gcHome.gv3 .v3-hot-in,#gcHome.gv3 .v3-dm{transition:none}
}

BIN
demo/gch/v3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

129
demo/gch/v3.js Normal file
View File

@@ -0,0 +1,129 @@
/* 11-02 首页「孕妈广场」效果稿 V3 · 话题弹幕流(只在 ?gcv=3 时加载)
「此刻最热」小卡(真实照片 + 热)→ 三行缓慢流动的话题弹幕(按住暂停、点进话题)→ 细长投稿入口。分类切换后弹幕换成该分类话题。 */
(function () {
var sec = document.getElementById('gcHome');
var T = window.GC_TOPICS;
if (!sec || !Array.isArray(T) || !T.length) return;
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var kfmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
var fmtNum = function (n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ','); };
var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
var POOL = [];
for (var i = 1; i <= 22; i++) POOL.push('m' + (i < 10 ? '0' : '') + i);
for (i = 1; i <= 14; i++) POOL.push('p' + (i < 10 ? '0' : '') + i);
var ava = function (k) { return 'assets/img/mom/' + POOL[k % POOL.length] + '.jpg'; };
var CAT = { family: ['家庭婚姻', '#E0566F'], work: ['职场', '#3A72B8'], baby: ['经验', '#2E8A7C'] };
var ORDER = ['family', 'work', 'baby'];
function go(id) {
location.href = 'guangchang/' + (id ? '?t=' + encodeURIComponent(id) : '') + location.hash;
}
/* 「全部」三块轮流排,避免一行同色;某一块:热门在前 */
function pick(cat) {
if (cat) { var l = T.filter(function (t) { return t.cat === cat; }); return l.filter(function (t) { return t.hot; }).concat(l.filter(function (t) { return !t.hot; })); }
var by = ORDER.map(function (c) { return T.filter(function (t) { return t.cat === c; }); }), out = [];
for (var r = 0; r < 20; r++) by.forEach(function (l) { if (l[r]) out.push(l[r]); });
return out;
}
var talkAll = T.reduce(function (a, t) { return a + (t.talk || 0); }, 0);
sec.className = 'gc-home gv3';
sec.innerHTML =
'<div class="v3-head">' +
'<h2 class="v3-title"><span>孕妈广场</span></h2>' +
'<span class="v3-live"><i></i>' + kfmt(talkAll) + ' 妈妈在聊</span>' +
'<button type="button" class="v3-more" data-go="">去逛逛<i aria-hidden="true">›</i></button>' +
'</div>' +
'<div class="v3-cat" role="tablist" aria-label="话题分类">' +
'<button type="button" class="on" data-cat="">全部</button>' +
'<button type="button" data-cat="family">家庭婚姻</button>' +
'<button type="button" data-cat="work">职场</button>' +
'<button type="button" data-cat="baby">经验</button>' +
'</div>' +
'<button type="button" class="v3-hot" id="v3Hot"></button>' +
'<div class="v3-dm" id="v3Dm" aria-label="正在聊的话题"></div>' +
'<button type="button" class="v3-post" data-go=""><b><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 20h4L19 9l-4-4L4 16z"/><path d="M13.5 6.5l4 4"/></svg></b><span>发一条你的故事</span><em>被选中 ¥30+500兜豆</em><i aria-hidden="true">›</i></button>' +
'<span class="v3-tag">效果稿 V3</span>';
sec.classList.remove('hide');
var hotEl = document.getElementById('v3Hot'), dm = document.getElementById('v3Dm');
var hotList = [], hotIdx = 0, hotTimer = 0;
function hotHtml(t) {
var c = CAT[t.cat] || ['', '#E0566F'], k = t.id.charCodeAt(1) * 3;
return '<span class="v3-hot-in">' +
(t.ph ? '<img class="v3-ph" src="' + esc(t.ph) + '" alt="" loading="lazy">' : '<span class="v3-ph v3-g" style="background:linear-gradient(150deg,' + t.c[0] + ',' + t.c[1] + ');color:' + t.ink + '">' + esc(t.g) + '</span>') +
'<span class="v3-hb">' +
'<span class="v3-hk"><em>热</em>此刻最热<i style="background:' + c[1] + '"></i>' + c[0] + '</span>' +
'<span class="v3-hn">' + esc(t.name) + '</span>' +
'<span class="v3-hm"><span class="v3-avs"><img src="' + ava(k) + '" alt="" loading="lazy"><img src="' + ava(k + 5) + '" alt="" loading="lazy"><img src="' + ava(k + 11) + '" alt="" loading="lazy"></span>' + fmtNum(t.talk) + ' 人在聊</span>' +
'</span><span class="v3-go" aria-hidden="true">›</span></span>';
}
function showHot(fade) {
var t = hotList[hotIdx % hotList.length];
if (!t) return;
hotEl.dataset.t = t.id;
if (!fade || reduce) { hotEl.innerHTML = hotHtml(t); return; }
hotEl.classList.add('out');
setTimeout(function () { hotEl.innerHTML = hotHtml(t); hotEl.classList.remove('out'); }, 320);
}
function chip(t, k) {
var c = CAT[t.cat] || ['', '#E0566F'];
return '<button type="button" class="v3-chip" data-t="' + esc(t.id) + '" style="--cc:' + c[1] + ';--c1:' + t.c[0] + '" tabindex="-1">' +
'<img src="' + ava(k * 7 + 3) + '" alt="" loading="lazy">' +
'<span>' + esc(t.name) + '</span>' + (t.hot ? '<em>热</em>' : '') + '<i></i></button>';
}
/* 三行:方向 左/右/左,速度 px/s 略不同;每行一组内容不够宽就重复,再整体复制一份做无缝循环 */
var ROWS = [{ dir: 1, v: 13, d: 0 }, { dir: -1, v: 10, d: -9 }, { dir: 1, v: 15.5, d: -4 }];
function paint(cat) {
var list = pick(cat);
hotList = list.filter(function (t) { return t.hot && t.ph; });
if (!hotList.length) hotList = list.slice(0, 3);
hotIdx = 0; showHot(false);
var rows = [[], [], []];
list.forEach(function (t, j) { rows[j % 3].push(t); });
dm.innerHTML = rows.map(function (r, ri) {
var base = r.slice();
while (base.length < 6) base = base.concat(r);
var g = base.map(function (t, j) { return chip(t, ri * 13 + j); }).join('');
return '<div class="v3-row"><div class="v3-track' + (ROWS[ri].dir < 0 ? ' rev' : '') + '"><div class="v3-grp">' + g + '</div><div class="v3-grp" aria-hidden="true">' + g + '</div></div></div>';
}).join('');
requestAnimationFrame(function () {
Array.prototype.forEach.call(dm.querySelectorAll('.v3-track'), function (tr, ri) {
var w = tr.firstElementChild.offsetWidth || 600, dur = w / ROWS[ri].v;
tr.style.animationDuration = dur.toFixed(1) + 's';
tr.style.animationDelay = (ROWS[ri].d - ri * 3) + 's';
});
});
}
paint('');
if (!reduce) hotTimer = setInterval(function () {
if (dm.classList.contains('hold') || document.hidden) return;
hotIdx++; showHot(true);
}, 5200);
/* 按住暂停(松手 / 纵向滚动被系统接管时恢复) */
var hold = function (on) { dm.classList.toggle('hold', on); };
dm.addEventListener('pointerdown', function () { hold(true); });
['pointerup', 'pointercancel', 'pointerleave'].forEach(function (ev) { dm.addEventListener(ev, function () { hold(false); }); });
dm.addEventListener('touchstart', function () { hold(true); }, { passive: true });
dm.addEventListener('touchend', function () { hold(false); }, { passive: true });
dm.addEventListener('touchcancel', function () { hold(false); }, { passive: true });
sec.addEventListener('click', function (e) {
var cb = e.target.closest('[data-cat]');
if (cb) {
if (cb.classList.contains('on')) return;
Array.prototype.forEach.call(sec.querySelectorAll('.v3-cat button'), function (x) { x.classList.toggle('on', x === cb); });
if (reduce) { paint(cb.dataset.cat); return; }
dm.classList.add('swap');
setTimeout(function () { paint(cb.dataset.cat); dm.classList.remove('swap'); }, 260);
return;
}
var t = e.target.closest('[data-t]');
if (t && sec.contains(t)) { go(t.dataset.t); return; }
if (e.target.closest('[data-go]')) go('');
});
})();

BIN
demo/gch/v4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

79
demo/gch/v5.css Normal file
View File

@@ -0,0 +1,79 @@
/* 首页「孕妈广场」效果稿 V5 · 今日一问 + 话题横滑 */
#gcHome.gv5{margin:16px -26px 0;padding:18px 26px 16px;border-radius:26px;position:relative;z-index:0;background-color:#fff}
#gcHome.gv5 button{font:inherit;-webkit-tap-highlight-color:transparent}
#gcHome.gv5 .g5-head{display:flex;align-items:center;gap:8px}
#gcHome.gv5 .g5-title{margin:0;font-size:21px;font-weight:900;letter-spacing:.5px;color:#2A1E1E}
#gcHome.gv5 .g5-title span{background:linear-gradient(transparent 58%,#FFD0DC 58%,#FFD0DC 92%,transparent 92%);padding:0 3px}
#gcHome.gv5 .g5-tag{font-size:11px;color:#C4B5B1;font-weight:500;align-self:flex-end;margin-bottom:3px}
#gcHome.gv5 .g5-more{margin-left:auto;display:inline-flex;align-items:center;gap:2px;height:26px;padding:0 4px 0 6px;border:0;background:none;font-size:13px;font-weight:700;color:#E0566F}
#gcHome.gv5 .g5-more i{font-style:normal;font-size:16px;line-height:1;margin-top:-1px}
/* 今日一问卡 */
#gcHome.gv5 .q5{position:relative;margin-top:12px;padding:14px 14px 12px;border-radius:20px;overflow:hidden;
background:radial-gradient(120px 90px at 100% 0,rgba(255,196,170,.45),transparent 70%),linear-gradient(150deg,#FFF6F1 0%,#FFEDF1 100%);
box-shadow:inset 0 0 0 1px rgba(242,98,126,.10),0 10px 22px -16px rgba(226,90,80,.45)}
#gcHome.gv5 .q5::before{content:"\201C";position:absolute;right:10px;top:-14px;font-size:96px;font-weight:900;line-height:1;color:#FFD0DC;opacity:.7;font-family:Georgia,serif;pointer-events:none}
#gcHome.gv5 .q5-top{position:relative;display:flex;align-items:center;gap:8px}
#gcHome.gv5 .q5-k{display:inline-flex;align-items:center;gap:5px;height:22px;padding:0 9px;border-radius:99px;background:linear-gradient(120deg,#FF8A5B,#F4593C);color:#fff;font-size:11.5px;font-weight:800;letter-spacing:.3px}
#gcHome.gv5 .q5-k i{width:6px;height:6px;border-radius:50%;background:#fff;opacity:.9}
#gcHome.gv5 .q5-d{font-size:11px;color:#B08F88;font-weight:600}
#gcHome.gv5 .q5-q{position:relative;margin:10px 0 12px;font-size:17px;font-weight:900;line-height:1.4;color:#2F2424;letter-spacing:.2px}
#gcHome.gv5 .q5-act{position:relative;min-height:44px}
#gcHome.gv5 .q5-btns{display:flex;gap:10px}
#gcHome.gv5 .q5-v{flex:1;min-width:0;height:40px;padding:0 8px;border-radius:14px;display:flex;align-items:center;justify-content:center;text-align:center;font-size:14px;font-weight:800;white-space:nowrap;transition:transform .15s}
#gcHome.gv5 .q5-v.a{border:0;background:linear-gradient(135deg,#FF8A9E,#F2627E);color:#fff;box-shadow:0 8px 14px -10px #F2627E}
#gcHome.gv5 .q5-v.b{border:1.5px solid #FFC2A8;background:#fff;color:#E2553A}
#gcHome.gv5 .q5-v:active{transform:scale(.96)}
#gcHome.gv5 .q5-lab{display:flex;justify-content:space-between;gap:8px;font-size:12px;font-weight:700;color:#9A7F78}
#gcHome.gv5 .q5-lab span{display:inline-flex;align-items:center;gap:3px;white-space:nowrap}
#gcHome.gv5 .q5-lab b{font-size:14px;font-weight:900;font-variant-numeric:tabular-nums}
#gcHome.gv5 .q5-lab .la b{color:#F2627E}
#gcHome.gv5 .q5-lab .lb b{color:#F4893C}
#gcHome.gv5 .q5-res.pa .la,#gcHome.gv5 .q5-res.pb .lb{color:#3A2A2A}
#gcHome.gv5 .q5-lab i{font-style:normal;width:15px;height:15px;border-radius:50%;display:inline-grid;place-items:center;font-size:10px;background:#F2627E;color:#fff}
#gcHome.gv5 .q5-res.pb .q5-lab i{background:#F4893C}
#gcHome.gv5 .q5-bar{display:flex;gap:3px;height:9px;margin-top:6px;border-radius:99px;overflow:hidden}
#gcHome.gv5 .q5-bar .ba{flex:none;width:var(--w);background:linear-gradient(90deg,#FF9AAD,#F2627E);border-radius:99px 0 0 99px;transition:width .6s cubic-bezier(.2,.8,.2,1)}
#gcHome.gv5 .q5-bar .bb{flex:1;background:linear-gradient(90deg,#FFB27A,#F4893C);border-radius:0 99px 99px 0}
#gcHome.gv5 .q5-res.in .ba{width:50%}
#gcHome.gv5 .q5-see{display:inline-flex;align-items:center;gap:2px;margin-top:8px;padding:0;border:0;background:none;font-size:12.5px;font-weight:800;color:#E0566F}
#gcHome.gv5 .q5-see i{font-style:normal;font-size:15px;line-height:1}
#gcHome.gv5 .q5-who{position:relative;display:flex;align-items:center;gap:7px;margin-top:10px;padding-top:10px;border-top:1px dashed rgba(226,140,130,.28);font-size:12px;color:#9A7F78}
#gcHome.gv5 .q5-who b{color:#D9466A;font-weight:800;font-variant-numeric:tabular-nums}
#gcHome.gv5 .q5-avs{display:flex}
#gcHome.gv5 .q5-avs img{width:22px;height:22px;border-radius:50%;object-fit:cover;border:2px solid #FFF3F2;margin-left:-7px;background:#FFE3D3}
#gcHome.gv5 .q5-avs img:first-child{margin-left:0}
/* 分类 */
#gcHome.gv5 .g5-cat{display:flex;gap:6px;margin:14px 0 0}
#gcHome.gv5 .g5-cat button{flex:none;height:28px;padding:0 13px;border:0;border-radius:99px;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;font-weight:700;color:#9A7F78;background:#F8F1EE;white-space:nowrap;transition:background .2s,color .2s}
#gcHome.gv5 .g5-cat button.on{background:#2F2424;color:#fff}
/* 横滑小方卡 */
#gcHome.gv5 .g5-row{display:flex;gap:10px;margin:10px -26px 0;padding:2px 26px 6px;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x proximity;scroll-padding:0 26px;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:none}
#gcHome.gv5 .g5-row::-webkit-scrollbar{display:none}
#gcHome.gv5 .g5-row::after{content:"";flex:none;width:16px}
#gcHome.gv5 .g5-c{flex:none;width:112px;padding:0;border:0;background:none;text-align:left;display:flex;flex-direction:column;scroll-snap-align:start;transition:transform .15s}
#gcHome.gv5 .g5-c:active{transform:scale(.97)}
#gcHome.gv5 .g5-p{position:relative;display:block;width:112px;height:112px;border-radius:16px;overflow:hidden;background:var(--c1,#F3E7E2);box-shadow:0 6px 14px -10px rgba(80,40,40,.5)}
#gcHome.gv5 .g5-p img{width:100%;height:100%;object-fit:cover;display:block}
#gcHome.gv5 .g5-p em{position:absolute;left:6px;top:6px;height:18px;padding:0 6px;border-radius:6px;background:rgba(255,255,255,.9);color:var(--ink);font-size:10.5px;font-style:normal;font-weight:800;line-height:18px}
#gcHome.gv5 .g5-p em.h{left:auto;right:6px;background:linear-gradient(135deg,#FF7A45,#F4433C);color:#fff}
#gcHome.gv5 .g5-n{margin-top:7px;font-size:13px;font-weight:800;line-height:1.38;color:#2F2424;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;height:36px}
#gcHome.gv5 .g5-m{display:inline-flex;align-items:center;gap:4px;margin-top:4px;font-size:11px;font-weight:600;color:#A8908A;white-space:nowrap}
#gcHome.gv5 .g5-m i{width:6px;height:6px;border-radius:50%;background:#43C08A;box-shadow:0 0 0 2px rgba(67,192,138,.18)}
#gcHome.gv5 .g5-sub{height:112px;align-items:center;justify-content:center;gap:2px;text-align:center;border-radius:16px;background:linear-gradient(150deg,#FFF1E6,#FFE2E8);box-shadow:inset 0 0 0 1.5px rgba(244,89,60,.18)}
#gcHome.gv5 .g5-s1{font-size:14px;font-weight:900;color:#2F2424}
#gcHome.gv5 .g5-s2{font-size:11px;color:#B08F88;font-weight:600;margin-top:2px}
#gcHome.gv5 .g5-s3{display:flex;align-items:baseline;gap:2px;color:#F4593C;font-weight:900}
#gcHome.gv5 .g5-s3 b{font-size:18px}
#gcHome.gv5 .g5-s3 span{font-size:11px}
#gcHome.gv5 .g5-s4{margin-top:4px;height:22px;padding:0 10px;border-radius:99px;background:linear-gradient(120deg,#FF8A5B,#F4593C);color:#fff;font-size:11px;font-weight:800;line-height:22px}
@media (prefers-reduced-motion:reduce){
#gcHome.gv5 *{transition:none!important;animation:none!important}
}

BIN
demo/gch/v5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

113
demo/gch/v5.js Normal file
View File

@@ -0,0 +1,113 @@
/* 首页「孕妈广场」效果稿 V5 · 今日一问 + 话题横滑(只在 ?gcv=5 时加载;不改仓库其他文件) */
(function () {
var sec = document.getElementById('gcHome'), T = window.GC_TOPICS;
if (!sec || !Array.isArray(T) || !T.length) return;
var esc = function (s) { return String(s == null ? '' : s).replace(/[&<>"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]; }); };
var num = function (n) { return String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ','); };
var kfmt = function (n) { return n >= 10000 ? (n / 10000).toFixed(1).replace(/\.0$/, '') + '万' : n >= 1000 ? (n / 1000).toFixed(1).replace(/\.0$/, '') + 'k' : String(n); };
var hash = function (s) { var x = 7; for (var i = 0; i < s.length; i++) x = (x * 31 + s.charCodeAt(i)) | 0; return Math.abs(x); };
var ava = function (n) { return 'assets/img/mom/' + n + '.jpg'; };
var MOMS = []; for (var i = 1; i <= 22; i++) MOMS.push('m' + (i < 10 ? '0' : '') + i); for (i = 1; i <= 14; i++) MOMS.push('p' + (i < 10 ? '0' : '') + i);
var go = function (id) { location.href = 'guangchang/' + (id ? '?t=' + encodeURIComponent(id) : '') + location.hash; };
var CAT_CN = { family: '家庭婚姻', work: '职场', baby: '经验' }, CATS = ['family', 'work', 'baby'];
/* 今日一问:按北京日期在热门话题里轮换;问法 + 两个立场是效果稿占位文案 */
var Q = {
f01: ['怀孕之后,家里的唠叨变多了吗?', '真的变多了', '还好,能接受'],
f02: ['长辈按老经验养胎,你会怎么回?', '笑笑不接话', '直接讲清楚'],
f05: ['被“关心”到喘不过气,你会说出来吗?', '会委婉说', '忍一忍算了'],
m01: ['怀孕后,家里的分工变了吗?', '他做得更多了', '基本没变'],
m06: ['孕期更想要礼物,还是被看见?', '被看见更重要', '礼物也要有'],
m10: ['他懂你养胎其实很累吗?', '他挺懂的', '还差得远'],
w01: ['孕期上班,不舒服你会直接说吗?', '会直接说', '能忍就忍'],
w02: ['产检请假,你会提前心里预演吗?', '每次都预演', '直接请就好'],
w10: ['上班孕妈的累,同事看得见吗?', '大多看得见', '基本看不见'],
b01: ['孕期的难受,你会跟别人讲吗?', '会讲出来', '自己消化'],
b03: ['育儿内容,越看越心慌吗?', '是的,少看了', '看了更安心'],
b08: ['偶尔害怕生孩子,你也有过吗?', '我也有过', '还好不怕']
};
var DAY = Math.floor((Date.now() + 8 * 3600e3) / 864e5);
var DATE = new Date(DAY * 864e5).toISOString().slice(0, 10);
var hot = T.filter(function (t) { return t.hot && Q[t.id]; });
var qt = hot[DAY % hot.length], q = Q[qt.id];
var seed = hash(qt.id + DATE), pctA = 38 + seed % 27; // 占位比例 38%~64%
var voters = 1200 + seed % 900; // 占位表态人数
var KEY = 'gcv5_vote';
var vote = null;
try { var sv = JSON.parse(localStorage.getItem(KEY) || 'null'); if (sv && sv.d === DATE && sv.t === qt.id) vote = sv.v; } catch (e) {}
var avs = [0, 1, 2, 3].map(function (k) { return MOMS[(seed + k * 7) % MOMS.length]; });
function pick(cat) {
if (cat) { var l = T.filter(function (t) { return t.cat === cat && t.ph; }); return l.filter(function (t) { return t.hot; }).concat(l.filter(function (t) { return !t.hot; })); }
var by = CATS.map(function (c) { return T.filter(function (t) { return t.cat === c && t.hot && t.ph; }); }), out = [];
for (var r = 0; r < 10; r++) by.forEach(function (l) { if (l[r]) out.push(l[r]); });
return out;
}
function resultHTML() {
var a = pctA + (vote === 0 ? 1 : 0), b = 100 - a;
return '<div class="q5-res' + (vote === 0 ? ' pa' : ' pb') + '">' +
'<div class="q5-lab"><span class="la">' + (vote === 0 ? '<i>✓</i>' : '') + esc(q[1]) + ' <b>' + a + '%</b></span>' +
'<span class="lb"><b>' + b + '%</b> ' + esc(q[2]) + (vote === 1 ? '<i>✓</i>' : '') + '</span></div>' +
'<div class="q5-bar"><span class="ba" style="--w:' + a + '%"></span><span class="bb"></span></div>' +
'<button type="button" class="q5-see" data-t="' + esc(qt.id) + '">看看 ' + num(voters + 1) + ' 位妈妈怎么说 <i>›</i></button></div>';
}
function actHTML() {
if (vote != null) return resultHTML();
return '<div class="q5-btns"><button type="button" class="q5-v a" data-v="0">' + esc(q[1]) + '</button>' +
'<button type="button" class="q5-v b" data-v="1">' + esc(q[2]) + '</button></div>';
}
var mo = new Date(DAY * 864e5), dlab = (mo.getUTCMonth() + 1) + '月' + mo.getUTCDate() + '日';
sec.innerHTML =
'<div class="g5-head"><h2 class="g5-title"><span>孕妈广场</span></h2><small class="g5-tag">效果稿 V5</small>' +
'<button type="button" class="g5-more" data-t="">去广场 <i>›</i></button></div>' +
'<div class="q5" id="q5">' +
'<div class="q5-top"><span class="q5-k"><i></i>今日广场一问</span><span class="q5-d">' + dlab + ' · ' + CAT_CN[qt.cat] + '</span></div>' +
'<p class="q5-q">' + esc(q[0]) + '</p>' +
'<div class="q5-act" id="q5Act">' + actHTML() + '</div>' +
'<div class="q5-who"><span class="q5-avs">' + avs.map(function (n) { return '<img src="' + ava(n) + '" alt="" loading="lazy">'; }).join('') + '</span>' +
'<span id="q5Cnt"><b>' + num(voters + (vote != null ? 1 : 0)) + '</b> 位妈妈已表态</span></div>' +
'</div>' +
'<div class="g5-cat" role="tablist" aria-label="话题分类"><button type="button" class="on" data-cat="">全部</button><button type="button" data-cat="family">家庭婚姻</button><button type="button" data-cat="work">职场</button><button type="button" data-cat="baby">经验</button></div>' +
'<div class="g5-row" id="g5Row"></div>';
sec.classList.add('gv5');
sec.classList.remove('hide');
var row = document.getElementById('g5Row');
function paint(cat) {
row.innerHTML = pick(cat).map(function (t) {
return '<button type="button" class="g5-c" data-t="' + esc(t.id) + '" style="--ink:' + t.ink + ';--c1:' + t.c[0] + '">' +
'<span class="g5-p"><img src="' + esc(t.ph) + '" alt="" loading="lazy">' + (cat ? '' : '<em>' + CAT_CN[t.cat] + '</em>') + (t.hot && cat ? '<em class="h">热</em>' : '') + '</span>' +
'<span class="g5-n">' + esc(t.name) + '</span>' +
'<span class="g5-m"><i></i>' + kfmt(t.talk) + ' 在聊</span></button>';
}).join('') +
'<button type="button" class="g5-c g5-sub" data-t=""><span class="g5-s1">你也来说说</span><span class="g5-s2">被选中得</span>' +
'<span class="g5-s3"><b>¥30</b><span>+500兜豆</span></span><span class="g5-s4">去投稿 ›</span></button>';
row.scrollLeft = 0;
}
paint('');
sec.addEventListener('click', function (e) {
var c = e.target.closest('[data-cat]');
if (c && sec.contains(c)) {
[].forEach.call(sec.querySelectorAll('.g5-cat button'), function (b) { b.classList.toggle('on', b === c); });
paint(c.getAttribute('data-cat'));
return;
}
var v = e.target.closest('.q5-v');
if (v) {
vote = +v.getAttribute('data-v');
try { localStorage.setItem(KEY, JSON.stringify({ d: DATE, t: qt.id, v: vote })); } catch (er) {}
var act = document.getElementById('q5Act');
act.innerHTML = resultHTML();
act.firstElementChild.classList.add('in');
requestAnimationFrame(function () { requestAnimationFrame(function () { act.firstElementChild.classList.remove('in'); }); });
document.getElementById('q5Cnt').innerHTML = '<b>' + num(voters + 1) + '</b> 位妈妈已表态';
return;
}
var t = e.target.closest('[data-t]');
if (t && sec.contains(t)) go(t.getAttribute('data-t'));
});
})();

BIN
demo/gch/v6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
guangchang/av/a000.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
guangchang/av/a001.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
guangchang/av/a002.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
guangchang/av/a003.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
guangchang/av/a004.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
guangchang/av/a005.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
guangchang/av/a006.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

BIN
guangchang/av/a007.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
guangchang/av/a008.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
guangchang/av/a009.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
guangchang/av/a010.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
guangchang/av/a011.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a012.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
guangchang/av/a013.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
guangchang/av/a014.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
guangchang/av/a015.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
guangchang/av/a016.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
guangchang/av/a017.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
guangchang/av/a018.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
guangchang/av/a019.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
guangchang/av/a020.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a021.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a022.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
guangchang/av/a023.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
guangchang/av/a024.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
guangchang/av/a025.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
guangchang/av/a026.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
guangchang/av/a027.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
guangchang/av/a028.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a029.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
guangchang/av/a030.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
guangchang/av/a031.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
guangchang/av/a032.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a033.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
guangchang/av/a034.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
guangchang/av/a035.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a036.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
guangchang/av/a037.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
guangchang/av/a038.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
guangchang/av/a039.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
guangchang/av/a040.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
guangchang/av/a041.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
guangchang/av/a042.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
guangchang/av/a043.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
guangchang/av/a044.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
guangchang/av/a045.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
guangchang/av/a046.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
guangchang/av/a047.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
guangchang/av/a048.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
guangchang/av/a049.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
guangchang/av/a050.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
guangchang/av/a051.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
guangchang/av/a052.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
guangchang/av/a053.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
guangchang/av/a054.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
guangchang/av/a055.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
guangchang/av/a056.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
guangchang/av/a057.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
guangchang/av/a058.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
guangchang/av/a059.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
guangchang/av/a060.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
guangchang/av/a061.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
guangchang/av/a062.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Some files were not shown because too many files have changed in this diff Show More