2548 lines
210 KiB
HTML
2548 lines
210 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">
|
||
<meta name="theme-color" content="#F4593C">
|
||
<meta name="mobile-web-app-capable" content="yes">
|
||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||
<title>兜爸心选 · 孕育陪伴</title>
|
||
<!-- V:26110127 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||
<link rel="stylesheet" href="mama-box.css">
|
||
<link rel="stylesheet" href="night.css">
|
||
<!-- 夜晚模式:首屏绘制前就按上次的选择加 class,避免先白后黑闪一下(开关在首页右上角 #nightBtn,逻辑见 app.js) -->
|
||
<script>try{if(localStorage.getItem('mmbox.night.v1')==='1'){document.documentElement.classList.add('night');document.querySelector('meta[name=theme-color]').content='#2A2340'}}catch(e){}</script>
|
||
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||
<!-- 共享助手:授权/跳商城/位置上报(分享卡片同步,见 docs/h5-auth-standard.md 第四节) -->
|
||
<script src="/common/wx-auth.js?v=26102601"></script>
|
||
</head>
|
||
<body>
|
||
<a class="skip" href="#screens">跳到内容</a>
|
||
<div class="phone" id="phone">
|
||
<!-- 身份未就绪提示(2026-09-20 新增)
|
||
⚠️ 数据源是「宿主有没有把 openid 注入进来」,由 app.js 的 showIdNotice()/hideIdNotice() 控制。
|
||
背景:小程序首页壳在拿不到 openid 时会**匿名加载**本页(见 js/app.js 的访客态分支),
|
||
此时页面看着能用、其实全是占位(孕周 `--`、查不到任何档案)。以前是静默的,
|
||
用户/测试者看不出异常 —— 从商城返回首页加载本页时尤其容易被误判成「数据丢了」。
|
||
所以这里给一条**可见**的提示,并提供重试;排查时也能一眼看出是身份问题而不是数据问题。 -->
|
||
<div class="id-notice hide" id="idNotice" role="status">
|
||
<span class="idn-ico" aria-hidden="true">!</span>
|
||
<span class="idn-txt" id="idNoticeTxt">未获取到微信身份,页面数据可能不完整</span>
|
||
<button class="idn-retry" id="idNoticeRetry">重试</button>
|
||
</div>
|
||
<!-- 2026-10-02 底部导航「推荐版」:内容滑到导航下面时淡出,而不是被白条硬切 -->
|
||
<div class="tab-fade" aria-hidden="true"></div>
|
||
<nav class="tabbar" id="tabbar">
|
||
<button class="tab is-active" data-tab="home">
|
||
<span class="t-ico t-line"><svg class="t-svg" viewBox="0 0 24 24" aria-hidden="true"><path class="tf" d="M4 10.4 12 4l8 6.4V18a2.4 2.4 0 0 1-2.4 2.4H6.4A2.4 2.4 0 0 1 4 18z"/><text class="td t-dou" x="12" y="17.4" text-anchor="middle">兜</text></svg></span><span class="t-txt">首页</span>
|
||
</button>
|
||
<button class="tab" data-tab="archive">
|
||
<span class="t-ico t-line"><svg class="t-svg" viewBox="0 0 24 24" aria-hidden="true"><path class="tf" d="M8.3 20.4c-1.9 0-2.9-1.5-2.6-3.4l.5-3c.3-1.9 1.4-3 2.9-3 1.6 0 2.5 1.3 2.2 3.2l-.5 3.1c-.3 1.9-1.1 3.1-2.5 3.1z"/><path class="tf" d="M15.9 14.4c-1.4 0-2.2-1.2-2.5-3.1l-.5-3.1c-.3-1.9.6-3.2 2.2-3.2 1.5 0 2.6 1.1 2.9 3l.5 3c.3 1.9-.7 3.4-2.6 3.4z"/><circle class="td" cx="6.6" cy="8.4" r=".95"/><circle class="td" cx="8.6" cy="7.6" r=".85"/><circle class="td" cx="10.4" cy="8.3" r=".75"/><circle class="td" cx="13.6" cy="2.9" r=".8"/><circle class="td" cx="15.5" cy="2.3" r=".85"/><circle class="td" cx="17.5" cy="3" r=".95"/></svg></span><span class="t-txt">档案</span>
|
||
</button>
|
||
<button class="tab tab-fab" data-sheet="open">
|
||
<span class="fab"><img src="assets/img/69818ea975da.png" alt="" aria-hidden="true"><b class="fab-w" aria-hidden="true"><i>记</i><em>一下</em><s>!</s></b></span><span class="t-txt">记一下</span>
|
||
</button>
|
||
<button class="tab" id="tabLetter">
|
||
<!-- ⚠️ 2026-09-19(9.19 需求第 2 条):这枚 tab 从「兜爸心选」商城入口改回「宝宝来信」。
|
||
2026-09-20:内置来信屏(#screen-letter)及其全部功能代码已删除 ——
|
||
来信功能整体由第三方 H5 承接,这枚 tab 是进「宝宝来信」的入口,
|
||
落点 = **第三方「宝宝来信」H5**(mp.yizhezhe.com/laixin/)。
|
||
⚠️ 因此依旧**不挂 data-tab**:它不参与 go() 的 tab 高亮切换。
|
||
点了走 jumpApp()(同页 location.href + query 带 openid/unionid),
|
||
与其它 H5 应用(宫格、工具卡)完全一致 —— 见 app.js 的 #tabLetter 绑定。
|
||
⚠️ 红点 #tabBadge 也挂在这枚 tab 上,数据源是 laixin 的
|
||
/api/mp/public/laixin/unread,owner 只有 syncLaixinReminder() 一处
|
||
(第九批曾把红点挪到「首页」,现已挪回)。 -->
|
||
<span class="t-ico t-line"><svg class="t-svg" viewBox="0 0 24 24" aria-hidden="true"><rect class="tf" x="3.4" y="5.6" width="17.2" height="13" rx="2.6"/><path class="tl" d="M4 7.2l8 5.6 8-5.6"/><path class="td" d="M12 15.9s-2-1.2-2-2.5a1 1 0 0 1 2-.3 1 1 0 0 1 2 .3c0 1.3-2 2.5-2 2.5z"/></svg></span><span class="t-badge" id="tabBadge"></span><span class="t-txt">宝宝来信</span>
|
||
</button>
|
||
<button class="tab" data-tab="me">
|
||
<span class="t-ico t-line"><svg class="t-svg" viewBox="0 0 24 24" aria-hidden="true"><circle class="tf" cx="12" cy="8.6" r="3.9"/><path class="tf" d="M4.8 20.2c.6-3.7 3.5-5.9 7.2-5.9s6.6 2.2 7.2 5.9z"/></svg><img class="t-ava" id="tabAva" alt=""></span><span class="t-txt">我的</span>
|
||
</button></nav>
|
||
|
||
<main class="screens" id="screens">
|
||
|
||
<section class="screen is-active" id="screen-home" data-screen="home">
|
||
<div class="home-hero no-letter">
|
||
<!-- 2026-10-04 头图改版(用户:宝宝按孕周换形态、孕囊跟着宝宝大小变、去掉飘落的花瓣、加阳光和水波纹):
|
||
背景换成「去掉羊水囊的空背景」,羊水囊 + 宝宝整体都在 .hero-baby 里,按孕周 9 个阶段换图(js/hero-fx.js)。
|
||
每阶段一张会动的 GIF(本地程序化形变:呼吸、轻浮、小手、蹬脚;脸不动,所以永远闭眼闭嘴)+ 一张同帧静图打底,
|
||
静图先出、GIF 加载完再盖上。孕囊大小 = .hero-baby 的 --k,由 JS 按阶段写。
|
||
.hero-fx 是阳光光束 + 水波焦散的画布,叠在宝宝之上、文字之下。 -->
|
||
<!-- 2026-10-04 七版:#heroWater = 参考页(YANG-bak)的 WebGL 羊水 + 光束 + 呼吸暖光,在宝宝下面;孕囊图透明底叠在上面 -->
|
||
<canvas class="hero-water" id="heroWater" aria-hidden="true"></canvas>
|
||
<div class="hero-baby" id="heroBaby">
|
||
<img class="hero-kid hero-kid-still" id="heroStill" alt="" decoding="async">
|
||
<img class="hero-kid" id="heroKid" alt="" decoding="async">
|
||
</div>
|
||
<!-- 右上角原来有个消息圆钮,点开只弹「暂无新消息」——一个永远没有内容的入口,
|
||
还顶着一颗红点天天提示。整个删掉;这一排现在只剩左边的品牌字。
|
||
.hero-top 本身留着:它的 height:32 + margin-top:10 撑着下面整列的起点
|
||
(现在这一排里除了品牌字还并排放着 slogan,见下面那段注释)。 -->
|
||
<!-- slogan 从「品牌字底下另起两行」挪到了「品牌字右边、同一行」。
|
||
|
||
⚠️ 它现在是 .hero-top 的**孩子**,而 .hero-top 是四个页面共用的
|
||
display:flex + justify-content:space-between —— 第二个孩子会被
|
||
space-between 甩到最右边去。这里**不动父级的对齐方式**
|
||
(动了会连着挪「我的 / 档案」两页右上角的按钮组),
|
||
改用 .hero-slogan{margin-right:auto} 把富余空间吃掉,让它贴着品牌字排。
|
||
这跟 .hero-actions{margin-left:auto} 是同一个路子,全站一致。
|
||
|
||
⚠️ 一行 10 个字放得下,是**先把气泡挪下去**换来的,不是本来就放得下。
|
||
320 宽(本版支持的最窄屏,CSS 里 max-width:359px 那条断点为证)横向账:
|
||
左内边距 16 + 品牌字 4×21 + 4×.5 = 86 → 品牌字排到 x=102
|
||
slogan 起点 102 + margin-left 9 → x=111
|
||
slogan 宽 10×13 + 9×.3 = 132.7 → 排到 x≈243.7
|
||
橙区右内边距 15,可用到 x=305 → 还余 61px ✓
|
||
真正卡住的是纵向:slogan 的行盒是 y 18..34(13px 字塞在 16px 行高里,
|
||
居中于 y10..42 那一排),而气泡原来 top:26 —— 圆顶正好戳在字底下。
|
||
量过 hero-art.png 的 alpha 通道:这幅画是**实心整圆、边缘是硬的**,
|
||
α≥8 和 α≥220 量出来的左缘只差 1px,没有可以压上去的透明薄边。
|
||
所以只能把气泡整体下移到 top:40,给字底留 6px。
|
||
气泡一动,橙区那笔竖列账要连着重算 —— 已经算过,见 style.css 的 .home-hero。
|
||
改字号 / 加字 / 挪气泡之前,把上面两笔账都重算一遍。 -->
|
||
<div class="hero-top">
|
||
<!-- 2026-10-01 左上角文字换成正式 LOGO(用户提供的红字原稿)。头图是橙红底,红色原稿压上去会糊,
|
||
所以抠成白色透明 PNG(按红色浓度转 alpha,3x 高清),和旁边白字 slogan、宝宝插画同一套白色语言。 -->
|
||
<h1 class="hero-brand"><img class="hero-logo" src="assets/img/db2f99232b39.png" alt="兜爸心选" width="107" height="30"></h1>
|
||
<p class="hero-slogan">全家都爱用的孕育平台</p>
|
||
<!-- 2026-10-05 夜晚模式开关(用户:「做一个夜晚模式,右上角有个切换按钮」) -->
|
||
<div class="hero-actions">
|
||
<button class="icon-btn glass night-btn" id="nightBtn" aria-label="切换夜晚模式" aria-pressed="false">
|
||
<svg class="nb-moon" viewBox="0 0 24 24" width="18" height="18"><path d="M20.2 14.6A8.3 8.3 0 0 1 9.4 3.8a8.3 8.3 0 1 0 10.8 10.8Z"/></svg>
|
||
<svg class="nb-sun" viewBox="0 0 24 24" width="19" height="19"><circle cx="12" cy="12" r="4.3"/><g stroke="currentColor" stroke-width="1.9" stroke-linecap="round"><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.5 1.5M17.1 17.1l1.5 1.5M5.4 18.6l1.5-1.5M17.1 6.9l1.5-1.5"/></g></svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 2026-10-01 头部左侧改版(用户:「LOGO 下边、小孩左边那块太单一,好好设计一下」)。
|
||
原来是「孕周圆环 + 一张天数玻璃卡」,信息只有两条、形状又都是圆/方块。现在四层,从情绪到数据:
|
||
① .hi-due 见面倒计时(2026-10-04 用户要求去掉前面的白色小心)—— 最有期待感的一句放最上面
|
||
② .hi-week 超大孕周数字「31 周 +6天」—— 主角,替代圆环
|
||
③ .hi-bar 孕程进度条,进度头上骑着「本周水果」(宝宝大小),右边写「像菠萝」
|
||
④ .hd-card 原来的玻璃卡,「小名在妈妈肚子里 / 已经生活了 N 天」原样保留
|
||
竖向账(橙区 250 不变):hero-top 止于 42 → ①顶 54 高 22 → ②顶 82 高 50 → ③顶 140 高 16 → ④顶 166 高 52 → 底 218,
|
||
离「宝宝来信」卡顶 234 留 16px(和旧版一样)。宽度不超过 x≈197(旧玻璃卡的右缘),不伸进宝宝插画。
|
||
JS 只认 id:heroLeft / heroWeek / heroWeekU / heroPlus / heroBar / heroFruit / heroSize / heroWho / heroDays。 -->
|
||
<div class="hero-pane">
|
||
<span class="hi-due" id="heroDue"><span id="heroDueT">距离见面还有 <b id="heroLeft">--</b> 天</span></span>
|
||
<div class="hi-week"><b id="heroWeek">--</b><span class="hi-unit"><em id="heroWeekU">周</em><span id="heroPlus"></span></span></div>
|
||
<div class="hi-prog">
|
||
<div class="hi-bar"><i class="hi-fill" id="heroBar"><span class="hi-knob" id="heroFruit" aria-hidden="true"></span></i></div>
|
||
<span class="hi-size" id="heroSize"></span>
|
||
</div>
|
||
<div class="hd-card">
|
||
<span class="hd-who">
|
||
<b id="heroWho">宝宝</b><span class="hd-where">在妈妈肚子里</span>
|
||
</span>
|
||
<span class="hd-tail">已经生活了 <b id="heroDays">--</b> 天</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 宝宝来信提醒卡。**数据源是 laixin(第三方「宝宝来信」应用)**,
|
||
由 js 里的 syncLaixinReminder()(拉数)→ renderLetterReminder()(渲染)唯一负责显隐与文案
|
||
(拉 /api/mp/public/laixin/unread;**未建档一律不提示**,建档后 unread > 0 才显示,
|
||
卡与底 tab 红点由同一次判定同时落 —— 2026-09-22 产品口径)。
|
||
点击 = 跳 laixin,与底 tab「宝宝来信」同落点(app.js 里绑的是 openLetterApp)。
|
||
|
||
⚠️ 2026-09-20:这张卡**默认就是收起的**(标记里直接带 .hide,
|
||
#homeBody 直接带 .no-letter)。卡的显隐要等未读接口回来才知道,
|
||
而首屏渲染远早于它 —— 默认显示的话会「先冒出一张假卡、数据回来再缩回去」
|
||
(商城↔首页来回切时特别明显)。
|
||
⚠️ 别把这里的 .hide / .no-letter 去掉,去掉就退回闪烁版。
|
||
⚠️ 这张卡 2026-09-20 之前读的是 box_app 自己的 /mama-box/letters(多数用户 0 封),
|
||
而底 tab 早已跳 laixin —— 两套数据导致「红点说有新信、卡里什么都没有」。
|
||
改数据源就是修这个,**别再把它接回本地信件数据**(内置来信屏已整体删除,这张卡只认 laixin)。 -->
|
||
<button class="letter-card ripple hide" id="homeLetter">
|
||
<span class="lc-envwrap"><svg class="lc-env lc-env-v" viewBox="0 0 64 48" aria-hidden="true"><rect x="2" y="4" width="60" height="42" rx="7" fill="#fff"/><path d="M4 9l28 20L60 9" fill="none" stroke="#F7C6D1" stroke-width="2.4" stroke-linejoin="round"/><path d="M4 44l20-17M60 44L40 27" stroke="#FBE1E7" stroke-width="2"/><circle cx="32" cy="29" r="8.5" fill="#E2456A"/><path d="M32 33.2c-2.6-1.6-4-3-4-4.4a2 2 0 0 1 4-.7 2 2 0 0 1 4 .7c0 1.4-1.4 2.8-4 4.4z" fill="#fff"/></svg><b class="lc-num" id="lcNum" aria-hidden="true"></b></span>
|
||
<span class="lc-stamp" aria-hidden="true"><i>♥</i></span>
|
||
<div class="lc-body">
|
||
<!-- ⚠️ 这段只是**兜底**(正常情况下用户看不到:卡默认 .hide,
|
||
有未读时由 renderLetterReminder() 改写成「宝宝来信」+ 通用提醒文案)。
|
||
改这几行时连着那边一起看,否则会出现「HTML 里写着一套、屏幕上是另一套」。
|
||
⚠️ 上一批这里短暂叫过「宝宝的新消息」,本批随整条线退回「来信」。 -->
|
||
<div class="lc-title" id="lcTitle">宝宝来信</div>
|
||
<div class="lc-desc" id="lcDesc">妈妈,今天我在你肚子里翻了个身……</div>
|
||
<div class="lc-link"><span id="lcLink">读读宝宝的话</span> <i>›</i></div>
|
||
</div>
|
||
<span class="lc-arrow" aria-hidden="true"><svg viewBox="0 0 24 24" width="16" height="16"><path d="M9 5l7 7-7 7" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
|
||
</button>
|
||
|
||
<!-- 来信卡收起来时由 hideLetterCard() / renderLetterReminder() 给 #homeBody 挂 .no-letter,
|
||
把下面第一块(.tool-dock)的上间距补回来。
|
||
⚠️ 2026-09-20:它**默认就带 .no-letter**(与 #homeLetter 默认带 .hide 配套,
|
||
首屏按「没有来信卡」排版,避免数据回来时布局跳一下)。
|
||
|
||
── 这一版首页正文换了骨架 ──
|
||
上一版是同一套「竖色条标题 + 灰色说明 + 一块内容」原样重复四遍
|
||
(工具 / AI 小结 / 脚印 / 指南),四处的字号、间距、列宽全一样,
|
||
只有色条颜色不同,往下扫就是「条-块-条-块-条-块-条-块」。
|
||
现在那套框架整个拆了:.sec-title / .sec-sub 在首页一处不留,
|
||
抬头改为长在各模块**内部**,四个模块收成三块,
|
||
靠三种完全不同的容器语言自己分段 ——
|
||
.tool-dock 通栏出血的浅米托盘
|
||
.today-line 没有容器,只有一条从早贯到晚的竖线
|
||
.shelf 横向可滑的书架卡带
|
||
页面也因此有了两种宽度节奏:文字型内容仍在 26px 栏内,
|
||
托盘和卡带出血到屏幕边缘。 -->
|
||
<div class="home-body no-letter" id="homeBody">
|
||
<!-- 模块一 · 工具托盘。
|
||
抬头进了托盘里面:标题独占一行,右端「所有工具」做成白底细边胶囊;
|
||
说明单独做成一枚浅色 chip,不再是标题底下一行贴边的灰字。
|
||
通往「记一下」弹层的门这一屏仍是两处,是故意的,不是漏删:
|
||
这颗胶囊是**导航**位(扫抬头找"看全部"时手先落在这儿),
|
||
宫格右下角那张 .mini-card.more 是**内容**位(顺带把第三列剩下的
|
||
44px 填平,而且是个够手指点的大靶子)。两个都指向 data-sheet="open",
|
||
删掉任意一个另一个都还走得通。 -->
|
||
<section class="tool-dock">
|
||
<!-- 大字水印。aria-hidden:读屏念到这块该直接进标题,
|
||
不该先听见两声「兜爸」。样式和理由都在 css/style.css 的 .wm 上。
|
||
2026-10-01 用户要求:水印字从「妈妈」改成品牌名「兜爸」。 -->
|
||
<span class="wm" aria-hidden="true">兜爸</span>
|
||
<!-- 2026-11-01 用户:「我的孕期数据和上面那个工具结合在一起时,是一个模块……上面所有的工具,用户可以去选择放哪一个,放到什么位置上」
|
||
同日二改(用户看过预览):数据卡和编辑完全解耦 ——
|
||
① #vitals 数据卡:只看「用过哪个记录类工具」(胎动 / 体重 / 血压 / 血糖 / 宫缩 / 估重),有真实记录就出,最近记录的排前;
|
||
最多直接露 4 张,多的折叠在「展开全部 N 项数据」里;一条真实记录都没有时出 胎动 / 体重 / 血压 / 血糖 4 张示例数卡(不写「示例」)。
|
||
访客 / 产后不出。逻辑在 app.js renderVitals。
|
||
② #htGrid 图标宫格:完全由「编辑」决定显示哪些、什么顺序,最多 8 个(4×2),记录类工具也以图标出现,胶囊里放简短状态。
|
||
「全部工具」不占格子,挪到标题右侧「全部 ›」,与「编辑」并排。编辑弹层 #htSheet(app.js htEditor),存 localStorage mmbox.homeTools.v1。
|
||
没自定义过 = 默认 8 个 + 孕周没到换替补;自定义后以用户为准,没到孕周的显示「孕N周开放」、点了弹原提示。
|
||
各 id(#kickTodayHome / #weightVal / #calNext / #vtK…)和 data-mini / data-vt 照旧,接口回填、示例数、跳转都沿用。 -->
|
||
<div class="dock-head">
|
||
<h2 class="dock-title" id="dockTitle">我的孕期工具</h2>
|
||
<button class="ht-all" type="button" data-sheet="open" hidden style="display:none">全部<span aria-hidden="true"> ›</span></button>
|
||
<button class="ht-edit" id="htEdit" type="button" aria-label="编辑首页工具"><svg viewBox="0 0 24 24" width="13" height="13" aria-hidden="true"><path d="M4 20h4L19 9l-4-4L4 16z" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linejoin="round"/><path d="M13.5 6.5l4 4" stroke="currentColor" stroke-width="2.2"/></svg>编辑</button>
|
||
</div>
|
||
<!-- 图标:App 表里各应用的正式 logo(app.js applyToolLogos),「全部工具」没有应用 logo,保留渐变底白图形。
|
||
data-tool = App 表 identifier(排序 / 显隐按它认);不是 data-mini 的普通应用格由 JS 按需生成(.tg-app)。 -->
|
||
<div class="tg-grid" id="htGrid">
|
||
<button class="tg kick ripple" data-mini="kick" data-tool="taidong">
|
||
<i class="tg-ic lg"><img src="/taidong/logo/logo-foot.svg" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">数胎动</span>
|
||
<!-- 默认中性占位,不写演示数字(真实值由卡片接口写入) -->
|
||
<span class="tg-s">今天 <b id="kickTodayHome">--</b> 次</span>
|
||
</button>
|
||
<button class="tg weight ripple" data-mini="weight" data-tool="yunqitizhong">
|
||
<i class="tg-ic lg"><img src="/upload/picture/a6d7e61edee2ff0395cf00587a7c4036.svg" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">孕期体重</span>
|
||
<span class="tg-s" id="weightVal">记一笔</span>
|
||
</button>
|
||
<button class="tg cal ripple" data-mini="cal" data-tool="chanjianrili">
|
||
<i class="tg-ic lg"><img src="/chanjian-rili/logo/logo-7-dots.svg" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">孕检日历</span>
|
||
<span class="tg-s" id="calNext">—</span>
|
||
</button>
|
||
<button class="tg fweight ripple" data-mini="fweight" data-tool="taierguzhong">
|
||
<i class="tg-ic lg"><img src="/upload/picture/715333a69fb67d8812ab093f342fa00f.png" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">胎儿估重</span>
|
||
<span class="tg-s">去测算</span>
|
||
</button>
|
||
<button class="tg curve ripple" data-mini="curve" data-tool="gongsuopinlv">
|
||
<i class="tg-ic lg"><img src="/upload/picture/1c02d720e4d23b09c996e859703b8b5e.svg" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">数宫缩</span>
|
||
<span class="tg-s" data-wk="cn">—</span>
|
||
</button>
|
||
<button class="tg bp ripple" data-mini="bp" data-tool="yun">
|
||
<i class="tg-ic lg"><img src="/upload/picture/816227e3933211145bb8fc774ee32e82.svg" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">孕期血压</span>
|
||
<span class="tg-s">量一量</span>
|
||
</button>
|
||
<button class="tg glu ripple" data-mini="glu" data-tool="yunqixuetang">
|
||
<i class="tg-ic lg"><img src="/upload/picture/fde3c920fae453f2642731e4135b88f5.png" alt="" aria-hidden="true"></i>
|
||
<span class="tg-n">孕期血糖</span>
|
||
<span class="tg-s">记一笔</span>
|
||
</button>
|
||
</div>
|
||
<!-- 2026-11-01 用户:「孕期工具」和「记录」调换,工具宫格放上面,记录数据卡(连同那行说明)放到宫格下面 -->
|
||
<p class="dock-note"><svg viewBox="0 0 24 24" width="11" height="11" aria-hidden="true"><path d="M11 2.6l1.9 5.2 5.2 1.9-5.2 1.9L11 16.8l-1.9-5.2L3.9 9.7l5.2-1.9L11 2.6z" fill="currentColor"/><path d="M18.4 14.6l.8 2.1 2.2.8-2.2.8-.8 2.1-.8-2.1-2.2-.8 2.2-.8.8-2.1z" fill="currentColor" opacity=".6"/></svg>妈妈每记录一次,宝宝就多一段成长记忆</p>
|
||
<div class="vt" id="vitals">
|
||
<button type="button" class="vt-it vt-k ripple" data-vt="kick" data-tool="taidong">
|
||
<span class="vt-top"><i class="vt-ic"><img src="/taidong/logo/logo-foot.svg" alt="" aria-hidden="true"></i><span class="vt-l">数胎动</span></span>
|
||
<span class="vt-v"><b id="vtK">--</b><small class="vt-u">次</small></span>
|
||
<span class="vt-f"><span class="vt-s" id="vtKs">去数一数 ›</span><span class="vt-d" id="vtKd"></span></span>
|
||
</button>
|
||
<button type="button" class="vt-it vt-w ripple" data-vt="weight" data-tool="yunqitizhong">
|
||
<span class="vt-top"><i class="vt-ic"><img src="/upload/picture/a6d7e61edee2ff0395cf00587a7c4036.svg" alt="" aria-hidden="true"></i><span class="vt-l">孕期体重</span></span>
|
||
<span class="vt-v"><b id="vtW">--</b><small class="vt-u">kg</small></span>
|
||
<span class="vt-f"><span class="vt-s" id="vtWs">去记一笔 ›</span><span class="vt-d" id="vtWd"></span></span>
|
||
</button>
|
||
<button type="button" class="vt-it vt-p ripple" data-vt="bp" data-tool="yun">
|
||
<span class="vt-top"><i class="vt-ic"><img src="/upload/picture/816227e3933211145bb8fc774ee32e82.svg" alt="" aria-hidden="true"></i><span class="vt-l">孕期血压</span></span>
|
||
<span class="vt-v"><b id="vtP">--</b><small class="vt-u">mmHg</small></span>
|
||
<span class="vt-f"><span class="vt-s" id="vtPs">去记一笔 ›</span><span class="vt-d" id="vtPd"></span></span>
|
||
</button>
|
||
<button type="button" class="vt-it vt-g ripple" data-vt="glu" data-tool="yunqixuetang">
|
||
<span class="vt-top"><i class="vt-ic"><img src="/upload/picture/fde3c920fae453f2642731e4135b88f5.png" alt="" aria-hidden="true"></i><span class="vt-l">孕期血糖</span></span>
|
||
<span class="vt-v"><b id="vtG">--</b><small class="vt-u">mmol/L</small></span>
|
||
<span class="vt-f"><span class="vt-s" id="vtGs">去记一笔 ›</span><span class="vt-d" id="vtGd"></span></span>
|
||
</button>
|
||
<button type="button" class="vt-it vt-c ripple hide" data-vt="curve" data-tool="gongsuopinlv">
|
||
<span class="vt-top"><i class="vt-ic"><img src="/upload/picture/1c02d720e4d23b09c996e859703b8b5e.svg" alt="" aria-hidden="true"></i><span class="vt-l">数宫缩</span></span>
|
||
<span class="vt-v"><b id="vtC">--</b><small class="vt-u"></small></span>
|
||
<span class="vt-f"><span class="vt-s" id="vtCs">去记一笔 ›</span><span class="vt-d" id="vtCd"></span></span>
|
||
</button>
|
||
<button type="button" class="vt-it vt-e ripple hide" data-vt="fweight" data-tool="taierguzhong">
|
||
<span class="vt-top"><i class="vt-ic"><img src="/upload/picture/715333a69fb67d8812ab093f342fa00f.png" alt="" aria-hidden="true"></i><span class="vt-l">胎儿估重</span></span>
|
||
<span class="vt-v"><b id="vtE">--</b><small class="vt-u"></small></span>
|
||
<span class="vt-f"><span class="vt-s" id="vtEs">去测算 ›</span><span class="vt-d" id="vtEd"></span></span>
|
||
</button>
|
||
<button type="button" class="vt-more hide" id="vtMore" aria-expanded="false"></button>
|
||
</div>
|
||
<style>
|
||
/* —— 工具宫格(仿育儿首页) —— */
|
||
.tg-grid{display:grid;grid-template-columns:repeat(4,1fr);row-gap:16px;column-gap:4px;margin-top:14px}
|
||
.tg{position:relative;display:flex;flex-direction:column;align-items:center;gap:5px;min-width:0;padding:2px 0;border:0;background:none;font:inherit;color:inherit;overflow:visible}
|
||
.tg-ic{width:48px;height:48px;border-radius:15px;display:grid;place-items:center;box-shadow:0 6px 14px var(--tg-sh,rgba(230,110,80,.25)),inset 0 1px 0 rgba(255,255,255,.35);background:var(--tg-bg)}
|
||
.tg-ic img,.tg-ic svg{width:27px;height:27px;object-fit:contain}
|
||
/* 2026-10-31 用户:图标统一用正式上线的应用图标(App 表 logo,后台换了 JS 会跟着换;这里的 src 只是首屏占位) */
|
||
.tg-ic.lg{display:block;width:50px;height:50px;padding:0;background:none;box-shadow:none;border-radius:0}
|
||
.tg-ic.lg img{display:block;margin:0;position:static;width:100%;height:100%;object-fit:contain;filter:drop-shadow(0 5px 8px rgba(120,80,70,.18))}
|
||
.tg-n{font-size:13px;font-weight:600;color:#3B2A2A;white-space:nowrap}
|
||
/* 末尾「添加」格:虚线描边的浅底方块,比工具图标弱一档 */
|
||
.tg-add .tg-ic{box-sizing:border-box;width:50px;height:50px;border-radius:15px;background:#FFF7F3;border:1.5px dashed #F0B9A6;box-shadow:none;color:#E8735A}
|
||
.tg-add .tg-ic svg{width:22px;height:22px}
|
||
.tg-add .tg-n{color:#8A6F69}
|
||
.tg-add .tg-s{background:#FBEDE7;color:#C2674F}
|
||
.tg-s{max-width:100%;padding:1px 8px;border-radius:99px;font-size:11px;line-height:17px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:var(--tg-pl);color:var(--tg-tx)}
|
||
.tg-s b{font-weight:800}
|
||
.tg-s small{margin-left:1px;font-size:9.5px}
|
||
.tg.kick{--tg-bg:linear-gradient(150deg,#F7A072,#E9673F);--tg-pl:#FFEADF;--tg-tx:#D4552F;--tg-sh:rgba(233,103,63,.28)}
|
||
.tg.weight{--tg-bg:linear-gradient(150deg,#F79A92,#E5606A);--tg-pl:#FFE6E6;--tg-tx:#D24B57;--tg-sh:rgba(229,96,106,.28)}
|
||
.tg.cal{--tg-bg:linear-gradient(150deg,#9CC873,#68A043);--tg-pl:#E9F5DE;--tg-tx:#4E8A2C;--tg-sh:rgba(104,160,67,.28)}
|
||
.tg.fweight{--tg-bg:linear-gradient(150deg,#8FB0EA,#5B7FCC);--tg-pl:#E5EDFC;--tg-tx:#4568B8;--tg-sh:rgba(91,127,204,.28)}
|
||
.tg.curve{--tg-bg:linear-gradient(150deg,#B39BEA,#8366CC);--tg-pl:#EFE8FC;--tg-tx:#6F50BC;--tg-sh:rgba(131,102,204,.28)}
|
||
.tg.bp{--tg-bg:linear-gradient(150deg,#F58FB0,#DC5584);--tg-pl:#FDE6EE;--tg-tx:#C93F70;--tg-sh:rgba(220,85,132,.28)}
|
||
.tg.glu{--tg-bg:linear-gradient(150deg,#6FD0C2,#2FA192);--tg-pl:#DFF5F1;--tg-tx:#22887B;--tg-sh:rgba(47,161,146,.28)}
|
||
.tg.is-warn .tg-s{background:#FDE3E0;color:#D2453B}
|
||
html.night .tg-n{color:#F1E6EE}
|
||
html.night .tg-s{background:rgba(255,255,255,.1);color:#E9D6E2}
|
||
/* —— 2026-11-01 工具 + 数据合成一个模块:数据卡(2 列)在上、小图标宫格(4 列)在下,同一块白底里 —— */
|
||
.tg.hide,.vt-it.hide,.vt.hide{display:none}
|
||
.tg-n{max-width:100%;overflow:hidden;text-overflow:ellipsis}
|
||
.tg-app{--tg-pl:#F7EEE8;--tg-tx:#9A6450;--tg-bg:linear-gradient(150deg,#F2C17E,#E19A4C)}
|
||
/* 2026-11-01 用户:图标下的胶囊跟图标同色系 —— 普通应用按各自 logo 主色配 */
|
||
.tg-app[data-tool="yunqinengbuchi"]{--tg-pl:#E3F3E8;--tg-tx:#2E8550}
|
||
.tg-app[data-tool="daichanqingdan"]{--tg-pl:#FFEBDD;--tg-tx:#D9692A}
|
||
.tg-app[data-tool="bushui"]{--tg-pl:#DDF1F3;--tg-tx:#1F7F8C}
|
||
.tg-app[data-tool="yundujinian"]{--tg-pl:#E7E8EF;--tg-tx:#3A3F57}
|
||
.ht-all{margin-left:auto;flex:none;padding:4px 2px;border:0;background:none;font:inherit;font-size:12.5px;font-weight:600;color:#8E7773;white-space:nowrap}
|
||
.ht-all:active{opacity:.5}
|
||
.ht-edit{margin-left:auto;flex:none;white-space:nowrap;display:inline-flex;align-items:center;gap:4px;height:28px;padding:0 12px;border:1px solid #F1D9CF;border-radius:99px;background:#FFF6F2;font:inherit;font-size:12.5px;font-weight:700;color:#D9573A}
|
||
.ht-edit:active{opacity:.6}
|
||
.dock-head .dock-all{display:none}
|
||
/* 孕周没到(用户自己选了放在首页):图标淡一点 + 右上角「孕N周开放」,点了弹原提示 */
|
||
.tg.is-locked{overflow:visible}
|
||
.tg.is-locked .tg-ic{opacity:.5;filter:saturate(.6)}
|
||
.tg.is-locked .tg-n{color:#9A8380}
|
||
.tg.is-locked .tg-s{background:#F3EEEC;color:#9A8380}
|
||
.tg.is-locked::after{content:attr(data-lock);position:absolute;top:-8px;left:50%;margin-left:4px;padding:0 5px;border-radius:7px;background:#FDE7E1;color:#D9573A;font-size:9.5px;font-weight:800;line-height:15px;white-space:nowrap;box-shadow:0 0 0 2px #fff;pointer-events:none}
|
||
.tg-grid.has-locked{row-gap:20px;padding-top:6px}
|
||
/* 数据卡区:没有外框、没有标题,和宫格同一块白底;宫格前一条极细分隔,读起来是「数据 → 其余工具」 */
|
||
.vt{display:grid;grid-template-columns:repeat(2,1fr);gap:9px;margin-top:2px}
|
||
.tg-grid + .dock-note{display:flex;margin-top:16px;padding-top:14px;border-top:1px dashed #F1DED6}
|
||
.vt-it{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:3px;padding:11px 12px 10px;border-radius:16px;min-width:0;text-align:left;font:inherit;color:inherit;background:var(--vt-bg,#fff);border:0}
|
||
.vt-it.span2{grid-column:span 2}
|
||
.vt-top{display:flex;align-items:center;gap:6px;width:100%;min-width:0}
|
||
.vt-ic{flex:none;width:24px;height:24px;display:block}
|
||
.vt-ic img{display:block;width:100%;height:100%;object-fit:contain}
|
||
.vt-l{font-size:13px;color:#3B2A2A;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.vt-v{margin-top:3px;white-space:nowrap;display:flex;align-items:baseline;gap:3px}
|
||
.vt-v b{font-size:25px;line-height:1.1;font-weight:800;letter-spacing:-.5px;color:#2F2424;font-variant-numeric:tabular-nums}
|
||
.vt-u{font-size:11.5px;font-weight:600;color:#7A6663}
|
||
.vt-u:empty{display:none}
|
||
.vt-f{display:flex;align-items:center;gap:6px;width:100%;min-width:0}
|
||
.vt-s{flex:none;font-size:11px;line-height:1.4;padding:1px 8px;border-radius:99px;background:#fff;color:var(--vt-c);font-weight:700;white-space:nowrap}
|
||
.vt-s:empty{display:none}
|
||
.vt-it.empty:not(.demo) .vt-s{background:none;padding:1px 0;color:var(--vt-c)}
|
||
.vt-it.empty:not(.demo) .vt-v b{color:#CDBAB5}
|
||
.vt-s.ok{background:rgba(47,138,94,.12);color:#2F8A5E}
|
||
.vt-s.hi{background:rgba(210,69,59,.12);color:#D2453B}
|
||
.vt-s.lo{background:rgba(199,122,30,.14);color:#C77A1E}
|
||
.vt-d{font-size:11px;color:#6E5A57;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis}
|
||
.vt-d:empty{display:none}
|
||
/* 超过 4 项数据时的折叠开关(占满一行) */
|
||
.vt-more{grid-column:1/-1;display:flex;align-items:center;justify-content:center;gap:4px;height:32px;margin-top:-1px;border:0;border-radius:12px;background:#FBF4F1;font:inherit;font-size:12.5px;font-weight:700;color:#9A6450}
|
||
.vt-more.hide{display:none}
|
||
.vt-more svg{width:12px;height:12px;transition:transform .2s}
|
||
.vt-more[aria-expanded="true"] svg{transform:rotate(180deg)}
|
||
html.night .vt-more{background:rgba(255,255,255,.07);color:#E2C2B5}
|
||
/* 每格一层很淡的同色底(2026-10-31 用户:稍微加一点点背景色) */
|
||
.vt-k{--vt-c:#E9673F;--vt-bg:#FFF5F0}
|
||
.vt-w{--vt-c:#E5606A;--vt-bg:#FFF4F4}
|
||
.vt-p{--vt-c:#C94F8C;--vt-bg:#FDF3F8}
|
||
.vt-g{--vt-c:#22968A;--vt-bg:#F0FAF8}
|
||
.vt-c{--vt-c:#7A5BC8;--vt-bg:#F6F2FD}
|
||
.vt-e{--vt-c:#4E74C4;--vt-bg:#F1F5FD}
|
||
html.night .vt-it{background:rgba(255,255,255,.07);box-shadow:none}
|
||
html.night .vt-s{background:rgba(255,255,255,.1)}
|
||
html.night .vt-v b{color:#F3E8F0}
|
||
html.night .vt-l{color:#E2D2DC}
|
||
html.night .vt + .tg-grid{border-color:rgba(255,255,255,.1)}
|
||
|
||
/* 2026-11-01 用户:数据区去掉各工具彩色 logo;不要白底卡片(也不要每格一个颜色)。
|
||
数据 2×2:同一种很淡的暖色半透明底、圆角小块;图标区不加底,直接落在模块渐变上;两区之间只靠留白,不画线。 */
|
||
.vt{gap:8px;padding:0;background:none;border:0;border-radius:0;box-shadow:none;overflow:visible}
|
||
/* 11-01 用户:数胎动、孕期血压这些数据块底色再深一点 → 四块一起加深(仍同一种暖色,不每格一色) */
|
||
.vt-it{--vt-bg:rgba(255,218,203,.95);--vt-c:#C8664E;border-radius:14px;padding:11px 13px 10px}
|
||
.vt-ic{display:none}
|
||
.vt-l{font-size:12.5px;font-weight:600;color:#8A7470}
|
||
.vt-v b{font-size:24px;color:#2F2424}
|
||
/* 11-01 用户:记录数据的块有点大、占地方 → 收紧:内边距、数字字号、行距都小一档(高约 92→70px) */
|
||
.vt{gap:7px}
|
||
.vt-it{gap:1px;padding:8px 11px 8px;border-radius:12px}
|
||
.vt-l{font-size:12px}
|
||
.vt-v{margin-top:1px}
|
||
.vt-v b{font-size:20px;line-height:1.15}
|
||
.vt-u{font-size:11px}
|
||
.vt-s{font-size:10.5px;padding:0 7px}
|
||
.vt-d{font-size:10.5px}
|
||
.vt-more{height:28px}
|
||
.vt-s{background:rgba(255,255,255,.8);color:#8A6458}
|
||
.vt-more{border-radius:12px;background:rgba(255,218,203,.95);height:32px;margin-top:0}
|
||
html.night .vt-it,html.night .vt-more{background:rgba(255,255,255,.07)}
|
||
/* 11-01 用户:工具区背后的「兜爸」水印看不太清 → 加深一档,隐约能认出来但不抢卡片 */
|
||
.tool-dock .wm{color:#F5EBE3}
|
||
/* 11-01 用户选 A:工具在上,数据卡压成一行横滑小卡(高度省一半),左右滑看全部 */
|
||
.vt{display:flex;gap:8px;margin:0 -26px;padding:2px 26px 6px;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:none;scroll-snap-type:x proximity;scroll-padding:0 26px}
|
||
.vt::-webkit-scrollbar{display:none}
|
||
.vt::after{content:"";flex:none;width:18px}
|
||
.vt-it{flex:none;width:auto;min-width:112px;gap:0;padding:8px 11px 8px;border-radius:14px;scroll-snap-align:start}
|
||
.vt-l{font-size:11.5px}
|
||
.vt-v{margin-top:0}
|
||
.vt-v b{font-size:19px}
|
||
.vt-f{margin-top:2px}
|
||
.vt-d{display:none}
|
||
.vt-more{display:none!important}
|
||
/* 11-01 用户:数据块桃色底太深、有点丑,要「有一些玻璃质感」→ 改成半透明白玻璃:上亮下透的渐变 + 背景模糊 + 白描边高光 + 很淡的暖色投影;
|
||
桃色只留在状态小标签上(白玻璃上再用白胶囊会看不出来) */
|
||
.vt-it,.vt-more{background:linear-gradient(150deg,rgba(255,255,255,.78) 0%,rgba(255,255,255,.42) 100%);-webkit-backdrop-filter:blur(12px) saturate(150%);backdrop-filter:blur(12px) saturate(150%);border:1px solid rgba(255,255,255,.9);box-shadow:0 4px 14px rgba(200,110,86,.09),inset 0 1px 0 rgba(255,255,255,.95)}
|
||
.vt-s{background:rgba(255,226,214,.75);color:#B65E48}
|
||
.vt-more{color:#B65E48}
|
||
html.night .vt-it,html.night .vt-more{background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.1);box-shadow:none}
|
||
html.night .vt-s{background:rgba(255,255,255,.1)}
|
||
/* 2026-11-01 用户:整块背景有点单调 → 在原毛玻璃上叠一层很淡的暖色:右上一团淡粉、左下一团淡杏,底色微微偏桃色 */
|
||
#homeBody>section.tool-dock.tool-dock:not(.ny-peek):not(.game-promo){background:
|
||
linear-gradient(90deg,rgba(255,150,112,.28),rgba(255,150,112,0) 60%) top/100% 2px no-repeat,
|
||
radial-gradient(260px 170px at 100% 0,rgba(255,190,205,.30),rgba(255,190,205,0) 72%),
|
||
radial-gradient(280px 200px at 0 100%,rgba(255,210,170,.30),rgba(255,210,170,0) 72%),
|
||
radial-gradient(240px 110px at 0 0,rgba(255,150,112,.18),rgba(255,150,112,0) 72%),
|
||
linear-gradient(180deg,rgba(255,243,237,.78),rgba(255,248,244,.64))!important}
|
||
.vt + .tg-grid,.vt.hide + .tg-grid{margin-top:16px;padding-top:0;border:0;background:none;box-shadow:none}
|
||
html.night .vt{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.08)}
|
||
html.night .vt-it,html.night .vt-more{background:#2B2230}
|
||
html.night .ht-edit{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.12);color:#F3A58F}
|
||
html.night .tg.is-locked::after{box-shadow:none}
|
||
/* —— 编辑首页工具弹层(#htSheet),外观沿用「记一下」sheet —— */
|
||
.hts-scrim{z-index:100}
|
||
.hts{position:absolute;left:0;right:0;bottom:0;z-index:101;max-height:88%;display:flex;flex-direction:column;background:#FAF5F1;border-radius:28px 28px 0 0;transform:translateY(100%);transition:transform .38s cubic-bezier(.2,.8,.2,1);box-shadow:0 -10px 40px rgba(90,50,35,.2);overscroll-behavior:contain}
|
||
.hts.show{transform:none}
|
||
.hts:not(.show){box-shadow:none}
|
||
.hts-grip{padding:10px 0 2px;display:grid;place-items:center}
|
||
.hts-grip span{width:42px;height:5px;border-radius:3px;background:#DCD2CA}
|
||
.hts-head{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;padding:6px 20px 8px}
|
||
.hts-head h2{margin:0;font-size:21px;font-weight:800;color:#2F2424}
|
||
.hts-head p{margin:5px 0 0;font-size:12px;color:#8E7773}
|
||
.hts-scroll{flex:1;min-height:0;overflow-y:auto;overscroll-behavior-y:contain;padding:0 16px 10px}
|
||
.hts-scroll::-webkit-scrollbar{display:none}
|
||
.hts-sec{display:flex;align-items:baseline;gap:8px;margin:12px 4px 8px}
|
||
.hts-sec b{font-size:14.5px;color:#3B2A2A}
|
||
.hts-sec span{margin-left:auto;font-size:11.5px;color:#9A8380}
|
||
.hts-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
|
||
.hts-row{position:relative;display:flex;align-items:center;gap:8px;height:52px;padding:0 6px 0 8px;border-radius:14px;background:#fff;box-shadow:0 1px 3px rgba(150,100,80,.06);-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;touch-action:pan-y}
|
||
.hts-row.is-drag{z-index:2;box-shadow:0 10px 24px rgba(150,90,70,.22);transform-origin:center;transition:box-shadow .15s;background:#FFFDFB}
|
||
.hts-list.is-dragging .hts-row:not(.is-drag){transition:none}
|
||
.hts-rm{flex:none;width:24px;height:24px;border-radius:50%;border:0;background:#F25A4B;color:#fff;display:grid;place-items:center;padding:0}
|
||
.hts-rm svg{width:12px;height:12px}
|
||
.hts-ic{flex:none;width:32px;height:32px;object-fit:contain}
|
||
.hts-ic.ph{display:grid;place-items:center;border-radius:10px;background:#F2C17E;color:#fff;font-weight:800;font-size:14px}
|
||
.hts-n{flex:1;min-width:0;display:flex;align-items:center;gap:6px;font-size:14px;font-weight:600;color:#2F2424;white-space:nowrap}
|
||
.hts-n i{font-style:normal;overflow:hidden;text-overflow:ellipsis}
|
||
.hts-tag{flex:none;font-style:normal;padding:0 6px;border-radius:6px;font-size:10px;line-height:16px;font-weight:700;background:#FFEDE6;color:#E0573A}
|
||
.hts-tag.lk{background:#F3EEEC;color:#8E7773}
|
||
.hts-mv{flex:none;width:30px;height:30px;border:0;border-radius:9px;background:#F6F0EC;color:#8E6F65;display:grid;place-items:center;padding:0}
|
||
.hts-mv svg{width:14px;height:14px}
|
||
.hts-mv:disabled{opacity:.3}
|
||
.hts-hd{flex:none;width:30px;height:40px;display:grid;place-items:center;color:#C9B4AF;touch-action:none;cursor:grab}
|
||
.hts-hd svg{width:18px;height:18px}
|
||
.hts-more{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
|
||
.hts-add{position:relative;display:flex;flex-direction:column;align-items:center;gap:5px;padding:12px 2px 10px;border:0;border-radius:14px;background:#fff;font:inherit;color:#3B2A2A}
|
||
.hts-add img,.hts-add .hts-ic{width:34px;height:34px}
|
||
.hts-add span{max-width:100%;font-size:11.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
.hts-add b{position:absolute;top:5px;right:6px;width:18px;height:18px;border-radius:50%;background:#2FA36B;font-size:0;color:transparent}
|
||
.hts-add b::before,.hts-add b::after{content:"";position:absolute;left:50%;top:50%;width:10px;height:2px;margin:-1px 0 0 -5px;border-radius:1px;background:#fff}
|
||
.hts-add b::after{transform:rotate(90deg)}
|
||
.hts-add.is-full{opacity:.45}
|
||
.hts-empty{grid-column:1/-1;padding:14px 0;text-align:center;font-size:12.5px;color:#9A8380}
|
||
.hts-foot{display:flex;gap:10px;padding:10px 16px calc(12px + env(safe-area-inset-bottom));border-top:1px solid #F0E6E0}
|
||
.hts-reset{flex:none;display:flex;align-items:center;justify-content:center;padding:0 16px;height:44px;border:0;border-radius:22px;background:#F1E9E4;font:inherit;font-size:14px;font-weight:700;color:#7A6663}
|
||
.hts-done{flex:1;display:flex;align-items:center;justify-content:center;height:44px;border:0;border-radius:22px;background:linear-gradient(135deg,#F77B55,#EE5A3E);font:inherit;font-size:15px;font-weight:800;color:#fff;box-shadow:0 6px 14px rgba(238,90,62,.25)}
|
||
html.night .hts{background:#2F261E}
|
||
html.night .hts-head h2,html.night .hts-sec b,html.night .hts-n,html.night .hts-add{color:#F1E6EE}
|
||
html.night .hts-row,html.night .hts-add{background:rgba(255,255,255,.07);box-shadow:none}
|
||
html.night .hts-mv,html.night .hts-reset{background:rgba(255,255,255,.1);color:#E2D2DC}
|
||
html.night .hts-foot{border-color:rgba(255,255,255,.08)}
|
||
/* 2026-11-01 用户:「把此刻下面三行轮播改成两行轮播」→ 可见 2 行(app.js FEED_N=2),高度 30×2;
|
||
mama-box.css 里「新进一行淡入」按第 4 个子元素写死,两行时新进的是第 3 个,这里补上 */
|
||
.pl-feed.pl-feed3{height:60px}
|
||
.pl-feed3 .pl-track>.pl-row:nth-child(3):last-child{animation:plIn .55s var(--ease) both}
|
||
</style>
|
||
<!-- 此刻(2026-10-01 需求文档 v1.0 第二节;同日两次改版)。数据 GET /api/mp/public/mama-box/pulse,渲染在 app.js pulseCard()。
|
||
⚠️ 模拟数据是产品负责人 2026-10-01 拍板的例外(AGENTS.md §4.12),只限这一条。
|
||
用户 2026-10-01:「把此刻跟上面的孕育工具结合到一起……此刻相当于上面那个卡片的一个轻量化的展示」
|
||
→ 不再单独成卡,收进工具卡底部一条浅色带:一行人数 + 她们在做 / 和你比 + 今天别忘了 + 一行滚动动态。
|
||
「她们在聊」按用户要求删除;全站版(访客)的「今日三项」小卡也去掉(和上面工具宫格重复)。
|
||
show=false 或接口失败 → 整条保持 .hide,工具卡和以前一样。
|
||
同日三改(用户:「此刻有一点点不够清爽,文字太多了,密密麻麻的」):从 5 行减到 3 行 ——
|
||
① 标题行不变;② 「她们在做」两条进度条合成**一句**,只挑你今天还没做的那项(都做了就一句夸奖),去掉进度条;
|
||
③ 「今天别忘了」整行删(产检、盲盒在上面工具宫格和盲盒横幅里都有);④ 滚动动态去掉白底卡片,压成一行小字。 -->
|
||
<!-- 2026-10-02 陪伴版(用户:「改成陪伴的语气……头像展示 6 到 8 个……升级成同周妈妈的悄悄话……
|
||
不做复杂社区,只做一点陪伴」):
|
||
① 头像从标题行挪到第二行,一排 7 个,后面跟「今天 N 位同周妈妈陪宝宝数了胎动」——说人数不说百分比,不和你比;
|
||
② 「你今天还没数 ›」改成邀请:「小米粒在等你,陪它数一数 ›」,做过了就是「你今天也陪它数过啦 ✓」;
|
||
③ 同周悄悄话 #whWall:横滑的小纸条,只能「抱抱」不能评论,没有昵称头像。数据 GET /whisper(app.js whisperWall())。
|
||
拉到悄悄话时滚动动态 #plFeed 让位(一块地方只讲一件事),拉不到就还是滚动动态。 -->
|
||
<div class="pulse hide" id="pulse" role="region" aria-label="此刻,同孕周妈妈们">
|
||
<div class="pl-head">
|
||
<span class="pl-live"><i></i>此刻</span>
|
||
<span class="pl-title" id="plTitle"></span>
|
||
</div>
|
||
<div class="pp-crowd">
|
||
<span class="pp-avs" id="ppAvs" aria-hidden="true"></span>
|
||
<span class="pp-col">
|
||
<span class="pp-crowd-t" id="ppCrowd"></span>
|
||
<span class="pp-doing hide" id="ppDoing"></span>
|
||
</span>
|
||
</div>
|
||
<!-- 2026-10-02 用户:「此刻给我放 3 个使用应用记录」→ 动态从「一行滚动、有悄悄话就让位」改成常驻三行,
|
||
排在悄悄话入口上面;每 3 秒最上面一条淡出、底下补一条;点一行直接进对应工具(act → TODAY_GO)。 -->
|
||
<div class="pl-feed pl-feed3 hide" id="plFeed"><div class="pl-track" id="plTrack"></div></div>
|
||
<!-- 2026-10-02 二改(用户:「此刻有一点点乱……悄悄话点进去,前端一个很简洁、轻量化的入口,
|
||
点进去是整个悄悄话的大页面,设计炫酷一点、有创意、视觉有冲击力」):
|
||
首页只留一条入口(一句轮播的悄悄话 + 条数),横滑纸条带挪进全屏页 #whPage。 -->
|
||
<button class="wh-entry hide" id="whWall" type="button" aria-label="打开同孕周悄悄话">
|
||
<!-- 2026-10-02 用户:「入口那一小条里要有星空,星星一闪一闪,再划过几个流星,不要太多」 -->
|
||
<span class="we-sky" aria-hidden="true"><i class="tw" style="left:50%;top:12%;width:6px;height:6px;animation-delay:-1.2s;animation-duration:2.4s"></i><i style="left:60%;top:30%;width:4px;height:4px;animation-delay:-0.3s;animation-duration:2.0s"></i><i class="tw" style="left:73%;top:15%;width:5px;height:5px;animation-delay:-2.4s;animation-duration:2.8s"></i><i class="tw" style="left:93%;top:13%;width:4px;height:4px;animation-delay:-3.1s;animation-duration:2.2s"></i><i class="tw" style="left:21%;top:90%;width:4px;height:4px;animation-delay:-3.7s;animation-duration:2.6s"></i><i class="tw" style="left:45%;top:88%;width:5px;height:5px;animation-delay:-1.6s;animation-duration:3.2s"></i><i style="left:73%;top:80%;width:4px;height:4px;animation-delay:-2.2s;animation-duration:2.6s"></i><i class="tw" style="left:89%;top:88%;width:5px;height:5px;animation-delay:-0.8s;animation-duration:3.0s"></i><b class="we-mt"></b><b class="we-mt m2"></b></span>
|
||
<span class="we-ico" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M5 18.5V7.8A2.8 2.8 0 017.8 5h8.4A2.8 2.8 0 0119 7.8v5.4a2.8 2.8 0 01-2.8 2.8H9.2z" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round"/><path d="M9 10.5h6" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"/></svg></span>
|
||
<span class="we-txt"><b id="weName">孕妈悄悄话</b><span class="we-topic"><em>本周话题</em><strong id="weTopic"></strong></span><span class="we-roll" id="weRoll"></span></span>
|
||
<span class="we-go" id="weGo"></span>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 孕妈广场(2026-11-01 第一版,占位内容)。用户原话:「在这个模块下边加一个广场,放一些话题,有跟家庭里的,也有宝妈经验的……
|
||
展示的时候不要像下面『其他妈妈也在搜』那种列表形式,两个列表就乱了。点进去之后变成小红书那种瀑布流」。
|
||
→ 首页只放一排横滑的话题封面卡(不是列表):渐变色块 + 大水印字 + 话题名 + 篇数/在聊,热门带角标;
|
||
点卡进 guangchang/?t=话题id,点「去逛逛」进广场全部。话题表在 guangchang/topics.js(与广场页共用),渲染在 app.js initPlaza()。
|
||
⚠️ 篇数 / 在聊人数是占位数字(topics.js 注释),广场页底部写着「示例占位」。topics.js 没加载到 → 整块保持 .hide。 -->
|
||
<section class="gc-home hide" id="gcHome">
|
||
<div class="gch-head">
|
||
<h2 class="gch-title"><span>孕妈广场</span></h2>
|
||
<span class="gch-cat" id="gchCat" 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></span>
|
||
<button type="button" class="gch-more" id="gchMore">去逛逛<i aria-hidden="true">›</i></button>
|
||
</div>
|
||
<div class="gch-who"><span class="gch-avs" id="gchAvs" aria-hidden="true"></span><span id="gchCnt"></span></div>
|
||
<div class="gch-row gb" id="gchRow"></div>
|
||
<style>
|
||
#homeBody>section.gc-home{--gt:255,120,150}
|
||
.gc-home{margin:16px -26px 0;padding:16px 26px 16px;border-radius:26px;position:relative;z-index:0;background-color:#fff}
|
||
.gc-home.hide{display:none}
|
||
.gch-head{display:flex;align-items:center;gap:8px}
|
||
/* 11-01 第四版:四块分类(家庭/婚姻/职场/母婴)放不进标题行 → 分类单独占第二行,五段等宽 */
|
||
.gch-head{flex-wrap:wrap;row-gap:10px}
|
||
#gchCat{order:3;flex-basis:100%}
|
||
/* 11-01 用户:分类滑块里的字放在每段正中间 */
|
||
#gchCat button{flex:1;min-width:0;height:28px;padding:0 4px;display:flex;align-items:center;justify-content:center;text-align:center;font-size:13px;white-space:nowrap}
|
||
.gch-note{display:flex;align-items:center;gap:8px;width:100%;margin:10px 0 0;padding:9px 12px;border:0;border-radius:14px;background:#FFF1DE;font:inherit;font-size:13px;font-weight:800;color:#A86312;text-align:left}
|
||
.gch-note span{flex:1;min-width:0}
|
||
.gch-note i{flex:none;font-style:normal;font-size:12px;font-weight:800}
|
||
.gch-note.ok{background:linear-gradient(120deg,#FF8A5B,#F4593C);color:#fff;box-shadow:0 8px 16px -10px #F4593C}
|
||
.gch-title{flex:none;margin:0;font-size:21px;font-weight:900;letter-spacing:.5px;color:#2A1E1E}
|
||
.gch-title span{background:linear-gradient(transparent 58%,#FFD0DC 58%,#FFD0DC 92%,transparent 92%);padding:0 3px}
|
||
.gch-cat{display:flex;padding:2px;border-radius:99px;background:rgba(240,222,214,.7)}
|
||
.gch-cat button{height:22px;padding:0 8px;border:0;border-radius:99px;background:none;font:inherit;font-size:11.5px;font-weight:700;color:#9A7F78}
|
||
.gch-cat button.on{background:#fff;color:#D9466A;box-shadow:0 1px 4px rgba(190,110,120,.18)}
|
||
.gch-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:inherit;font-size:12px;font-weight:800;color:#fff;box-shadow:0 4px 10px rgba(242,98,126,.28)}
|
||
.gch-more i{font-style:normal;font-size:15px;line-height:1;padding:0 4px 1px 1px}
|
||
.gch-who{display:flex;align-items:center;gap:7px;margin:9px 0 0;font-size:12px;color:#8E7773}
|
||
.gch-who b{color:#D9466A;font-weight:800;font-variant-numeric:tabular-nums}
|
||
.gch-avs{display:flex}
|
||
.gch-avs img{width:20px;height:20px;border-radius:50%;object-fit:cover;border:1.5px solid #fff;margin-left:-6px;background:#FFE3D3}
|
||
.gch-avs img:first-child{margin-left:0}
|
||
.gch-row{display:flex;gap:10px;margin:12px -26px 0;padding:2px 26px 8px;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x proximity;scroll-padding:0 26px;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain}
|
||
.gch-row::-webkit-scrollbar{display:none}
|
||
.gch-row::after{content:"";flex:none;width:16px}
|
||
.gch-card{position:relative;flex:none;width:124px;height:152px;padding:12px 11px 10px;border:0;border-radius:18px;overflow:hidden;text-align:left;font:inherit;display:flex;flex-direction:column;scroll-snap-align:start;
|
||
background:linear-gradient(155deg,var(--c1),var(--c2));color:var(--ink);box-shadow:0 8px 16px -10px var(--ink),inset 0 1px 0 rgba(255,255,255,.7)}
|
||
.gch-card:active{transform:scale(.97)}
|
||
.gch-card .gk{align-self:flex-start;height:18px;padding:0 6px;border-radius:6px;background:rgba(255,255,255,.62);font-size:10px;font-weight:800;line-height:18px;letter-spacing:.5px}
|
||
.gch-card .gg{position:absolute;right:-8px;top:18px;font-size:72px;font-weight:900;line-height:1;color:#fff;opacity:.55;pointer-events:none;font-family:"STKaiti","KaiTi","Kaiti SC",serif}
|
||
.gch-card .gb{position:absolute;right:-26px;bottom:-30px;width:86px;height:86px;border-radius:50%;background:rgba(255,255,255,.28);pointer-events:none}
|
||
.gch-card .gn{position:relative;margin-top:auto;font-size:15px;font-weight:900;line-height:1.3;letter-spacing:.2px;color:#2F2424;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||
.gch-card .gm{position:relative;margin-top:5px;font-size:10.5px;font-weight:600;white-space:nowrap;opacity:.85}
|
||
.gch-card .gh{position:absolute;right:0;top:0;height:20px;padding:0 7px 0 8px;border-radius:0 18px 0 10px;background:linear-gradient(135deg,#FF7A45,#F4433C);color:#fff;font-size:10.5px;font-weight:800;line-height:20px;letter-spacing:.5px}
|
||
/* 照片卡:图铺满 + 下半截暗渐变托住白字 */
|
||
.gch-card.ph{background:#E9DDD6;color:#fff}
|
||
.gch-card.ph .gp{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
|
||
.gch-card.ph::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(0,0,0,0) 22%,rgba(30,16,16,.8) 100%);pointer-events:none}
|
||
.gch-card.ph .gk,.gch-card.ph .gn,.gch-card.ph .gm,.gch-card.ph .gh{z-index:1}
|
||
.gch-card.ph .gk{position:relative;background:rgba(255,255,255,.88);color:var(--ink)}
|
||
.gch-card.ph .gn{color:#fff;text-shadow:0 1px 3px rgba(0,0,0,.35)}
|
||
.gch-card.ph .gm{opacity:.92}
|
||
.gch-card.all{align-items:center;justify-content:center;gap:8px;text-align:center;--c1:#FFF6F2;--c2:#FFE9E1;--ink:#C9886F;border:1.5px dashed #F2C9BA;box-shadow:none}
|
||
.gch-card.all .ga{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;background:#fff;color:#E2553A;font-size:22px;font-weight:700;box-shadow:0 4px 10px rgba(226,85,58,.15)}
|
||
.gch-card.all b{font-size:13.5px;font-weight:800;color:#8A5A4C}
|
||
.gch-card.all small{font-size:11px;color:#B39184}
|
||
/* —— 11-01 第五版「广场地面」 —— */
|
||
.gch-row.gb{display:block;height:250px;margin:10px -26px 0;padding:0;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior-x:contain;scrollbar-width:none}
|
||
.gch-row.gb::after{display:none}
|
||
.gb-map{position:relative;height:250px;min-width:100%;width:max-content;display:flex;align-items:flex-start;gap:8px;padding:8px 26px 0;box-sizing:border-box;
|
||
background:radial-gradient(circle at 50% 50%,rgba(255,206,190,.22) 0 2px,transparent 2.5px) 0 0/22px 22px,linear-gradient(180deg,#FFF8F4 0%,#FFF1EA 100%)}
|
||
.gb-path{position:absolute;left:0;top:0;pointer-events:none}
|
||
.gb-path path{fill:none;stroke:#F6C9B8;stroke-width:2;stroke-dasharray:2 7;stroke-linecap:round}
|
||
.gb-w{position:absolute;width:18px;height:18px;border-radius:50%;object-fit:cover;border:2px solid #fff;box-shadow:0 2px 6px rgba(200,120,100,.25);opacity:.85;animation:gbWalk 6s ease-in-out infinite alternate}
|
||
.gb-w:nth-of-type(2n){animation-duration:7.5s;animation-direction:alternate-reverse}
|
||
@keyframes gbWalk{from{transform:translateX(-6px)}to{transform:translateX(8px)}}
|
||
.gb-col{position:relative;z-index:1;flex:none;width:128px;display:flex;flex-direction:column}
|
||
.gb-col.lo{padding-top:78px}
|
||
.gb-b{position:relative;display:block;width:128px;padding:0 0 26px;border:0;background:none;font:inherit;text-align:left;animation:gbBob 4.2s ease-in-out infinite;animation-delay:var(--d)}
|
||
@keyframes gbBob{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
|
||
.gb-b:active .gb-in{transform:scale(.96)}
|
||
.gb-in{position:relative;display:flex;flex-direction:column;gap:5px;padding:10px 11px 10px;border-radius:20px 20px 20px 6px;background:#fff;color:var(--ink);
|
||
box-shadow:0 10px 20px -12px var(--ink),0 0 0 1.5px var(--c2) inset;transition:transform .15s}
|
||
/* 气泡尾巴:左下角一个小三角,指向下面的头像 */
|
||
.gb-in::after{content:"";position:absolute;left:12px;bottom:-5px;width:10px;height:10px;background:inherit;background:#fff;transform:rotate(45deg);border-radius:0 0 3px 0;box-shadow:1.5px 1.5px 0 0 var(--c2)}
|
||
.gb-b:nth-child(odd) .gb-in{background:linear-gradient(150deg,#fff 40%,var(--c1))}
|
||
.gb-a{position:absolute;left:5px;bottom:-2px;width:24px;height:24px;border-radius:50%;object-fit:cover;border:2px solid #fff;box-shadow:0 3px 8px rgba(0,0,0,.12);background:#FFE3D3}
|
||
.gb-ph{display:block;width:calc(100% + 22px);height:60px;margin:-10px -11px 2px;border-radius:20px 20px 0 0;object-fit:cover}
|
||
.gb-k{display:flex;align-items:center;gap:4px;font-size:10px;font-weight:800;letter-spacing:.5px;opacity:.85}
|
||
.gb-k em{font-style:normal;height:15px;padding:0 5px;border-radius:5px;background:linear-gradient(135deg,#FF7A45,#F4433C);color:#fff;font-size:9.5px;line-height:15px}
|
||
.gb-n{font-size:13.5px;font-weight:900;line-height:1.38;color:#2F2424;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
||
.gb-b.ph .gb-n{-webkit-line-clamp:2}
|
||
.gb-m{display:flex;align-items:center;gap:5px;font-size:10.5px;font-weight:700;opacity:.8;white-space:nowrap}
|
||
.gb-m i{width:6px;height:6px;border-radius:50%;background:#2DBE6C;box-shadow:0 0 0 0 rgba(45,190,108,.5);animation:gbLive 1.8s ease-out infinite}
|
||
@keyframes gbLive{to{box-shadow:0 0 0 6px rgba(45,190,108,0)}}
|
||
.gb-end{justify-content:center;align-self:stretch;padding-right:26px}
|
||
.gb-all{width:112px;height:112px;margin:0 auto;border-radius:50%;border:1.5px dashed #F2B9A6;background:radial-gradient(circle at 35% 30%,#fff,#FFE9E0);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;font:inherit;color:#B9654E;box-shadow:0 10px 22px -14px #E2553A}
|
||
.gb-all b{font-size:26px;font-weight:900;line-height:1;color:#E2553A;font-family:"DIN Alternate","Helvetica Neue",Arial,sans-serif}
|
||
.gb-all span{font-size:11px;line-height:1.35;text-align:center}
|
||
.gb-all i{margin-top:3px;font-style:normal;font-size:11.5px;font-weight:800;color:#E2553A}
|
||
@media (prefers-reduced-motion:reduce){.gb-b,.gb-w,.gb-m i{animation:none}}
|
||
html.night .gb-map{background:radial-gradient(circle at 50% 50%,rgba(255,255,255,.06) 0 2px,transparent 2.5px) 0 0/22px 22px,transparent}
|
||
html.night .gb-path path{stroke:rgba(255,255,255,.18)}
|
||
/* 11-01 用户:「此刻 N 位孕 X 周妈妈和你同一周」保留但降低视觉权重,别和「今天 N 位妈妈陪宝宝数了胎动」两行数字同时抢注意力
|
||
→ 标题行改成一行浅灰小字的辅助信息(数字不再放大、不用品牌色),主信息让给下面那行 */
|
||
#pulse .pl-title{font-size:11.5px;font-weight:500;color:#A8928C;line-height:1.4}
|
||
#pulse .pl-title b{font-size:11.5px;font-weight:700;letter-spacing:0;color:#8E7773}
|
||
#pulse .pl-live{font-size:11px}
|
||
#pulse .pl-live::after{height:10px}
|
||
#pulse .pp-crowd{margin-top:7px}
|
||
#pulse .pp-crowd-t{font-size:13px;color:#5E4A47}
|
||
#pulse .pp-crowd-t b{font-size:15px;font-weight:900;color:#2F2424}
|
||
html.night #pulse .pl-title{color:#9C8A94}
|
||
html.night #pulse .pl-title b{color:#B9A6B1}
|
||
html.night .gch-title{color:#F1E6EE}
|
||
html.night .gch-cat{background:rgba(255,255,255,.08)}
|
||
</style>
|
||
</section>
|
||
|
||
<!-- 孕期小知识(2026-09-30)。用户原话:「按她填写的孕周,比如孕 20 周 5 天,给她列出几个小模块,
|
||
设计一定要漂亮、匹配母婴用户,最好是动态的;小知识匹配每周的每一天」。
|
||
内容:assets/data/preg-tips.json(孕 4–40 周,每周 宝宝/妈妈/饮食/注意 四句 + 每天一条小知识,共 7 条),
|
||
首次需要时才 fetch,不进首屏。渲染在 app.js renderTips()。
|
||
⚠️ 默认 .hide:只有拿到**真实孕周**(state.pregEmpty === false 且非产后)才显示,
|
||
内置默认孕周(DEFAULT_DUE 推出来的 27 周上下)是假的,不能拿它配知识。
|
||
⚠️ 一周 7 个圆点 = 这一周的第 1–7 天。今天及以前可以点开回看;以后的几天锁着,
|
||
写「明天见」—— 让每天回来看一条,而不是一口气翻完。 -->
|
||
<section class="preg-tips hide" id="pregTips">
|
||
<!-- 2026-10-31 用户定:「孕期小知识」首页这块改成「其他妈妈也在搜」(照用户给的参考图):
|
||
黄色荧光笔大标题 + 一排 10 个妈妈头像 + 参考图上那 6 个问题(固定,assets/data/qa/hot.json 前 6 条),
|
||
其余问题在「查看全部」进的 #detailQA 里。渲染在 app.js renderSearch()。 -->
|
||
<div class="ms-head">
|
||
<h2 class="ms-title"><span>其他妈妈也在搜</span></h2>
|
||
<!-- 2026-11-01 用户:「爆、热那些可以稍微再明显一些,这种火热的状态」→ 标题旁加「实时热搜」火苗标签 -->
|
||
<span class="ms-live" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12.6 2.5c.4 3-1.6 4.6-3 6.2C8 10.4 7 12 7 14.3A5 5 0 0012 19.5a5 5 0 005-5.2c0-2-1-3.6-1.9-4.6-.2 1.3-.9 2.2-1.9 2.6.6-3.4-.2-7-.6-9.8z" fill="currentColor"/></svg>实时热搜</span>
|
||
<span class="ms-wk" id="msWk"></span>
|
||
</div>
|
||
<div class="ms-who"><span class="ms-avs" id="msAvs" aria-hidden="true"></span><span class="ms-cnt" id="msCnt"></span></div>
|
||
<div class="ms-list" id="msList"></div>
|
||
<button type="button" class="ms-all ripple hide" id="msAll"></button>
|
||
<style>
|
||
.ms-head{display:flex;align-items:center;gap:8px}
|
||
.ms-title{margin:0;font-size:21px;font-weight:900;letter-spacing:.5px;color:#2A1E1E}
|
||
.ms-title span{background:linear-gradient(transparent 58%,#FFE066 58%,#FFE066 92%,transparent 92%);padding:0 3px}
|
||
.ms-wk{margin-left:auto;padding:2px 9px;border-radius:99px;background:#FFEDE6;color:#E0573A;font-size:11.5px;font-weight:700}
|
||
.ms-who{display:flex;align-items:center;gap:8px;margin:10px 0 4px}
|
||
.ms-avs{display:flex}
|
||
.ms-avs img{width:26px;height:26px;border-radius:50%;object-fit:cover;border:2px solid #fff;background:#FFE3D3;margin-left:-7px;box-shadow:0 2px 5px rgba(160,100,90,.15)}
|
||
.ms-avs img:first-child{margin-left:0}
|
||
.ms-cnt{font-size:12px;color:#9A8380}
|
||
.ms-list{display:flex;flex-direction:column}
|
||
.ms-it{display:flex;align-items:center;gap:10px;width:100%;padding:11px 2px;border:0;border-bottom:1px dashed #F1DDD6;background:none;font:inherit;color:inherit;text-align:left;text-decoration:none}
|
||
.ms-it:last-child{border-bottom:0}
|
||
.ms-no{flex:none;width:20px;font-size:16px;font-weight:900;font-style:italic;color:#C9B4AF;text-align:center}
|
||
/* 2026-11-01 前 3 名:实心火热色序号块,像热搜榜 */
|
||
.ms-it:nth-child(-n+3) .ms-no{height:20px;border-radius:6px;font-size:13px;font-style:normal;line-height:20px;color:#fff}
|
||
.ms-it:nth-child(1) .ms-no{background:linear-gradient(135deg,#FF6A3D,#EE2346)}
|
||
.ms-it:nth-child(2) .ms-no{background:linear-gradient(135deg,#FF8A3D,#F2553A)}
|
||
.ms-it:nth-child(3) .ms-no{background:linear-gradient(135deg,#FFB03D,#FF7A1A)}
|
||
.ms-m{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
|
||
.ms-q{min-width:0;font-size:15.5px;line-height:1.4;font-weight:600;color:#2F2424;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||
/* 热度行:火苗放大、数字加粗橙红(2026-11-01) */
|
||
.ms-h{display:flex;align-items:center;gap:3px;font-size:11.5px;color:#9A8380}
|
||
.ms-h svg{width:15px;height:15px;color:#FF5A36}
|
||
.ms-h b{font-weight:800;color:#F04A2E;font-variant-numeric:tabular-nums}
|
||
.ms-it:nth-child(-n+3) .ms-h svg{animation:msFlick 1.8s ease-in-out infinite;transform-origin:50% 90%}
|
||
/* 2026-11-01 热度更明显:爆 = 红橙渐变白字 + 小火苗 + 光泽扫过 + 轻呼吸;热 = 橙色实底白字;新 = 绿色不变 */
|
||
.ms-bd{flex:none;position:relative;overflow:hidden;display:inline-flex;align-items:center;justify-content:center;gap:1px;min-width:22px;padding:0 6px;border-radius:7px 7px 7px 2px;font-size:11.5px;line-height:19px;font-weight:900;text-align:center;background:#FF7A1A;color:#fff;box-shadow:0 2px 6px rgba(255,122,26,.3)}
|
||
.ms-bd svg{width:11px;height:11px;margin-left:-2px}
|
||
.ms-bd.bao{padding:0 7px 0 6px;background:linear-gradient(120deg,#FF9A3D 0%,#FF5A36 45%,#EE2346 100%);box-shadow:0 3px 10px rgba(238,35,70,.38);animation:msBreath 2.4s ease-in-out infinite}
|
||
.ms-bd.bao::after{content:"";position:absolute;top:0;bottom:0;left:-60%;width:45%;background:linear-gradient(100deg,transparent,rgba(255,255,255,.55),transparent);transform:skewX(-18deg);animation:msShine 2.8s ease-in-out infinite}
|
||
.ms-bd.new{background:#E6F5EC;color:#2F8A5E;box-shadow:none}
|
||
@keyframes msBreath{0%,100%{transform:scale(1)}50%{transform:scale(1.08)}}
|
||
@keyframes msShine{0%,55%{left:-60%}85%,100%{left:130%}}
|
||
.ms-live{display:inline-flex;align-items:center;gap:2px;padding:1px 7px 1px 5px;border-radius:99px;background:linear-gradient(120deg,#FF8A3D,#F2394A);color:#fff;font-size:11px;font-weight:800;line-height:17px;box-shadow:0 2px 6px rgba(242,57,74,.25)}
|
||
.ms-live svg{width:12px;height:12px;color:#FFE07A;animation:msFlick 1.6s ease-in-out infinite;transform-origin:50% 90%}
|
||
@keyframes msFlick{0%,100%{transform:scale(1) rotate(0)}30%{transform:scale(1.12) rotate(-6deg)}60%{transform:scale(.95) rotate(4deg)}}
|
||
@media (prefers-reduced-motion:reduce){.ms-bd.bao,.ms-bd.bao::after,.ms-live svg,.ms-it .ms-h svg{animation:none!important}.ms-bd.bao::after{display:none}}
|
||
html.night .ms-h b{color:#FF8A6A}
|
||
.ms-tag{flex:none;padding:0 6px;border-radius:6px;font-size:10.5px;line-height:17px;font-weight:700;background:#FFF1DC;color:#C77A1E}
|
||
.ms-tag.hot{background:#FFE4DE;color:#E8492F}
|
||
.ms-tag.new{background:#E6F5EC;color:#2F8A5E}
|
||
.ms-go{flex:none;font-style:normal;font-size:18px;color:#D9C2BC}
|
||
.ms-all{display:block;width:100%;text-align:center;margin:6px 0 2px;padding:10px;border:0;border-radius:14px;background:#FFF1EA;font:inherit;font-size:13.5px;font-weight:700;color:#E0573A}
|
||
.ms-all.hide{display:none}
|
||
html.night .ms-all{background:rgba(255,255,255,.07);color:#F3A58F}
|
||
html.night .ms-title{color:#F3E8F0}
|
||
html.night .ms-title span{background:linear-gradient(transparent 58%,rgba(255,214,90,.45) 58%,rgba(255,214,90,.45) 92%,transparent 92%)}
|
||
html.night .ms-q{color:#EFE3EA}
|
||
html.night .ms-it{border-color:rgba(255,255,255,.1)}
|
||
html.night .ms-avs img{border-color:#2A2231}
|
||
</style>
|
||
<p class="pt-foot">仅供参考,身体有任何不适请以医生意见为准</p>
|
||
</section>
|
||
|
||
<!-- 3D 婴儿房 · 「透过页面看到后面的房间」(2026-10-01 三版)。用户原话:
|
||
「把那个房间整体……铺到它的后边……两个模块中间,它不用点击,从外边其实就能看到这个里边是什么,
|
||
整个铺到这个背景的后边,有一个引导进入的按钮,我点进去再弹出这个新的页面」。
|
||
做法:这一块没有底色,是页面上开的一道「空隙」;房间图层(#nypLayer)由 JS 每次滚动都对齐到 .screen 的可视区,
|
||
所以页面往上滚时房间不跟着走,看起来就是铺在整页背后、从缝里露出来(视差)。上下两条内阴影 = 上下模块压在房间上面。
|
||
整块都能点(2026-10-02 用户要求:点到房子 / 模块任意位置都直接进 3D 婴儿房,不必非点「进去布置」);滑动页面不会触发 click,不怕误触。
|
||
图:assets/img/nursery-day.jpg / nursery-night.jpg,由「3D 婴儿房」会话(33d6c837)导出的无 UI 渲染
|
||
(原图 yef/cover-day.png、cover-night.png,1125×1500,**原尺寸**存 JPG —— 375 宽 × 3 倍屏正好 1125 像素,别再缩,缩到 750 在 iPhone 上会糊(2026-10-01 用户反馈过));里面摆的是演示布置,不是用户自己的房间。
|
||
底色必须和图边一致:白天 #DCE5EC、夜间 #2C3350(2026-10-01 写实版,取图顶两角;旧卡通版是 #FFECD8 / #5A5890),否则缝里会露出图片边框。
|
||
2026-10-01 晚:3D 婴儿房会话把封面换成「整栋小别墅外景」(婴儿房是二楼剖开那一间),房子占画面中部偏下、上方约 20% 纯底色。
|
||
缝高 300→340、图宽 100%→88%(max 420)、上提 40px:缝滚到屏幕中间时屋顶到草坪整栋都露出来,草坪压在玻璃条下面;标题改「我们的家」。
|
||
位置:2026-10-01 用户要求和消消乐对调 —— 后又和孕期小知识对调 —— 现在在孕期小知识下面、今天的动线上面(原来在今天的动线和书架之间)。北京时间 19:00–6:00 换夜间图(开灯版)。JS 在 app.js nurseryRender()。 -->
|
||
<section class="ny-peek" id="nursery">
|
||
<div class="nyp-layer" id="nypLayer" aria-hidden="true"><img id="nypImg" src="assets/img/nursery-day-sky.jpg?v=20261006a" alt="" decoding="async"></div>
|
||
<span class="nyp-chip" id="nyChip">进去看看 · 宝宝的婴儿房</span>
|
||
<div class="nyp-bar">
|
||
<div class="nyp-txt"><b id="nyTitle">我们的家</b><span id="nySub">做孕期任务攒兜豆,一件件布置好</span></div>
|
||
<button class="nyp-btn" id="nyBtn" type="button">进去布置 <svg viewBox="0 0 24 24" width="11" height="11" aria-hidden="true"><path d="M8 5l8 7-8 7z" fill="currentColor"/></svg></button>
|
||
</div>
|
||
</section>
|
||
<!-- 首页 · 兜豆兑换商城模块(2026-10-01):紧跟婴儿房(那张卡写着「攒兜豆把它布置好」),
|
||
顺着「兜豆」这条线往下接。头部一条 + 下面一排可兑好物;点哪儿都 openExchange()。 -->
|
||
<!-- 外层 .exch-wrap 套上和其它模块同款的白色外壳(2026-10-01 用户:「应该有个底色,跟其他模块一样」),里面粉色卡不变 -->
|
||
<section class="exch-wrap" id="homeExchMod"><div class="exch-mod">
|
||
<button class="exch-strip ripple" id="homeExch">
|
||
<span class="es-coin" aria-hidden="true"><img src="assets/img/dou-coin.svg?v=20261002" width="36" height="36" alt=""></span>
|
||
<span class="es-main"><b>兜豆兑换</b><span id="homeExchSub">做孕期任务就能攒兜豆</span></span>
|
||
<span class="es-go">去兑换<i>›</i></span>
|
||
</button>
|
||
<!-- 本场可兑好物(/mall/drop:有库存且已开售,按 heat_30m 降序取前 6),横向滑动;拉不到数据整行隐藏 -->
|
||
<div class="ex-goods hide" id="homeExchGoods"></div>
|
||
</div></section>
|
||
|
||
<!-- 模块二 · 今天的动线。
|
||
上一版这里是两个各自独立的模块:「AI今日小结」一张渐变卡,
|
||
下面「今日成长脚印」一张白卡装的时间轴。可 AI 那句话总结的
|
||
就是脚印里这四条记录,中间隔着一整套抬头分开摆,两边都在自说自话。
|
||
现在合成一条线:起点是「今天」,中间四条记录,
|
||
末尾挂 AI 那句话当这一天的落款。
|
||
时间轴外面那张白卡也撤了 —— 结构改由 .today-line::before 那条
|
||
贯穿到底的竖线撑起来,不再靠一个方框圈出来,
|
||
这样它和上面的托盘、下面的卡带才真的是三种容器语言。
|
||
|
||
⚠️ .steps 仍是整卡可点的 role="button",里面**不能**再出现 <button>。
|
||
所以「查看全部 ›」挂在 .tl-head 上、AI 气泡是 .steps 的兄弟节点,
|
||
两者都在 .steps 外面。 -->
|
||
<!-- 今日脚印 2026-10-01 改版(用户:「对标其他模块,UI 要漂亮一些,内容文字也要有创意」):
|
||
· 头部左边一张撕页日历(日 / 月·周几),右边标题 + 一句小诗;
|
||
· 每条记录前的圆点换成**一左一右交替的小脚丫**,沿虚线往下走 —— 「脚印」两个字画出来;
|
||
· 每条记录是一张小卡:大字内容(数字加粗上色)+ 时间 + 来源小标签;
|
||
· 没记录时(guide)是一行脚丫插画 + 接口给的引导语(童趣字体)+ 带 logo 的应用芯片;
|
||
· AI 小结做成「宝宝写给妈妈的一张便签」:信纸横线 + 宝宝口吻 + 落款小名。
|
||
⚠️ 「AI」角标必须保留(唯一的机器生成提示,见 syncBabyWords 那段注释)。
|
||
JS 依赖的 id / class(.today-line / #tlSteps / .step 系列 / #tlGuide* / .ai-bubble / .ab-say / #abTag / #tlTitle)都沿用。 -->
|
||
<!-- 2026-10-31 用户:「把宝宝的今日脚印这个模块去掉」→ 整块不显示(含祈福掀角、AI 便签)。
|
||
节点先留着:app.js 足迹 / AI 小结 / 此刻 等逻辑还在往里面写数,删节点要连带改 JS。 -->
|
||
<section class="today-line fp2" hidden style="display:none">
|
||
<!-- 2026-10-05 祈福树入口(用户:「放到今日脚印的右上角,把右上角掀开一点,露出祈福树」):
|
||
卡片右上角像纸一样折起一角(.pl-flap 是翻过来的纸背),底下那块(.pl-hole)露出祈福树;点它跳祈福树(js/app.js #fpQifu)。
|
||
之前放在工具卡右上角 / 头图底边的版本已撤,工具卡恢复「所有工具 ›」。样式见 mama-box.css「祈福树入口 · 今日脚印掀角」。 -->
|
||
<a class="fp-peel" id="fpQifu" href="/qifu-shu/" aria-label="宝宝祈福树"><span class="pl-hole"><img src="assets/img/qifu-tree.png" alt="" width="31" height="30"></span><span class="pl-flapw"><span class="pl-flap"></span></span><span class="pl-t">祈福</span></a>
|
||
<div class="fp-head">
|
||
<div class="fp-cal" aria-hidden="true"><i class="fc-ring"></i><b id="fpCalD">--</b><span id="fpCalM">--</span></div>
|
||
<div class="fp-ht">
|
||
<h2 class="tl-h-title" id="tlTitle">宝宝的今日脚印</h2>
|
||
<p class="fp-poem fp-date" id="fpDate"></p>
|
||
</div>
|
||
<!-- 2026-10-05 用户:「祈福树左侧那个『全部』取消掉」→ 删了「全部 ›」。进档案仍可点脚印列表(#tlSteps data-goto=archive)或底部「档案」tab。 -->
|
||
</div>
|
||
<div class="steps fp-steps ripple" id="tlSteps" data-goto="archive" role="button" tabindex="0" aria-label="宝宝的今日脚印,查看完整档案">
|
||
<div class="step"><span class="st-time">今天</span><span class="st-dot"></span><span class="st-txt">正在获取今天的脚印…</span><span class="st-from"></span></div>
|
||
</div>
|
||
<!-- 2026-10-02 用户要求:今天还没用任何工具时,不再放示例/引导语,改成「今日待办」清单,提醒她今天该做什么。
|
||
条目 = 接口 unused(今天还没用的、已上架的应用),文案由 app.js FP_TODO 按应用名配成一句动作。 -->
|
||
<div class="tl-guide fp-guide fp-todo" id="tlGuide" style="display:none">
|
||
<div class="td-head"><b>今日待办</b><span class="td-cnt" id="tdCnt"></span></div>
|
||
<p class="tl-guide-t td-lead" id="tlGuideTitle"></p>
|
||
<div class="tl-guide-apps td-list" id="tlGuideApps"></div>
|
||
<p class="tl-guide-s td-foot" id="tlGuideSub"></p>
|
||
</div>
|
||
<button class="ai-bubble fp-note ripple" data-open="detailAI">
|
||
<span class="fn-top"><b class="ab-tag" id="abTag">宝宝今天想说</b></span>
|
||
<span class="ab-say"></span>
|
||
<span class="fn-foot"><span class="fn-sign" id="fpSign">—— 宝宝</span><em>往期小结 ›</em></span>
|
||
</button>
|
||
</section>
|
||
|
||
<!-- 树洞(2026-09-30)。用户原话:「宝妈们有任何情绪上的问题,都可以在这个树洞里扔进去」。
|
||
用户选定:**只存在她自己手机上**(localStorage 'mmbox.treehole.v1',不上传、后台也看不到),
|
||
扔进去后**只有「已收好」的动画,不做回应**。
|
||
⚠️ 唯一的例外是安全提示:内容里出现明显的轻生字眼时,收好之后在卡内显示一行援助热线
|
||
(12356 全国心理援助热线),这不是「回应心事」,是兜底,别删。
|
||
⚠️ 纸团飞进树洞的动画靠 Element.animate;不支持的老内核直接跳到「已收好」,不影响收存。 -->
|
||
<!-- 「妈妈的树洞」整块已删(2026-10-01 用户要求)。样式与 JS 一并删除,需要恢复看 git 历史 70c9786。 -->
|
||
|
||
<!-- 宝宝消消乐 · 推广入口(2026-09-30)。用户原话:「做了一个消消乐小游戏(待产清单主题),
|
||
放到首页展示并推广,宝妈们业余时间玩,名字叫宝宝消消乐」。
|
||
2026-10-09 用户改名「宝贝消消乐」(游戏页同步改了)。
|
||
2026-10-01 用户要求和 3D 婴儿房对调位置:现在在「今天的动线」和书架之间(原来在工具托盘正下方)。右侧 3×3 小棋盘是纯装饰动画
|
||
(每隔几秒一行三个同样的待产用品闪一下「消掉」再换新),JS 在 app.js gamePromo()。
|
||
游戏地址在 app.js 的 GAME_URL;为空时整块隐藏(.hide 默认)。点击走 jumpApp(),带身份跳转。 -->
|
||
<section class="game-promo hide" id="gamePromo">
|
||
<button class="gp-card ripple" id="gpCard" type="button" aria-label="开始玩宝贝消消乐">
|
||
<span class="gp-new">兜爸旗下小游戏</span>
|
||
<span class="gp-text">
|
||
<span class="gp-name">宝贝消消乐</span>
|
||
<span class="gp-sub">三消攒待产好物,兜豆兑好礼</span>
|
||
</span>
|
||
<span class="gp-board" id="gpBoard" aria-hidden="true"></span>
|
||
<span class="gp-cta">开始玩 <svg viewBox="0 0 24 24" width="12" height="12" aria-hidden="true"><path d="M8 5l8 7-8 7z" fill="currentColor"/></svg></span>
|
||
<span class="gp-spark s1" aria-hidden="true">✦</span><span class="gp-spark s2" aria-hidden="true">✦</span><span class="gp-spark s3" aria-hidden="true">✦</span>
|
||
</button>
|
||
</section>
|
||
|
||
<!-- 模块三 · 书架卡带。
|
||
上一版是「一张横排大卡 + 下面两张小卡」的老三段,和上面两个模块
|
||
一样都是往下堆。这里改成一条横向可滑的书架:三张等宽等高的**竖版**书
|
||
(封面在上、书名在下、免费标在底),右边故意露出下一张的边角,
|
||
不用画箭头也知道能往右滑。整页因此多了一段「可以往右读」的节奏 ——
|
||
这是最直观的一处排版变化。
|
||
资源这类内容对可发现性的要求低(不像工具是每天要点的),
|
||
收进横滑里是合适的;工具那一屏就没这么干。
|
||
|
||
⚠️ data-wk="n" 是从原来那条 h2 里搬过来的。app.js 用
|
||
$$('[data-wk]') 全局扫,属性一丢孕周就永远显示「—」。 -->
|
||
<section class="shelf gift2">
|
||
<!-- 2026-10-01 改版:用户要「资料免费送、是一种福利、针对这个孕周」的感觉。
|
||
抬头改成礼盒 + 「孕N周专属福利」,三张书卡改成「福利券」:左上孕周专属角标、
|
||
封面右上「免费」印章、中间一道撕券虚线、底行「免费领 ›」。
|
||
⚠️ data-wk 照旧(app.js $$('[data-wk]') 全局扫,角标里那两个也会被填上)。 -->
|
||
<div class="shelf-bar gb-bar">
|
||
<span class="gb-gift" aria-hidden="true"><svg viewBox="0 0 24 24" width="26" height="26"><rect x="4.5" y="10.5" width="15" height="9.5" rx="2" fill="#fff"/><rect x="3.2" y="7.4" width="17.6" height="4.2" rx="1.6" fill="#fff"/><rect x="11" y="7.4" width="2" height="12.6" fill="#F7745E"/><rect x="3.2" y="11" width="17.6" height="1" fill="#F7745E" opacity=".35"/><path d="M12 7.4C10.6 4.6 7.6 4.2 7.6 6.1c0 1.3 2.2 1.3 4.4 1.3zm0 0c1.4-2.8 4.4-3.2 4.4-1.3 0 1.3-2.2 1.3-4.4 1.3z" fill="none" stroke="#fff" stroke-width="1.6" stroke-linejoin="round"/><path d="M20 1.8l.5 1.3 1.3.5-1.3.5-.5 1.3-.5-1.3-1.3-.5 1.3-.5z" fill="#FFF3C4"/></svg></span>
|
||
<div class="gb-ht">
|
||
<h2 class="sh-title">孕<span data-wk="n">—</span>周专属福利</h2>
|
||
<p class="sh-note">这周用得上的孕育资料,<b>全部免费送</b></p>
|
||
</div>
|
||
<button class="sh-all" data-open="detailResList">全部 ›</button>
|
||
</div>
|
||
<!-- 三张卡的内部结构是**逐行对齐**的:封面 / 标题 / 简介 / 底行,一个不缺。
|
||
上一稿只有第一张有简介、也只有第一张有「立即领取」,另两张少两截,
|
||
于是三张卡的标题落在不同高度、底行也不齐 —— 这就是看着乱的原因。
|
||
封面给了固定高度(80px + object-fit:contain),底行靠
|
||
.sb-row{margin-top:auto} 顶到卡底,中间的简介统一截两行,
|
||
三张就自然等高、四段横着都成列了。
|
||
⚠️ 原来第一张那颗「立即领取」删掉了:整张卡本身就是个 <button>,
|
||
点哪儿都是进详情页,那颗 span 长得像按钮却并不真的领取,是个假承诺;
|
||
而且三张卡并列时三颗橙色大按钮也太吵。领取动作留在详情页底部。
|
||
|
||
底行读作一句话:「这些人领了 → 一共 12.8 万 → 而且免费」。
|
||
所以头像贴着人数(同一件事的两半,中间只留 7px),「免费」用
|
||
margin-left:auto 甩到最右,是另起的一件事。
|
||
.sb-faces 里那 6 个 <i> 是**装饰**,不是真实用户头像 ——
|
||
assets/ 里没有人像图,也不该为这点装饰新增二进制资源,
|
||
所以整叠头像是纯 CSS 画的(圆底 + ::before 头 + ::after 肩)。
|
||
aria-hidden:读屏念到这行应该只听见「12.8 万妈妈已领取」,
|
||
而不是六个没有内容的空节点。
|
||
|
||
⚠️ 上面那三个数(12.8 / 20.4 / 9.6 万)是**真实领取量**,不是编的 ——
|
||
2026-09-22 有人按「人气数看着像演示值」把它们连同头像叠一起删了,
|
||
属**误判**,已恢复。**别再删**。它们是**手工同步的静态文案**:
|
||
接口虽返回同源的 got(已领),但 __applyResources 明确「有意不读」
|
||
(9.19 起 H5 已无「已领」概念),所以更新领取量时要**手工改这三处**;
|
||
要改成读接口,得先把这个口径捋清再动。 -->
|
||
<div class="shelf-rail">
|
||
<button class="shelf-book sb-book ripple" data-open="detailRes" data-res="book">
|
||
<span class="sb-tag">孕<span data-wk="n">—</span>周专属</span>
|
||
<img class="sb-cover" src="assets/img/9f3fa8edf4aa.png" alt="" aria-hidden="true">
|
||
<span class="sb-title">《糖耐检查全攻略》</span>
|
||
<span class="sb-desc">孕24-28周必看 · 附检查前饮食清单</span>
|
||
<span class="sb-row"><span class="sb-faces" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i></span><i class="sb-got">12.8 万妈妈已领取</i><span class="pill-free">免费领</span></span>
|
||
</button>
|
||
<button class="shelf-book sb-food ripple" data-open="detailRes" data-res="food">
|
||
<span class="sb-tag">孕<span data-wk="n">—</span>周专属</span>
|
||
<img class="sb-cover" src="assets/img/3657b1f76026.png" alt="" aria-hidden="true">
|
||
<span class="sb-title">孕期营养全书</span>
|
||
<span class="sb-desc">按孕周编排的一日三餐参考</span>
|
||
<span class="sb-row"><span class="sb-faces" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i></span><i class="sb-got">20.4 万妈妈已领取</i><span class="pill-free">免费领</span></span>
|
||
</button>
|
||
<button class="shelf-book sb-music ripple" data-open="detailRes" data-res="music">
|
||
<span class="sb-tag">孕<span data-wk="n">—</span>周专属</span>
|
||
<img class="sb-cover" src="assets/img/67405412c52c.png" alt="" aria-hidden="true">
|
||
<span class="sb-title">胎教音乐合集</span>
|
||
<span class="sb-desc">30 首适合孕中期的舒缓曲目</span>
|
||
<span class="sb-row"><span class="sb-faces" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i></span><i class="sb-got">9.6 万妈妈已领取</i><span class="pill-free">免费领</span></span>
|
||
</button>
|
||
</div>
|
||
<!-- ⚠️ 这句话现在是**静态文案**(2026-09-19 9.19 需求:兑换码闸门取消,
|
||
不再有「已解锁/未解锁」两版口径,原来那个给 syncUnlockCopy() 用的
|
||
#shelfLeadTxt 靶子和该函数一起删了)。
|
||
旁边「查看全部 ›」是个 <a data-open>,它的点击监听是 init 时一次性
|
||
绑上去的 —— 谁要是图省事对整个 <p> 写 innerHTML,链接会连同监听被静默
|
||
换掉(看着一模一样,就是点不动),别再引入这种写法。
|
||
|
||
⚠️ 128 是**后端准备好的资料总数**,不是「资源列表里当前有多少条」——
|
||
2026-09-22 有人按「数字与列表条数不符」把它改成 RES 的条数,属**误判**,已回退:
|
||
· 资料按孕周陆续发放,目前上架 8 份,其余会陆续跟进;
|
||
· 没上架的**并非拿不到** —— 扫码加小助手可以直接索要(见顾问二维码弹窗)。
|
||
所以「128 份等你来领」是邀请口径(含找小助手要的),跟「列表当前 8 条」
|
||
是两件事,**数字不一样是对的**,别再"修"。 -->
|
||
<p class="unlock"><i class="ul-gift" aria-hidden="true"></i>福利库还有 <b>128</b> 份资料等你领 · <a data-open="detailResList">查看全部 ›</a></p>
|
||
</section>
|
||
|
||
<!-- 孕期盲盒 · 首页细横幅(2026-10-01,需求文档 v1.0 三-7)。
|
||
放在顶部大图正下方(需求:顶部大图 → 盲盒横幅 → 孕育工具 → 此刻 → 消消乐)。
|
||
文案/状态全由 app.js renderBanner() 按 /blindbox 返回写入;访客态(无 openid)、孕 4 周前、接口失败 → 保持 .hide。
|
||
⚠️ 2026-10-02 用户:「把盲盒放到首页下边,给一个位置就行,不用太明显」→
|
||
挪到 #homeBody 最后(福利书架之后),样式收成一条低调细条(见 CSS「盲盒挪到页底」)。
|
||
工具托盘因此重新成为第一个孩子,.home-body>:first-child 间距直接作用在它身上。 -->
|
||
<button class="bb-banner hide" id="bbBanner" type="button">
|
||
<span class="bb-gift" id="bbGift" aria-hidden="true"></span>
|
||
<span class="bb-badge hide" id="bbBadge" aria-hidden="true"></span>
|
||
<span class="bb-txt"><b class="bb-t" id="bbTitle"></b><span class="bb-s" id="bbSub"></span></span>
|
||
<span class="bb-cta" id="bbCta"></span>
|
||
<i class="bb-shine" aria-hidden="true"></i>
|
||
</button>
|
||
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<section class="screen" id="screen-archive" data-screen="archive">
|
||
<div class="page-hero">
|
||
<div class="hero-top">
|
||
<div class="hero-actions">
|
||
<button class="icon-btn glass" data-search="1" aria-label="搜索"><svg viewBox="0 0 24 24" width="19" height="19"><circle cx="11" cy="11" r="6.5" fill="none" stroke="currentColor" stroke-width="1.9"/><path d="M16 16l4.5 4.5" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"/></svg></button>
|
||
<button class="icon-btn glass" data-toast="更多操作" aria-label="更多"><svg viewBox="0 0 24 24" width="19" height="19"><circle cx="5" cy="12" r="1.7"/><circle cx="12" cy="12" r="1.7"/><circle cx="19" cy="12" r="1.7"/></svg></button>
|
||
</div>
|
||
</div>
|
||
<!-- 这一块整体重排过一次,改动的理由都写在下面各处 -->
|
||
<div class="hero-info ar-hero">
|
||
<!-- 页面名。上一版把它降成了 13px、opacity .78 的一行眉批 ——
|
||
当时的理由是「底部 tab 上就写着档案,别拿 27px 再说一遍」,
|
||
字号该让给孕周,这点现在还成立。但让过头了:
|
||
这行是整个页面唯一出现宝宝小名的地方,糊在橙底上基本读不到。
|
||
这一版不靠字号抢回来(25px 仍然归 .ar-week),改成一枚毛玻璃小牌:
|
||
半透明白底 + 一圈描边,从橙色里浮出来;小名单独拎出来加粗放大,
|
||
「的成长档案」压一档跟在后面 —— 重音落在名字上,而不是「档案」上。
|
||
⚠️ 小名现在写进 #arTitleName,不再是 #arTitle 本身。
|
||
syncPregnancy() 里那句赋值跟着改了,别再往 #arTitle 上写 textContent,
|
||
那会把牌子里的图标和「的成长档案」一起冲掉。 -->
|
||
<h1 class="ar-title" id="arTitle"><svg class="ar-t-ico" viewBox="0 0 24 24" width="13" height="13" aria-hidden="true"><path d="M4 4.5A1.5 1.5 0 015.5 3H10a3 3 0 013 3v13a2.5 2.5 0 00-2.5-2.5H4z" fill="currentColor" opacity=".5"/><path d="M20 4.5A1.5 1.5 0 0018.5 3H14a3 3 0 00-3 3v13a2.5 2.5 0 012.5-2.5H20z" fill="currentColor"/></svg><b class="ar-t-name" id="arTitleName">宝宝</b><span class="ar-t-rest">的成长档案</span></h1>
|
||
<!-- 这两行 + 左边那个大小图标 + 下面的孕程条,都由 syncPregnancy() 按孕期信息重算。
|
||
emoji 用 aria-hidden 挡掉:读屏念成「玉米」会和紧跟着的「像一根玉米了」重复 -->
|
||
<div class="ar-lines">
|
||
<span class="ar-size" id="arSizeArt" aria-hidden="true">🌽</span>
|
||
<div>
|
||
<p class="ar-week" id="arLine1">孕 24 周 +3 天</p>
|
||
<p class="hero-p sub" id="arLine2">像一根玉米了 · 约 600 克</p>
|
||
</div>
|
||
</div>
|
||
<!-- 孕程原来是右边一个 84px 的圆环,和首页 hero 那个环长得一模一样,
|
||
两页来回切像同一个组件贴了两遍;它还横着吃掉近三分之一宽度,
|
||
逼得旁边的字只能写得又短又挤,「已陪伴 171 天」当时就只能拿个「·」
|
||
硬接在孕周后面,两个不相干的单位读起来像一句话。
|
||
换成一条通栏细进度条:高 5px,信息一点没少,左右还各空出一个角,
|
||
「孕程」和「已陪伴」这才各站各的位置。 -->
|
||
<div class="ar-prog"><i id="arBar"></i></div>
|
||
<div class="ar-foot">
|
||
<span>孕程 <b id="arPct">60%</b></span>
|
||
<span>已陪伴 <b id="arDays">171</b> 天</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="page-body">
|
||
<!-- ========== 正在自动归档 + 生成档案(合成一张卡) ==========
|
||
顺序:标题 → 两个生成入口 → 归档条数统计。
|
||
周档案:每周一张长图,保存到相册或分享朋友圈;
|
||
完整档案:从记录第一天到今天,排成一本 A4 分页的册子,打印出来能直接装订。
|
||
两者都是 canvas 现画出来的,不依赖任何外部库。 -->
|
||
<div class="auto-card">
|
||
<div class="ac-head">
|
||
<span class="ac-h-l"><span class="live-dot"></span> 正在自动归档</span>
|
||
<span class="gen-badge" id="genWeekTag">第 24 周</span>
|
||
</div>
|
||
<!-- 说明文字拆进了下面两个入口各自的副标题:
|
||
谁能干什么写在谁身上,比笼统一句更好读。
|
||
「可打印」原本在这里的角标和按钮里各出现一次,现在只留按钮那处 -->
|
||
<div class="gen-btns">
|
||
<button class="gen-btn ripple" data-poster="week">
|
||
<svg viewBox="0 0 24 24" width="21" height="21" aria-hidden="true">
|
||
<rect x="3.5" y="4.5" width="17" height="16" rx="3" fill="none" stroke="currentColor" stroke-width="1.8"/>
|
||
<path d="M3.5 9.5h17M8 2.8v3.4M16 2.8v3.4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||
<rect x="7" y="12.5" width="5" height="4" rx="1.2" fill="currentColor"/>
|
||
</svg>
|
||
<span><b>本周档案</b><em>存相册 · 发朋友圈</em></span>
|
||
</button>
|
||
<button class="gen-btn ripple" data-poster="all">
|
||
<svg viewBox="0 0 24 24" width="21" height="21" aria-hidden="true">
|
||
<path d="M7 3.5h7.5L19 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
||
<path d="M14 3.5V8h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
||
<path d="M10 12h6M10 15.5h6M10 19h3.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||
</svg>
|
||
<span><b>完整档案</b><em>A4 分页 · 可装订</em></span>
|
||
</button>
|
||
</div>
|
||
<div class="ac-chips">
|
||
<span class="chip-stat">今日已归档 <b>4</b> 条</span>
|
||
<span class="chip-stat">累计 <b>386</b> 条</span>
|
||
<span class="chip-stat">来自 <b>9</b> 个孕期工具</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="segmented" id="archiveSeg">
|
||
<span class="seg-thumb" id="segThumb"></span>
|
||
<!-- ⚠️ 这三个按钮的顺序必须和下面 .seg-panel 的 DOM 顺序一一对应。
|
||
initSegmented() 是按 .is-active 在兄弟节点里的**序号**算 #segThumb 的 x 偏移,
|
||
只改按钮不改面板 → 高亮停在「成长数据」、底下却显示时光轴。 -->
|
||
<button class="seg-btn is-active" data-seg="data">成长数据</button>
|
||
<button class="seg-btn" data-seg="timeline">时光轴</button>
|
||
<!-- 收藏数原本在下面那行 sec-title 里,那行整条删了,
|
||
数字搬到标签上(和分段控件里其它计数同一种写法),#favCount 仍由 JS 更新。
|
||
⚠️ 这里原来写死 18,而屏幕上点亮的星标只有 6 个 —— 数字与内容对不上。
|
||
现在默认 0,由 app.js 启动时按 DOM 里 `.star.is-on` 的**实际个数**回填
|
||
(档案页不是首屏,用户看不到中间态;点星标时再 ±1)。 -->
|
||
<button class="seg-btn" data-seg="moment">珍贵时刻 <i id="favCount">0</i></button>
|
||
</div>
|
||
|
||
<!-- 成长数据 -->
|
||
<div class="seg-panel is-active" data-panel="data">
|
||
<!-- ⚠️ 空态(未建档 / pregEmpty):syncPregnancy 会给本面板加 .is-empty,
|
||
把下面三块**全无数据源**的演示内容整块隐藏,改显示这行引导。
|
||
三块里没有一个数字来自接口:58.2kg / 31 次 / 600g / 双顶径 6.1cm 都是设计稿数字,
|
||
未建档用户看到就是纯假数据(2026-09-22 实测)。 -->
|
||
<div class="data-empty">还没有可统计的记录<br>去「数胎动」或「孕期体重」记一笔,这里会生成趋势</div>
|
||
<div class="stat-row data-demo">
|
||
<div class="stat-card">
|
||
<div class="sc-label">体重</div>
|
||
<div class="sc-value">58.2<small>kg</small></div>
|
||
<div class="sc-trend up">↑ 7.7kg</div>
|
||
<svg class="spark" viewBox="0 0 100 34"><polyline points="2,30 26,24 50,17 74,10 98,4" fill="none" stroke="#F4593C" stroke-width="2.6" stroke-linecap="round"/></svg>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="sc-label">日均胎动</div>
|
||
<div class="sc-value">31<small>次</small></div>
|
||
<div class="sc-trend ok">正常</div>
|
||
<svg class="spark" viewBox="0 0 100 34"><polyline points="2,20 20,8 38,24 56,10 74,26 98,14" fill="none" stroke="#7FA86A" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
</div>
|
||
<div class="stat-card">
|
||
<div class="sc-label">估计体重</div>
|
||
<div class="sc-value">600<small>g</small></div>
|
||
<div class="sc-trend purple">P55</div>
|
||
<svg class="spark" viewBox="0 0 100 34"><polyline points="2,29 26,23 50,17 74,11 98,4" fill="none" stroke="#8B6FE0" stroke-width="2.6" stroke-linecap="round"/></svg>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="chart-card data-demo">
|
||
<div class="cc-title">妈妈体重 · 孕12–24周</div>
|
||
<svg class="chart" viewBox="0 0 320 150">
|
||
<line class="grid" x1="4" y1="20" x2="316" y2="20"/>
|
||
<line class="grid" x1="4" y1="66" x2="316" y2="66"/>
|
||
<line class="grid" x1="4" y1="112" x2="316" y2="112"/>
|
||
<path class="band" d="M8,138 L83,120 L158,100 L234,76 L310,54 L310,14 L234,36 L158,60 L83,80 L8,98 Z"/>
|
||
<path class="area" d="M8,124 L83,106 L158,86 L234,62 L310,40 L310,146 L8,146 Z"/>
|
||
<polyline class="line" points="8,124 83,106 158,86 234,62 310,40"/>
|
||
<circle class="pt" cx="83" cy="106" r="6"/><circle class="pt" cx="158" cy="86" r="6"/><circle class="pt" cx="234" cy="62" r="6"/>
|
||
<circle class="pt fill" cx="310" cy="40" r="7"/>
|
||
</svg>
|
||
<div class="cc-x"><span>12周</span><span>16周</span><span>20周</span><span>24周</span></div>
|
||
<div class="cc-legend"><span class="lg lg-line">我的体重</span><span class="lg lg-band">推荐区间</span></div>
|
||
</div>
|
||
|
||
<div class="meas-card data-demo">
|
||
<div class="meas"><span class="m-name">双顶径</span><div class="m-bar" style="--p:54%"><i></i></div><div class="m-val">6.1<small>cm</small><em>P58</em></div></div>
|
||
<div class="meas"><span class="m-name">股骨长</span><div class="m-bar" style="--p:50%"><i></i></div><div class="m-val">4.4<small>cm</small><em>P52</em></div></div>
|
||
<div class="meas"><span class="m-name">腹围</span><div class="m-bar" style="--p:60%"><i></i></div><div class="m-val">19.6<small>cm</small><em>P61</em></div></div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 时光轴 -->
|
||
<!-- 这里原来还压着一排分类 chips(全部/胎动/产检/来信/手记)。删了:
|
||
上面刚有一排「时光轴 / 成长数据 / 珍贵时刻」的分段,紧接着再来一排样子
|
||
几乎一样的标签,两排叠在一起谁管谁根本看不出来。
|
||
而且时光轴统共五条,一条一个分类,筛完最多剩两条 —— 为了从五条里挑两条
|
||
先读五个标签,不划算。每条底下本来就写着「来自「数胎动」」,
|
||
要认哪一类,读那行就够了。 -->
|
||
<div class="seg-panel" data-panel="timeline">
|
||
<div class="tl-card">
|
||
<div class="tl-item" data-cat="胎动">
|
||
<div class="tl-date" data-ga="now"></div>
|
||
<p class="tl-text">早上 9 点 10 分,他动了 <b>12 次</b>。你说那感觉像有人在里面轻轻敲门。</p>
|
||
<span class="tl-from">来自「数胎动」</span>
|
||
</div>
|
||
<div class="tl-item" data-cat="产检">
|
||
<div class="tl-date" data-ga="20"></div>
|
||
<p class="tl-text">大排畸那天,你第一次看清了他的侧脸。医生说「一切都好」,你在诊室外站了很久。</p>
|
||
<span class="tl-from">来自「孕检日历」+「B超影像」</span>
|
||
</div>
|
||
<div class="tl-item" data-cat="胎动">
|
||
<div class="tl-date" data-ga="18"></div>
|
||
<p class="tl-text">傍晚散步时,肚子里忽然有一下轻轻的翻涌 —— <b>第一次胎动</b>。你愣在原地,然后笑了。</p>
|
||
<span class="tl-from">来自「胎动记录」</span>
|
||
</div>
|
||
<div class="tl-item" data-cat="产检">
|
||
<div class="tl-date" data-ga="8"></div>
|
||
<p class="tl-text">第一次听见心跳,很快,像小火车。你把那 12 秒录了下来。</p>
|
||
<span class="tl-from">来自「胎心记录」</span>
|
||
</div>
|
||
<div class="tl-item" data-cat="手记">
|
||
<div class="tl-date" data-ga="1"></div>
|
||
<p class="tl-text">那两条线出现的早晨,你把它拍下来,发给了他。你们谁都没说话,笑了很久。</p>
|
||
<span class="tl-from">来自「妈妈手记」</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 珍贵时刻 -->
|
||
<!-- 同样删掉了一排分类 chips(全部/第一次/影像/声音/手写)。
|
||
六个格子的九宫格,本身一眼就扫完了,再给它配五个筛选标签是本末倒置。 -->
|
||
<div class="seg-panel" data-panel="moment">
|
||
<!-- 珍贵时刻的封面图标:原来是 emoji(🖼️💌👣🎧🤰✍️),
|
||
各系统渲染成的样子完全不同(拟物、彩色、还带阴影),
|
||
这里统一换成同一套线性扁平 SVG,颜色跟着各自的渐变底走 -->
|
||
<div class="moment-grid">
|
||
<button class="moment ripple" data-cat="影像 第一次" data-toast="第一张B超 · 孕8周">
|
||
<div class="mo-art a1">
|
||
<svg viewBox="0 0 48 48" aria-hidden="true">
|
||
<rect x="7" y="9" width="34" height="26" rx="5" class="f"/>
|
||
<rect x="7" y="9" width="34" height="26" rx="5" class="s"/>
|
||
<path d="M16 29a12 12 0 0 1 12-12" class="s"/>
|
||
<path d="M16 29a7 7 0 0 1 7-7" class="s"/>
|
||
<circle cx="16" cy="29" r="2.4" class="d"/>
|
||
<path d="M24 35v4M20 39h8" class="s"/>
|
||
</svg>
|
||
<i class="star is-on">★</i>
|
||
</div>
|
||
<div class="mo-title">第一张B超</div><div class="mo-meta" data-ga="8"></div><span class="mo-from">来自「B超影像」</span>
|
||
</button>
|
||
<!-- ⚠️ `.mo-from` 引的是**底 tab 的名字**,不是随便一句出处。
|
||
tab 叫什么,这里就必须写什么 —— 指过去的地方得真的存在。
|
||
上一批 tab 改叫「宝宝消息」时这三处跟着改过(标题「第一条消息」、
|
||
出处「来自「宝宝消息」」、data-toast),本批 tab 退回「宝宝来信」,
|
||
三处一起退。
|
||
⚠️ 宽度:来回都是等字数替换(5 字换 5 字、8 字换 8 字),
|
||
.mo-title / .mo-from 的排版账不用重算。
|
||
⚠️ data-toast 那句是点上去弹的提示,和标题同源,一起改,别只改一处 ——
|
||
它藏在属性里,只扫 textContent 的检查看不见它。 -->
|
||
<button class="moment ripple" data-cat="第一次" data-toast="第一封来信 · 孕12周">
|
||
<div class="mo-art a2">
|
||
<svg viewBox="0 0 48 48" aria-hidden="true">
|
||
<rect x="6" y="11" width="36" height="26" rx="5" class="f"/>
|
||
<rect x="6" y="11" width="36" height="26" rx="5" class="s"/>
|
||
<path d="M8.5 14.5l14 11a2.4 2.4 0 0 0 3 0l14-11" class="s"/>
|
||
</svg>
|
||
<i class="star is-on">★</i>
|
||
</div>
|
||
<div class="mo-title">第一封来信</div><div class="mo-meta" data-ga="12"></div><span class="mo-from">来自「宝宝来信」</span>
|
||
</button>
|
||
<button class="moment ripple" data-cat="第一次" data-toast="第一次胎动 · 孕18周">
|
||
<div class="mo-art a3">
|
||
<svg viewBox="0 0 48 48" aria-hidden="true">
|
||
<path d="M27 17c0 6-2.8 8.8-2.8 12.8 0 4-2.4 6.7-5.9 6.7s-6.3-2.7-6.3-6.7c0-5 2.9-7.9 2.9-12.8 0-4.1 2.6-7 5.9-7s6.2 2.9 6.2 7z" class="f"/>
|
||
<path d="M27 17c0 6-2.8 8.8-2.8 12.8 0 4-2.4 6.7-5.9 6.7s-6.3-2.7-6.3-6.7c0-5 2.9-7.9 2.9-12.8 0-4.1 2.6-7 5.9-7s6.2 2.9 6.2 7z" class="s"/>
|
||
<circle cx="31.5" cy="14.5" r="3" class="d"/>
|
||
<circle cx="35.6" cy="20.4" r="2.6" class="d"/>
|
||
<circle cx="36.8" cy="27" r="2.2" class="d"/>
|
||
</svg>
|
||
<i class="star is-on">★</i>
|
||
</div>
|
||
<div class="mo-title">第一次胎动</div><div class="mo-meta" data-ga="18"></div><span class="mo-from">来自「胎动记录」</span>
|
||
</button>
|
||
<button class="moment ripple" data-cat="声音" data-toast="正在播放 胎心录音 ♪">
|
||
<div class="mo-art a4">
|
||
<svg viewBox="0 0 48 48" aria-hidden="true">
|
||
<path d="M24 39S8 30.2 8 19.8C8 14.6 12 11.2 16.2 11.2c3.2 0 6 1.8 7.8 4.4 1.8-2.6 4.6-4.4 7.8-4.4 4.2 0 8.2 3.4 8.2 8.6C40 30.2 24 39 24 39z" class="f"/>
|
||
<path d="M24 39S8 30.2 8 19.8C8 14.6 12 11.2 16.2 11.2c3.2 0 6 1.8 7.8 4.4 1.8-2.6 4.6-4.4 7.8-4.4 4.2 0 8.2 3.4 8.2 8.6C40 30.2 24 39 24 39z" class="s"/>
|
||
<path d="M12.5 22.5h5.2l3-5.4 3.9 10.4 2.8-5h6.1" class="s"/>
|
||
</svg>
|
||
<i class="star is-on">★</i>
|
||
</div>
|
||
<div class="mo-title">胎心录音 12秒</div><div class="mo-meta" data-ga="20"></div><span class="mo-from">来自「胎心记录」</span>
|
||
</button>
|
||
<button class="moment ripple" data-cat="影像 第一次" data-toast="第一张孕肚照 · 孕22周">
|
||
<div class="mo-art a5">
|
||
<svg viewBox="0 0 48 48" aria-hidden="true">
|
||
<path d="M6 17a4 4 0 0 1 4-4h5l2.6-4.2h12.8L33 13h5a4 4 0 0 1 4 4v17a4 4 0 0 1-4 4H10a4 4 0 0 1-4-4z" class="f"/>
|
||
<path d="M6 17a4 4 0 0 1 4-4h5l2.6-4.2h12.8L33 13h5a4 4 0 0 1 4 4v17a4 4 0 0 1-4 4H10a4 4 0 0 1-4-4z" class="s"/>
|
||
<circle cx="24" cy="25.5" r="7" class="s"/>
|
||
<circle cx="24" cy="25.5" r="2.6" class="d"/>
|
||
</svg>
|
||
<i class="star is-on">★</i>
|
||
</div>
|
||
<div class="mo-title">第一张孕肚照</div><div class="mo-meta" data-ga="22"></div><span class="mo-from">来自「孕肚照」</span>
|
||
</button>
|
||
<button class="moment ripple" data-cat="手写" data-toast="给宝宝的回信 · 孕23周">
|
||
<div class="mo-art a6">
|
||
<svg viewBox="0 0 48 48" aria-hidden="true">
|
||
<path d="M31.4 8.6a4 4 0 0 1 5.7 5.7L17.6 33.8l-8.2 2.5 2.5-8.2z" class="f"/>
|
||
<path d="M31.4 8.6a4 4 0 0 1 5.7 5.7L17.6 33.8l-8.2 2.5 2.5-8.2z" class="s"/>
|
||
<path d="M28.5 11.5l5.7 5.7" class="s"/>
|
||
<path d="M14 41h22" class="s"/>
|
||
</svg>
|
||
<i class="star is-on">★</i>
|
||
</div>
|
||
<div class="mo-title">给宝宝的回信</div><div class="mo-meta" data-ga="23"></div><span class="mo-from">来自「我的回信」</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<button class="album-card ripple" data-toast="纪念册第 2 册编纂中……">
|
||
<div class="al-book"><span class="al-leaf">🌱</span><span class="al-tag">孕早期<br>1–13周</span></div>
|
||
<div class="al-body">
|
||
<div class="al-title">纪念册 <em>交给未来的孩子</em></div>
|
||
<p class="al-desc">第 1 册已成册(32 页)· 第 2 册编纂中<br>等他长大,这些会替你把话说完。</p>
|
||
<div class="al-bar"><i style="--p:62%"></i></div>
|
||
<div class="al-meta">孕中期 62% · 预计孕28周可成册</div>
|
||
</div>
|
||
</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="screen" id="screen-me" data-screen="me">
|
||
<div class="me-top me-v2">
|
||
<!-- 2026-10-01「我的」页改版:头部从实心橘渐变 + 白卡,改成蜜桃 → 珊瑚的柔光渐变,
|
||
用户信息直接压在渐变上(白字),下面一张金色「兜豆兑换商城」卡半压在头部边缘。
|
||
装饰:两团柔光 + 几颗小星星,纯 CSS/SVG,不加图片请求。 -->
|
||
<i class="mt-glow g1" aria-hidden="true"></i><i class="mt-glow g2" aria-hidden="true"></i>
|
||
<svg class="mt-stars" viewBox="0 0 120 60" aria-hidden="true"><path d="M20 14l1.6 4.2 4.4 1.6-4.4 1.6L20 25.6l-1.6-4.2-4.4-1.6 4.4-1.6z" fill="#fff" opacity=".75"/><path d="M92 8l1 2.6 2.6 1-2.6 1L92 15.2l-1-2.6-2.6-1 2.6-1z" fill="#fff" opacity=".6"/><circle cx="64" cy="22" r="1.6" fill="#fff" opacity=".55"/><circle cx="108" cy="40" r="1.2" fill="#fff" opacity=".5"/></svg>
|
||
<div class="hero-top">
|
||
<!-- (商城图标已移除:进商城统一走下方「兜爸心选」模块 meMallCard)
|
||
<button class="icon-btn plain" id="btnMall" aria-label="进商城">
|
||
<svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true">
|
||
<path d="M5 8h14l-1.2 11a2 2 0 0 1-2 1.8H8.2a2 2 0 0 1-2-1.8z" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/>
|
||
<path d="M8.6 10V6.8a3.4 3.4 0 0 1 6.8 0V10" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
-->
|
||
<!-- 扁平化齿轮:描边式矢量,替换原本的 ⚙️ emoji -->
|
||
<button class="icon-btn plain" data-modal="modalProfile" aria-label="设置">
|
||
<svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true">
|
||
<path d="M12 15.2a3.2 3.2 0 1 0 0-6.4 3.2 3.2 0 0 0 0 6.4z" fill="none" stroke="currentColor" stroke-width="1.7"/>
|
||
<path d="M19.4 13.5a1.5 1.5 0 0 0 .3 1.65l.06.05a1.8 1.8 0 1 1-2.55 2.55l-.05-.06a1.5 1.5 0 0 0-1.65-.3 1.5 1.5 0 0 0-.91 1.37v.14a1.8 1.8 0 1 1-3.6 0v-.07a1.5 1.5 0 0 0-.98-1.37 1.5 1.5 0 0 0-1.65.3l-.05.06a1.8 1.8 0 1 1-2.55-2.55l.06-.05a1.5 1.5 0 0 0 .3-1.65 1.5 1.5 0 0 0-1.37-.91h-.14a1.8 1.8 0 1 1 0-3.6h.07a1.5 1.5 0 0 0 1.37-.98 1.5 1.5 0 0 0-.3-1.65l-.06-.05A1.8 1.8 0 1 1 8.5 4.01l.05.06a1.5 1.5 0 0 0 1.65.3h.07a1.5 1.5 0 0 0 .91-1.37v-.14a1.8 1.8 0 1 1 3.6 0v.07a1.5 1.5 0 0 0 .91 1.37 1.5 1.5 0 0 0 1.65-.3l.05-.06a1.8 1.8 0 1 1 2.55 2.55l-.06.05a1.5 1.5 0 0 0-.3 1.65v.07a1.5 1.5 0 0 0 1.37.91h.14a1.8 1.8 0 1 1 0 3.6h-.07a1.5 1.5 0 0 0-1.37.91z" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<!-- 整张卡可点:点它和点右上角齿轮都会打开「我的资料」弹窗。
|
||
这里保持 div 而不是 button——里面还嵌着头像的编辑角标,
|
||
button 套 button 是非法结构,浏览器会把 DOM 拆开 -->
|
||
<div class="me-card ripple" data-modal="modalProfile" role="button" tabindex="0">
|
||
<div class="me-avatar" id="meAvatar">
|
||
<svg viewBox="0 0 40 40" width="34" height="34" aria-hidden="true">
|
||
<!-- 卡片改成白底后,写死的 #fff 剪影会直接看不见,改由 .me-avatar 的 color 决定 -->
|
||
<circle cx="20" cy="14.5" r="7" fill="currentColor"/>
|
||
<path d="M6.5 35c0-7.2 6-11.5 13.5-11.5S33.5 27.8 33.5 35z" fill="currentColor"/>
|
||
</svg>
|
||
<img id="meAvatarImg" alt="">
|
||
<i class="av-edit" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24" width="11" height="11">
|
||
<path d="M4 20h16" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/>
|
||
<path d="M15.6 4.4a2.3 2.3 0 0 1 3.3 3.3L9.7 16.9l-4.3 1 1-4.3z" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linejoin="round"/>
|
||
</svg>
|
||
</i>
|
||
</div>
|
||
<div class="me-info">
|
||
<div class="me-name" id="meName">未登录</div>
|
||
<!-- ⚠️ 这里先后住过两样东西,两样都已经删了,别再往回搬:
|
||
① 最早是「孕 24 周 +3 天 · 预产期 12月22日」,由 syncPregnancy() 刷。
|
||
删它是因为**重复**:往下滚一屏就是孕期卡,孕周、预产期、
|
||
剩余天数在那儿写得更全。
|
||
② 然后换成了一句话签名 <p class="me-bio" id="meBio">,
|
||
本批按用户要求(「我的资料里的一句话签名可以去掉」)连同
|
||
弹窗里的 #pfBio 输入框、js 里的 syncBio()、state.userBio 一起删。
|
||
⚠️ 必须一起删:只删输入框、留下这行展示,它就成了一句
|
||
谁也改不动的死文案 —— 用户会在资料弹窗里翻来翻去找哪儿能改。
|
||
⚠️ syncPregnancy() 里那行 $('.me-info p') 早就删掉了(它取的是
|
||
**第一个** <p>)。现在第一个 <p> 是下面的「已连续记录」,
|
||
谁要是把那行加回来,会把连续记录天数冲掉,而且是静默的。 -->
|
||
<span class="me-tag hide" id="meTag"></span>
|
||
<p id="meRecordLine">已连续记录 <b>42</b> 天</p>
|
||
<!-- 2026-10-10 用户:未授权时说明「数据还在」,避免误以为记录丢了。用 div 不用 p:别占「第一个 <p>」 -->
|
||
<div class="me-saved" id="meSaved" style="display:none">孕期资料已保存在本微信</div>
|
||
</div>
|
||
<i class="me-chev" aria-hidden="true">›</i>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="page-body no-top">
|
||
<!-- 毛玻璃底下的彩色光斑(2026-10-04 用户:「卡片毛玻璃一点,现在白底平铺不好看」)。
|
||
卡片是半透明 + backdrop-filter,必须垫点颜色才透得出玻璃感;纯 CSS,不加图片请求。 -->
|
||
<i class="me-orbs" aria-hidden="true"><b class="o1"></b><b class="o2"></b><b class="o3"></b><b class="o4"></b></i>
|
||
<!-- 退出登录已移到个人资料卡右上角的图标按钮(#meLogoutBtn) -->
|
||
<!-- ⚠️ 这两处的 data-modal 从 modalPreg 改成了 modalProfile:
|
||
「编辑孕期信息」那张弹窗已整个并进「我的资料」(见文件末尾那段说明)。
|
||
小名 / 性别 / 预产期现在只有一处能改,改完照样 syncPregnancy() 回刷这张卡。 -->
|
||
<!-- ⚠️ 「(必填)」是独立的 <span class="sec-req">,**不能**塞进 .sec-more 那颗按钮里 ——
|
||
.sec-more 是「编辑 ›」的可点区域,把「必填」并进去等于扩大了热区,
|
||
用户想读一眼提示、结果弹出了编辑窗。它也不能只是写进标题文本里:
|
||
要单独一个元素才能上品牌色。
|
||
⚠️ 用品牌色不用灰:「必填」是一句**要求**,写成灰小字就退成了附注,没人会去填。
|
||
宽度账(.page-body 左右各 18 → 可用 284,.sec-title 是 flex、gap 8):
|
||
竖条 4 + 8 + 「孕期信息」4×17.5=70 + 8 + 「(必填)」4×12=48 + 8 + 「编辑 ›」≈34
|
||
= 180 ≤ 284 ✓,余 104px,宽裕。 -->
|
||
<!-- 2026-10-01:按用户要求孕期卡和兜豆卡对调 —— 孕期卡现在半压在头部底边上,所以去掉了上方的
|
||
「孕期信息(必填)· 编辑 ›」标题行(标题压在渐变上很乱);整卡本身就点开资料弹窗,
|
||
「必填」挪进弹窗里那张「孕期信息」卡的角标。 -->
|
||
<button class="preg-card ripple" data-modal="modalProfile">
|
||
<div class="pc-row">
|
||
<!-- 孕周进度环 + 蜷着的宝宝。
|
||
上一版是一个细线条的孕妇侧影:笔画太细、那条「腿」像根多余的杂线,
|
||
肚子里那颗浅色小点在 52px 上几乎看不见,凑近才认得出画的是什么。
|
||
换掉的理由不只是好看 —— 这张卡讲的就是「走到哪儿了」
|
||
(孕 24 周 +3 天 / 还有 110 天 / 一条进度条 / 早中晚期三段),
|
||
所以图标本身就画成一圈进度:外圈是整个孕期,实心那段是已经走过的,
|
||
中间蜷着的是宝宝。图标和卡片说的是同一件事。
|
||
⚠️ 这一圈是**活的**:syncPregnancy() 按真实孕周重写 #pcRing 的
|
||
stroke-dasharray,和下面那条 .pc-bar 同源(同一个 pct)。
|
||
这里写死的 "45 73" 只是 JS 跑起来之前的占位(≈62%,对应 r=11.6
|
||
的周长 72.9),不是设计值 —— 要改进度去改 syncPregnancy,别调这里。
|
||
⚠️ 下面这几处颜色跟着 .preg-card 的配色走
|
||
(橘 → 雾蓝 → 紫粉 → 现在的深紫渐变 + 白)。
|
||
它们是 SVG presentation attribute,不在 style.css 里,
|
||
改配色时最容易漏掉的就是这一块 —— 上一版深紫 #7B5BD6 在这儿出现
|
||
**三次**(进度环 stroke、宝宝头 fill、身子 stroke),
|
||
只改第一处就会得到「紫环配蓝宝宝」。
|
||
⚠️ 卡片现在是深底,整个图标就是**一色白**,上面那个「三处」的坑
|
||
因此暂时看不出来了 —— 但它随时会回来:下次谁把配色改回浅底,
|
||
就得重新给这三处各挑一个深色。smoke 里钉着「图标里所有颜色一致」,
|
||
漏改一处就会红。
|
||
⚠️ 底环用 stroke-opacity 调暗,**不能**和进度环一样是实白 ——
|
||
两圈一样白就等于没有进度环,那一圈永远看着是满的。
|
||
用 stroke-opacity 而不是 rgba():presentation attribute 里
|
||
rgba 各家浏览器支持不一,stroke-opacity 是 SVG 1.1 的正经属性。 -->
|
||
<div class="pc-ico">
|
||
<svg viewBox="0 0 32 32" width="27" height="27" aria-hidden="true">
|
||
<circle cx="16" cy="16" r="11.6" fill="none" stroke="#F0704F" stroke-opacity=".3" stroke-width="3.2"/>
|
||
<circle id="pcRing" cx="16" cy="16" r="11.6" fill="none" stroke="#F0704F" stroke-width="3.2"
|
||
stroke-linecap="round" stroke-dasharray="45 73" transform="rotate(-90 16 16)"/>
|
||
<circle cx="17" cy="12.9" r="3.2" fill="#F0704F"/>
|
||
<path d="M13.8 17.2c.3 3.6 3 5.1 6 4.1" fill="none" stroke="#F0704F" stroke-width="3.4" stroke-linecap="round"/>
|
||
</svg>
|
||
</div>
|
||
<div class="pc-main"><div class="pc-title" id="pcTitle">孕 24 周 +3 天</div><div class="pc-sub" id="pcSub">预产期 2024年12月22日 · 还有 110 天</div></div>
|
||
<i class="chev">›</i>
|
||
</div>
|
||
<div class="pc-bar"><i id="pcBar" style="--p:60%"></i></div>
|
||
<div class="pc-stage"><span>孕早期</span><span class="cur" id="pcStage">孕中期 · 当前</span><span>孕晚期</span></div>
|
||
</button>
|
||
|
||
<!-- 兜豆兑换商城主卡(2026-10-01):半压在头部渐变边缘,是「我的」页最跳的一张。
|
||
点击走 openExchange()(app.js)—— 链接优先取应用后台,取不到再用写死的兜底地址。
|
||
#meExchSub 未登录写「攒兜豆,好物免费兑」,拿到余额后改成「兜豆 N · 可兑 M 件」(loadDou())。 -->
|
||
<!-- 授权完善资料:H5 → navigateTo → 小程序授权页(头像/昵称/手机号) → box_app /auth/profile 落库 -->
|
||
<div class="list-card" style="margin-top:14px" id="meAuthBox">
|
||
<button class="li ripple" id="meAuthCard">
|
||
<span class="li-ico o"><svg viewBox="0 0 24 24" width="19" height="19" aria-hidden="true"><rect x="5" y="10.5" width="14" height="9.5" rx="2.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M8.5 10.5V8a3.5 3.5 0 0 1 7 0v2.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path d="M12 15v2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></span>
|
||
<span class="li-t">授权完善资料</span>
|
||
<span class="li-v">获取手机号 / 昵称 / 头像</span>
|
||
<i class="chev">›</i>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 兜豆兑换:2026-10-04 用户要求「收起来,不要这么大地展示」—— 原来的大卡(标题+热门 3 件好物)收成一条横条,
|
||
和下面「兜爸心选商城」同款。#meExchCard / #meExchSub 不变(openExchange、loadDou 照旧);
|
||
#meExchDrop 已删,renderDrop() 里有 if (box) 判空,不用改 JS。 -->
|
||
<button class="mall-strip exch ripple" id="meExchCard">
|
||
<span class="ms-ico" aria-hidden="true"><img src="assets/img/dou-coin.svg?v=20261002" width="28" height="28" alt=""></span>
|
||
<span class="ms-main"><b>兜豆兑换</b><span id="meExchSub">攒兜豆,好物免费兑</span></span>
|
||
<!-- 2026-10-11 用户:兜豆余额要明显,不放副标题小字 → 右侧大号数字;拿到余额前 / 访客显示「去兑换」 -->
|
||
<span class="ms-bal hide" id="meDouBal"><b id="meDouN">0</b><small>兜豆</small></span>
|
||
<span class="ms-go" id="meExchGo">去兑换<i>›</i></span>
|
||
</button>
|
||
|
||
|
||
|
||
|
||
<!-- ================= 孕育顾问(企业微信入口) =================
|
||
常驻在孕期卡下面:上面那张卡讲「你走到哪儿了」,这张接着说
|
||
「路上有人陪你」,是同一段话的下一句;而「设置与服务」那组是
|
||
工具箱,把一个真人服务塞进去会被当成一行设置项划过去。
|
||
⚠️ 故意**不挂 data-modal="modalWx"**。那条通用通道直接调 openModal,
|
||
会绕过 openWx() —— 弹窗的模式类名、引导语、上次残留的红字和
|
||
输入内容、还有 wxPending 全都不会被重置。这里必须走 JS 那条路。
|
||
⚠️ 这张卡历史上**不随解锁状态隐藏**(资源库顶部那条 banner 会),
|
||
定位是「我的」页的常驻入口。本批(第九批)按用户要求把整块
|
||
「专属福利」先隐藏 —— 见下面 #meWelfareHidden 那段注释;
|
||
上面这条「常驻」的旧约定随之暂停,恢复时把该容器的 display:none 去掉即可。 -->
|
||
<!-- ⚠️ 本批(第九批)按用户要求**先隐藏**「专属福利」整块(标题 + 孕育顾问卡)。
|
||
用外层容器 display:none 而不是删 DOM,原因有二:
|
||
① #meWxCard 的点击绑定(app.js openWx('gift'))、syncBabyWords() 对
|
||
#meWxTitle/#meWxSub 的写入都还引用它们,删了会当场报错;
|
||
② 保留 DOM 便于随时一键恢复(去掉这里的 display:none 即可)。
|
||
⚠️ 隐藏的只是这一块。下面「甄选好物 / 进入商城」(#meMallCard)**不动** ——
|
||
它是另一张卡,用户没要求藏。
|
||
⚠️ 资源库顶部那条 #rlGift banner 不在这一块里,本次未动。 -->
|
||
<div id="meWelfareHidden" style="display:none">
|
||
<h2 class="sec-title dark">专属福利</h2>
|
||
<button class="wx-card ripple" id="meWxCard">
|
||
<!-- ⚠️ 这一版是**三段竖排**:角标行 / 图文行 / 通栏 CTA。
|
||
上一版是四段(角标 / 标题 / 图文 / CTA),本批按用户要求
|
||
「商品名放到到手价上边、跟到手价对齐」,把整个标题行搬进了右列
|
||
.wx-main —— 商品名和价格从此共用同一条左缘,这就是「对齐」的实现。
|
||
同时「每人领取一份放到商品名右边、左边整个位置留给图片」。
|
||
|
||
卡内净宽 = 320 − 页边 36 − 卡内边 36 = **248px**(下面所有账都对着它)
|
||
|
||
① 图文行:.wx-fig 76 + gap 12 → 右列 .wx-main = 248 − 76 − 12 = **160px**
|
||
|
||
② 标题行(住在 160px 的右列里;本批起两件**竖排**,各占一整行):
|
||
「可心柔婴儿纸巾」7 字 × 16 = 112 ≤ 160 ✓ 余 48px
|
||
「限领一份」 4 字 × 11.5 = 46 ≤ 160 ✓ 余 114px
|
||
⚠️ 上一版是横排:105 + gap 5 + 42 = 152 ≤ 160,**只余 8px**,
|
||
而且那 8px 是按 15px 字号死算的。微信有一个全局字体大小
|
||
滑块,用户一调大,105px 的商品名当场涨到 130+,余量瞬间
|
||
蒸发、ellipsis 真的触发 —— 商品名被啃成「可心柔婴儿纸…」。
|
||
**这就是用户本批报的那个 bug**(原话「把限领一份儿放到
|
||
可心柔婴儿纸巾的后边」,追问后确认他看到的是被切断的商品名)。
|
||
⚠️ 竖排把「两件抢同一条 160px」这个根子问题去掉了,不是把
|
||
临界点往后推。所以字号也一并回到 16 / 11.5,不再需要压字号。
|
||
**别为了省一行高度改回横排。**
|
||
|
||
③ 右列其余两行(都在 160px 里):
|
||
「到手价 ¥0」= 3×11.5 + gap 5 + ¥0 ≈ 26 → 65.5 ✓
|
||
副文「加小汤圆的孕育顾问领取」11 × 12.5 = 137.5 ✓ 一行;
|
||
小名满 12 字时 20 字 = 250 → 折两行,line-clamp:2 兜住
|
||
|
||
④ 高度账 —— 这就是「左边整个的位置都留给图片」:
|
||
.wx-main 高 = 19.5(head) + 5 + 26(price) + 5 + 18.1(sub 一行) ≈ 73.6
|
||
sub 折两行时 ≈ 91.8
|
||
所以 .wx-fig **不写死高度**,用 align-self:stretch + min-height:92 ——
|
||
图片永远填满左列整个高度:短文案时由 92 撑住卡高,
|
||
长小名把右列顶到 91.8 时也不会被超过。
|
||
|
||
⑤ CTA 通栏 248px。 -->
|
||
|
||
<!-- 角标行:只有一枚角标,右对齐 = 卡的右上角。
|
||
⚠️ 这一行**故意是空的**,只装角标。看着浪费了 18px 高,但角标并回
|
||
别处必然挤爆某一行,而挤爆的表现是商品名被省略号啃掉。
|
||
⚠️ 角标**仍然是正常流里的一枚标签**,绝不能改回 position:absolute
|
||
骑在卡边上:.wx-card 挂着 .ripple,overflow:hidden 会把它裁掉半截。
|
||
那正是用户早先说的「限量福利被切了」,已经犯过一次,别再犯。 -->
|
||
<span class="wx-top">
|
||
<!-- ⚠️ 文案「限量福利」是刻意避开「免费领」的:下面 CTA 已经写了
|
||
「立即免费领取」,角标再写一遍「免费领」是同一张卡里重复吆喝。 -->
|
||
<span class="wx-badge">限量福利</span>
|
||
</span>
|
||
|
||
<span class="wx-body">
|
||
<!-- 左边这块是**商品占位插画**(一包抽纸),不是最终图。
|
||
⚠️ 类名是 .wx-fig,**绝不能**叫 .wx-qr —— 那个类是弹窗里的
|
||
企业微信二维码,测试里有一条「全页只有一处二维码」的断言,
|
||
蹭上去会当场红。
|
||
⚠️ 「示例图 · 待替换」这行字画在 svg **内部**,换成真实商品图时
|
||
它跟着一起消失,不会留下一行孤零零的说明。
|
||
⚠️ svg 的 width/height 从写死的 88 改成了 100%:现在框是
|
||
76 宽 × 拉伸高,写死 88 会顶出去。换真图时也照此办理。
|
||
⚠️ 里面是**内联 svg**,object-fit 对它**不生效** —— 生效的是
|
||
preserveAspectRatio(默认 xMidYMid meet = contain)。
|
||
64×64 的方图放进 76×92 的框会上下各留 8px 空条,
|
||
露出卡的橙色渐变;.wx-fig 的 background:#FFF1E6 就是来堵这个的
|
||
(取的是下面那张 <rect> 自己的颜色,所以看不出接缝)。
|
||
别改成 slice(cover)—— 那会把抽纸盒裁掉头尾。 -->
|
||
<span class="wx-fig" aria-hidden="true">
|
||
<svg viewBox="0 0 64 64" width="100%" height="100%">
|
||
<rect x="2" y="2" width="60" height="60" rx="14" fill="#FFF1E6"/>
|
||
<!-- 抽纸软包 -->
|
||
<path d="M17 22h30v26a3 3 0 0 1-3 3H20a3 3 0 0 1-3-3V22z" fill="#fff" stroke="#E8A98C" stroke-width="1.6" stroke-linejoin="round"/>
|
||
<path d="M17 22c0-3.6 3-6.4 7-6.4h16c4 0 7 2.8 7 6.4" fill="#FFE1D2" stroke="#E8A98C" stroke-width="1.6" stroke-linejoin="round"/>
|
||
<!-- 抽出来的那一张 -->
|
||
<path d="M27.5 22c0-2.6 2-4.6 4.5-4.6s4.5 2 4.5 4.6" fill="none" stroke="#D85F38" stroke-width="1.8" stroke-linecap="round"/>
|
||
<path d="M23 33h18M23 39h13" stroke="#F2C7B3" stroke-width="1.8" stroke-linecap="round"/>
|
||
<text x="32" y="59.5" text-anchor="middle" font-size="6.4" fill="#B79C90">示例图 · 待替换</text>
|
||
</svg>
|
||
</span>
|
||
<span class="wx-main">
|
||
<!-- 标题行:商品名独占一行,「限领一份」排在它**下面**。
|
||
⚠️⚠️ 本批(第八批)把这两件从横排改成竖排,方向和上一批**相反**。
|
||
上一批是「限领在商品名右侧」,可右列只有 160px,两件抢同一条宽度,
|
||
当时那笔账只余 8px —— 于是商品名被省略号啃成「可心柔婴儿纸…」。
|
||
用户这次报的就是这个现象(原话「把限领一份儿放到可心柔婴儿纸巾的
|
||
后边」,问过之后确认他看到的是被切断的商品名)。
|
||
竖排之后标题独占整行 160px,7 字 × 16 = 112,宽度争抢从根上消失。
|
||
⚠️ 别为了「省一行高度」改回 flex-direction:row —— 那等于把这个
|
||
bug 原样装回来,而且它在短商品名下不复现,测不出来。
|
||
⚠️ .wx-head 仍必须是 .wx-main 的**第一件**、排在 .wx-price 前面 ——
|
||
用户早先的原话是「商品名放到到手价上边」,两批要求叠加在一起。
|
||
⚠️ 别把「限领一份」合回 .wx-title 凑成一个字符串:合成一个字符串
|
||
就只剩一个字号,「限领」不再是商品名底下那行灰色小字,
|
||
用户要的那个视觉层级整个没了。 -->
|
||
<span class="wx-head">
|
||
<span class="wx-title" id="meWxTitle">可心柔婴儿纸巾</span>
|
||
<!-- ⚠️ 文案「限领一份」和资源库 banner 的 .rlg-lim **必须逐字相同**
|
||
(用户早先要求两张卡「一模一样」,smoke 里有一条断言钉着)。
|
||
改这句就得同时改 .rlg-lim,只改一边会当场红。
|
||
⚠️ 「(每人限领一份)」砍成「限领一份」是**第七批**被 8px 余量逼的
|
||
(那时它和商品名横排、抢同一条 160px)。第八批改竖排之后
|
||
它独占整行,8 字 × 11.5 = 92 ≤ 160,其实又放得下了。
|
||
仍然保持 4 字,理由换成「用户没要求改字」+ 两张卡必须逐字相同。
|
||
别拿「现在放得下」当作可以随手改回长文案的依据。 -->
|
||
<span class="wx-lim">限领一份</span>
|
||
</span>
|
||
<!-- 价格行 —— 这一版「电商化」的主角。
|
||
⚠️ 这里**只写到手价,不写划掉的原价**。原价是编出来的数字,
|
||
而这是一个真实品牌的真实商品:划线价属于价格宣称,
|
||
编一个就成了虚假标价。「¥0」不是新承诺,它就是这张卡
|
||
从第一版起一直写着的「立即免费领取」换个说法 ——
|
||
同一件事用电商的排版语言再说一遍,没有多承诺任何东西。
|
||
⚠️ 「免费领」这个商务承诺本身仍未获确认(第四批提出,见 CHANGELOG
|
||
的「已知不做」)。要撤这个承诺的话,撤的是整张卡,不是这一行。 -->
|
||
<span class="wx-price"><i>到手价</i><b>¥0</b></span>
|
||
<!-- 静态兜底写「宝宝的」,不写「小汤圆」:用户还没填小名时,
|
||
屏幕上不该出现一个他从没输入过的名字。填了之后
|
||
syncBabyWords() 会把这里换掉。
|
||
⚠️ 小名的挂点在这一行,不在上面的标题里,也不在下面的 CTA 里。
|
||
改 syncBabyWords() 时别找错行。 -->
|
||
<span class="wx-sub" id="meWxSub">加宝宝的孕育顾问领取</span>
|
||
</span>
|
||
</span>
|
||
|
||
<!-- CTA 现在是**通栏**的(上一版只占右列 159px)。整卡 248px 的实心按钮
|
||
是电商卡的标准收尾,也是这张卡唯一的动作。
|
||
⚠️ 必须是 <span> 不能是 <button>:外层 .wx-card 本身就是
|
||
<button>,按钮套按钮是非法 HTML。 -->
|
||
<span class="wx-cta">立即免费领取</span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- 心选商城:改成一条横幅(原来是带大按钮的电商卡,和上面的兑换卡抢主角)。id/点击逻辑不变(goMall)。 -->
|
||
<button class="mall-strip ripple" id="meMallCard">
|
||
<span class="ms-ico" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M5 8h14l-1.2 11a2 2 0 0 1-2 1.8H8.2a2 2 0 0 1-2-1.8z" fill="#fff" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/><path d="M8.6 10V6.8a3.4 3.4 0 0 1 6.8 0V10" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg>
|
||
</span>
|
||
<span class="ms-main"><b>兜爸心选商城</b><span>为宝宝甄选的母婴好物</span></span>
|
||
<span class="ms-go">逛一逛<i>›</i></span>
|
||
</button>
|
||
|
||
<h2 class="sec-title dark">常用服务</h2>
|
||
<!-- 设置与服务:列表改成四宫格。按钮的 id / data-open / data-set 全部沿用,JS 不用动。
|
||
#meBoxCard 2026-10-05 起一律隐藏(用户要求删掉孕期卡册入口,见 app.js renderBanner);#meBoxV 显示成右上角小角标。 -->
|
||
<div class="svc-grid">
|
||
<button class="svc ripple hide" id="meBoxCard"><span class="sv-ico o"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><rect x="4.5" y="10.5" width="15" height="9.5" rx="2" fill="none" stroke="currentColor" stroke-width="1.8"/><rect x="3.3" y="7.2" width="17.4" height="3.6" rx="1.3" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M12 7.2V20M12 7.2C10.4 3.8 7 4.3 8 6.4c.6 1 2.4.9 4 .8zM12 7.2c1.6-3.4 5-2.9 4-.8-.6 1-2.4.9-4 .8z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linejoin="round"/></svg></span><span class="sv-t">孕期卡册</span><span class="sv-badge" id="meBoxV"></span></button>
|
||
<button class="svc ripple" data-open="detailSetting" data-set="privacy"><span class="sv-ico p"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><rect x="4.5" y="10" width="15" height="10.5" rx="3" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M8.2 10V7.6a3.8 3.8 0 0 1 7.6 0V10" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><circle cx="12" cy="15.2" r="1.5" fill="currentColor"/></svg></span><span class="sv-t">隐私权限</span></button>
|
||
<button class="svc ripple" data-open="detailSetting" data-set="help"><span class="sv-ico o"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><path d="M12 4.2c4.5 0 7.8 2.8 7.8 6.4s-3.3 6.4-7.8 6.4c-.7 0-1.3-.06-1.9-.18l-3.6 2.3a.4.4 0 0 1-.6-.45l.8-2.9c-1.5-1.16-2.3-2.7-2.3-4.4 0-3.6 3.1-6.4 7.6-6.4z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M9.9 9.4a2.2 2.2 0 0 1 4.2.8c0 1.5-2.1 1.6-2.1 3" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"/></svg></span><span class="sv-t">帮助反馈</span></button>
|
||
<!-- 2026-10-04 意见反馈(用户:「我的页面里加一个客服反馈,功能上的反馈、功能上的建议」)→ #modalFeedback,提交到 box_app /api/mp/public/mama-box/feedback -->
|
||
<!-- 2026-10-05 用户:「『我的』里加一个兑换记录,就是商城兑换的记录」→ 跳兜豆兑换商城 ?page=orders(商城会话 cc4ca879 提供,直接弹「兑换记录」,× 回首页);
|
||
#meOrdersV 角标 = 待发货笔数(/api/dou/summary 的 orders_pending,0 不显示)。 -->
|
||
<button class="svc ripple" id="meExchOrders"><span class="sv-ico o"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><path d="M6.5 3.8h11a1.2 1.2 0 0 1 1.2 1.2v15.1l-2.3-1.5-2.2 1.5-2.2-1.5-2.2 1.5-2.2-1.5-2.3 1.5V5a1.2 1.2 0 0 1 1.2-1.2z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M8.6 8.6h6.8M8.6 12h6.8M8.6 15.4h4" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></span><span class="sv-t">兑换记录</span><span class="sv-badge" id="meOrdersV"></span></button>
|
||
<button class="svc ripple" id="meFeedback"><span class="sv-ico g"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><path d="M5.5 4.8h13a1.7 1.7 0 0 1 1.7 1.7v8.6a1.7 1.7 0 0 1-1.7 1.7H11l-4.1 3a.4.4 0 0 1-.64-.32V16.8H5.5a1.7 1.7 0 0 1-1.7-1.7V6.5a1.7 1.7 0 0 1 1.7-1.7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/><path d="M8.2 9.3h7.6M8.2 12.5h4.8" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></span><span class="sv-t">意见反馈</span></button>
|
||
<button class="svc ripple" data-open="detailSetting" data-set="about"><span class="sv-ico b"><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><circle cx="12" cy="12" r="8.2" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M12 11v5.4" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"/><circle cx="12" cy="7.9" r="1.15" fill="currentColor"/></svg></span><span class="sv-t">关于我们</span></button>
|
||
</div>
|
||
<!-- 退出授权登录:仅已授权时显示(applyRemoteProfile 控制 style.display)。
|
||
调 box_app /auth/logout —— 只翻授权状态,不清昵称/头像/手机号等资料 -->
|
||
<button class="me-logout ripple" id="meLogoutCard" style="display:none">退出登录</button>
|
||
<p class="me-ver">兜爸心选</p>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
|
||
|
||
<!-- ================= 孕期小知识 · 这一周 详情页(2026-10-01)=================
|
||
首页 #pregTips 下面四个入口点进来:宝宝 / 妈妈 / 饮食 / 留心 四张卡竖排、全文不截断;
|
||
点哪个入口就滚到哪张并闪一下。内容由 renderTips() 写入 ptBaby/ptMom/ptEat/ptCare。 -->
|
||
<section class="detail" id="detailTips">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title" id="ptDtTitle">孕期小知识</span>
|
||
</div>
|
||
<div class="detail-body pt-page">
|
||
<!-- 本周每日小知识:第 1 天到今天,今天在最上面;以后的几天锁着(与首页 7 个圆点同一口径) -->
|
||
<h3 class="pt-sub">本周每日小知识</h3>
|
||
<div class="pt-list" id="ptList"></div>
|
||
<h3 class="pt-sub">这一周</h3>
|
||
<div class="pt-grid" id="ptGrid">
|
||
<div class="pt-card pc-baby" data-pt="baby"><span class="pt-ico" id="ptBabyIco" aria-hidden="true">👶</span><b>宝宝这周</b><p id="ptBaby"></p></div>
|
||
<div class="pt-card pc-mom" data-pt="mom"><span class="pt-ico" aria-hidden="true">🤰</span><b>妈妈身体</b><p id="ptMom"></p></div>
|
||
<div class="pt-card pc-eat" data-pt="eat"><span class="pt-ico" aria-hidden="true">🥗</span><b>吃点什么</b><p id="ptEat"></p></div>
|
||
<div class="pt-card pc-care" data-pt="care"><span class="pt-ico" aria-hidden="true">📋</span><b>这周留心</b><p id="ptCare"></p></div>
|
||
</div>
|
||
<p class="pt-foot">仅供参考,身体有任何不适请以医生意见为准</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 其他妈妈也在搜 · 全部问题(2026-10-31)=================
|
||
首页 #pregTips 只露 6 条,其余在这里:取 assets/data/qa/hot.json(24 条,前 6 条是首页那 6 个),
|
||
分类筛选 + 点开看答案;从首页点某一条进来,自动展开并滚到那一条。渲染在 app.js openQA()。 -->
|
||
<section class="detail" id="detailQA">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title" id="qaTitle">其他妈妈也在搜</span>
|
||
</div>
|
||
<div class="detail-body qa-page">
|
||
<div class="qa-hero">
|
||
<b id="qaHeroT">这周孕妈都在问</b>
|
||
<span id="qaHeroD"></span>
|
||
</div>
|
||
<div class="qa-cats" id="qaCats" role="tablist"></div>
|
||
<a class="qa-topic hide" id="qaTopic" href="topic/wen/">
|
||
<img src="topic/wen/img/hero.webp" alt="" loading="lazy">
|
||
<span><em>孕期专题</em><b>妊娠纹怎么防?现在该抹什么</b></span><i>›</i>
|
||
</a>
|
||
<div class="qa-list" id="qaList"></div>
|
||
<button type="button" class="qa-more" id="qaTips">看看本周每日小知识 ›</button>
|
||
<p class="pt-foot">仅供参考,身体有任何不适请以医生意见为准</p>
|
||
</div>
|
||
<style>
|
||
.qa-page{padding:6px 16px 40px}
|
||
.qa-hero{display:flex;flex-direction:column;gap:3px;margin:6px 2px 12px}
|
||
.qa-hero b{font-size:20px;font-weight:900;color:#2A1E1E}
|
||
.qa-hero span{font-size:12.5px;color:#7A6663}
|
||
.qa-cats{display:flex;gap:8px;overflow-x:auto;padding:2px 2px 10px;margin:0 -16px;padding-left:18px;padding-right:18px;scrollbar-width:none}
|
||
.qa-cats::-webkit-scrollbar{display:none}
|
||
.qa-cat{flex:none;padding:5px 12px;border-radius:99px;border:1px solid #F1DDD6;background:#fff;font:inherit;font-size:13px;color:#5E4B48}
|
||
.qa-cat small{margin-left:3px;font-size:11px;color:#A8938F}
|
||
.qa-cat.on{background:#F4593C;border-color:#F4593C;color:#fff;font-weight:700}
|
||
.qa-cat.on small{color:rgba(255,255,255,.8)}
|
||
.qa-topic{display:flex;align-items:center;gap:12px;margin:4px 0 10px;padding:8px 12px 8px 8px;border-radius:16px;background:linear-gradient(110deg,#FFEDE6,#FFF8F4);text-decoration:none;color:inherit}
|
||
.qa-topic.hide{display:none}
|
||
.qa-topic img{flex:none;width:54px;height:54px;border-radius:12px;object-fit:cover}
|
||
.qa-topic span{flex:1;display:flex;flex-direction:column;gap:2px;min-width:0}
|
||
.qa-topic em{font-style:normal;font-size:11px;color:#F4593C;font-weight:700}
|
||
.qa-topic b{font-size:14.5px;color:#2F2424}
|
||
.qa-topic i{font-style:normal;font-size:20px;color:#E4A595}
|
||
.qa-list{display:flex;flex-direction:column;gap:8px}
|
||
.qa-it{border-radius:16px;background:#fff;box-shadow:0 2px 8px rgba(190,120,100,.07);overflow:hidden}
|
||
.qa-it.hide{display:none}
|
||
.qa-q{display:flex;align-items:center;gap:10px;width:100%;padding:13px 12px;border:0;background:none;font:inherit;color:inherit;text-align:left}
|
||
.qa-no{flex:none;width:20px;font-size:15px;font-weight:900;font-style:italic;color:#C9B4AF;text-align:center}
|
||
.qa-it.top .qa-no{color:#F2533A}
|
||
.qa-tx{flex:1;min-width:0;font-size:15px;line-height:1.45;font-weight:600;color:#2F2424}
|
||
.qa-tag{flex:none;padding:0 6px;border-radius:6px;font-size:10.5px;line-height:17px;font-weight:700;background:#F6EEEB;color:#8A7471}
|
||
.qa-tag.hot{background:#FFE4DE;color:#E8492F}
|
||
.qa-ch{flex:none;font-style:normal;font-size:16px;color:#D9C2BC;transition:transform .2s}
|
||
.qa-it.open .qa-ch{transform:rotate(90deg)}
|
||
.qa-a{display:none;margin:0 12px 13px 42px;padding:10px 12px;border-radius:12px;background:#FFF6F2;font-size:14px;line-height:1.75;color:#4A3B39}
|
||
.qa-it.open .qa-a{display:block}
|
||
.qa-it.hit{animation:qaHit 1.2s ease}
|
||
@keyframes qaHit{0%,40%{box-shadow:0 0 0 2px #F4593C}100%{box-shadow:0 2px 8px rgba(190,120,100,.07)}}
|
||
.qa-more{display:block;margin:16px auto 4px;padding:8px 16px;border-radius:99px;border:1px solid #F1DDD6;background:#fff;font:inherit;font-size:13px;color:#E0573A}
|
||
html.night .qa-hero b,html.night .qa-tx,html.night .qa-topic b{color:#F1E6EE}
|
||
html.night .qa-it,html.night .qa-cat,html.night .qa-more{background:#2F2737;border-color:rgba(255,255,255,.1);box-shadow:none}
|
||
html.night .qa-a{background:rgba(255,255,255,.06);color:#E3D6DE}
|
||
html.night .qa-topic{background:linear-gradient(110deg,#3a2a2a,#2c2222)}
|
||
</style>
|
||
</section>
|
||
|
||
<!-- ================= AI 小结 内容页 ================= -->
|
||
<section class="detail" id="detailAI">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title">AI 孕育小结</span>
|
||
<button class="dt-plain" data-toast="小结每天 21:00 自动生成">⋯</button>
|
||
</div>
|
||
<!-- 这一页原来是「大卡 + 三条 li + 一串行」,从上到下全是罗列,没有层次。
|
||
重做成三段式:今日卡(深色,一眼看完今天)→ 三张建议卡(分类色 + 一句标题
|
||
一句正文)→ 往期时间轴(左边一条线串起来)。每段之间用带序号的小标题隔开。 -->
|
||
<div class="detail-body ai-body">
|
||
<!-- ① 今日卡:整页唯一的深色块,越往下越浅,视线自然从这里开始 -->
|
||
<section class="ai-today">
|
||
<span class="ai-glow" aria-hidden="true"></span>
|
||
<span class="ai-glow b" aria-hidden="true"></span>
|
||
<div class="ai-t-top">
|
||
<span class="ai-week" id="aiWeek">孕24周+3</span>
|
||
<span class="ai-date" id="aiDate">9月3日 周二</span>
|
||
</div>
|
||
<!-- 一句话概括今天,字号最大;右上角那枚小圆点是「今日状态」 -->
|
||
<span class="ai-mood" id="aiMood">安心</span>
|
||
<!-- renderAI() 会用 AI_LOGS[0].txt 覆盖这句,这里写的是渲染前的兜底。
|
||
口吻同样是宝宝第一人称,别让它在渲染前闪一句第三人称的旧话 -->
|
||
<p class="ai-hero-txt" id="aiTxt">妈妈,今天你数到我动了 3 次。我今天精神特别好,这是踏实的一天。</p>
|
||
<div class="ai-stats" id="aiStats"></div>
|
||
</section>
|
||
|
||
<div class="ai-sec">
|
||
<span class="ai-sec-n">01</span>
|
||
<!-- 原来叫「今天想对你说」。这三张卡的内容是「固定这两个时段陪他待一会儿」
|
||
「按平时胃口来就行」这类可执行的动作,是建议不是抒情,标题得对上 -->
|
||
<h3>今日小建议</h3>
|
||
<i class="ai-sec-line"></i>
|
||
</div>
|
||
<div class="ai-tips" id="aiTips"></div>
|
||
|
||
<div class="ai-sec">
|
||
<span class="ai-sec-n">02</span>
|
||
<h3>往期小结</h3>
|
||
<i class="ai-sec-line"></i>
|
||
<button class="sec-more" data-toast="已加载全部 30 天小结">近 30 天 ›</button>
|
||
</div>
|
||
<div class="ai-logs" id="aiLogs"></div>
|
||
|
||
<p class="unlock">小结由 AI 依据你的记录生成,是陪你一起看记录的伙伴,不代替医生的判断。</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 资源库 列表页 ================= -->
|
||
<section class="detail" id="detailResList">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title">孕育资源库</span>
|
||
<!-- 原来是 🔍 emoji(各系统渲染成实物放大镜),换成和档案页一致的扁平线性图标 -->
|
||
<button class="dt-plain" data-search="1" aria-label="搜索"><svg viewBox="0 0 24 24" width="20" height="20"><circle cx="11" cy="11" r="6.5" fill="none" stroke="currentColor" stroke-width="1.9"/><path d="M16 16l4.5 4.5" stroke="currentColor" stroke-width="1.9" stroke-linecap="round"/></svg></button>
|
||
</div>
|
||
<div class="detail-body">
|
||
<!-- ================= 试用装福利 banner =================
|
||
排在最前面(在那句 rl-lead 之前):它是这一页最想被看见的东西。
|
||
⚠️ 和服务卡同样的理由,故意**不挂 data-open / data-modal**。
|
||
那条通用通道直接调 openModal,会绕过 openWx() —— 模式类名、
|
||
引导语、上次残留的红字和输入内容、还有 wxPending 都不会被重置。
|
||
⚠️ 里面这张示意图**绝不能带 .wx-qr 类**。冒烟测试有一条钉着
|
||
「全页只有一处二维码」,蹭了那个类名会当场变红 —— 而且它也确实
|
||
不是二维码。用独立的 .rlg-fig。
|
||
⚠️ 2026-09-19:兑换码闸门取消后不再有「已解锁」状态,所以这条 banner
|
||
**恒显示**(原来 syncUnlockCopy() 会按解锁态给它挂 .hide,已删除)。
|
||
换真图:把 .rlg-fig 整个 <svg> 换成一个 img,类名照旧写 rlg-fig,
|
||
CSS 一行不用动(.rlg-fig 同时管 svg 和 img)。
|
||
⚠️ 这里**不要**写出图片路径的字面量 —— build.js 的 ASSET_RE
|
||
连 HTML 注释一起扫,写了就当场报「缺少资源文件」。 -->
|
||
<button class="rl-gift ripple" id="rlGift">
|
||
<!-- ⚠️ 这条 banner 和「我的」页那张 .wx-card 是**同一件商品的同一张卡**,
|
||
所以这一版跟着改成同样的三段竖排:标题行 / 图文行 / 通栏 CTA。
|
||
用户上一批的原话是两处「一模一样」;只改一边,同一个商品在两个
|
||
页面上又会长成两个样子 —— 上一版商品名写岔(那边「可心柔试用装」、
|
||
这边「免费领可心柔试用装」)就是这么来的。
|
||
⚠️ 但**比例刻意比那边小一号**(图 68×60 不跟着放大到 88、字号各降一档)。
|
||
这不是偷懒:那边是「我的」页上的一张独立卡,四周是空的;
|
||
这条 banner 上面是标题栏、下面紧跟着 128 条资源列表,
|
||
照搬 88px 的图 + 22px 的价格会把整条撑到 200px 上下,
|
||
把真正的资源列表整个顶到首屏外 —— banner 抢了主内容的位置。
|
||
⚠️ 宽度账(320 屏):320 − 页边 44(.detail-body 左右各 22)
|
||
− 卡内边 28 = 248,和那边一样宽。
|
||
本批标题行改成**竖排**(跟 .wx-card 同步),所以「标题和限领抢
|
||
同一行」那笔账整个不存在了:
|
||
商品名独占一行:「可心柔婴儿纸巾」7 字 × 16 = 112 ≤ 248 ✓ 余 136px
|
||
「限领一份」另起一行:4 字 × 11.5 = 46 ✓
|
||
⚠️ 这边**本来就排得下**(上一版横排是 7×15 + gap 6 + 4×11.5 = 157
|
||
≤ 248,余 91px)。跟着改成竖排纯粹是为了两张卡保持同构 ——
|
||
真正被挤爆的是「我的」页那张:它的右列只有 160px。
|
||
所以别拿「这边明明放得下」当理由把这边改回横排,
|
||
那只会让同一件商品在两个页面上又长成两个样子。 -->
|
||
<span class="rlg-head">
|
||
<!-- 标题和「我的」页 #meWxTitle 保持**同一个字符串**「可心柔婴儿纸巾」。
|
||
测试里有一条拿同一个变量同时比对两处,写岔了会红。
|
||
⚠️ 和 .wx-title 一样:标题只放商品名,不许把括号那半句并进来。
|
||
.rlg-title 是 nowrap + ellipsis,并进来 16 字 ≈ 264px > 248,
|
||
会被省略号从「(」处齐根切掉,而 textContent 照样是全的。 -->
|
||
<span class="rlg-title">可心柔婴儿纸巾</span>
|
||
<!-- ⚠️ 「限领一份」只是文案,前端**不记状态**:真正的把关在顾问
|
||
那边人工做。前端记了也挡不住换设备/清缓存,不假装能管住。
|
||
别看到这行就以为漏了个 localStorage。
|
||
⚠️ 「(每人限领一份)」砍成「限领一份」是**第七批**的事,
|
||
**这边一直排得下** —— 砍它纯粹是为了和「我的」页 .wx-lim
|
||
保持逐字相同(用户早先要求两张卡「一模一样」,smoke 有断言钉着)。
|
||
当时被宽度逼的是那边:标题行横排、右列 160px、余量只剩 8px。
|
||
⚠️ 第八批那边也改成竖排了,8px 那笔账已经不存在,两边**都**放得下。
|
||
仍保持 4 字是因为用户没要求改字,不是因为放不下。
|
||
这两句必须**一起改**,只改一边会当场红。 -->
|
||
<span class="rlg-lim">限领一份</span>
|
||
</span>
|
||
<span class="rlg-body">
|
||
<!-- 「示例图 · 待替换」这几个字写在 svg **内部**:换成真图时它跟着
|
||
一起消失,不会剩一句「待替换」孤零零挂在真图旁边。 -->
|
||
<svg class="rlg-fig" viewBox="0 0 68 60" role="img" aria-label="示例图,待替换为可心柔婴儿纸巾实物图">
|
||
<rect x="6" y="14" width="56" height="34" rx="6" fill="#FFD9C6"/>
|
||
<rect x="6" y="14" width="56" height="12" rx="6" fill="#FFC3A8"/>
|
||
<path d="M20 26c0-5 4-9 9-9h10c5 0 9 4 9 9" fill="none" stroke="#E8724C" stroke-width="2.4"/>
|
||
<path d="M26 33h16M26 39h11" stroke="#E8724C" stroke-width="2.4" stroke-linecap="round"/>
|
||
<text x="34" y="57" text-anchor="middle" font-size="7" fill="#B0907F">示例图 · 待替换</text>
|
||
</svg>
|
||
<span class="rlg-main">
|
||
<!-- ⚠️ 角标从卡外边缘(position:absolute;top:-7px)挪进了右列顶部。
|
||
原因和「我的」页那张卡一样:.rl-gift 挂着 .ripple,
|
||
.ripple 的 overflow:hidden 把负偏移的角标裁掉一半,
|
||
「福利」两个字只露下半截。这是本项目里**最早**的那处裁切。
|
||
别改回绝对定位。 -->
|
||
<span class="rlg-badge">福利</span>
|
||
<!-- 价格行,和「我的」页 .wx-price 同一件事、同样只写到手价。
|
||
⚠️ 一样**不编划线价**:可心柔是真实品牌,划线价属于价格宣称。
|
||
「¥0」只是把这张卡一直写着的「立即免费领取」换个说法。 -->
|
||
<span class="rlg-price"><i>到手价</i><b>¥0</b></span>
|
||
<!-- ⚠️ 这行原来是写死的静态文本,没有小名。用户要求两处「一模一样」,
|
||
所以给了 id 并纳入 syncBabyWords() 一起刷 —— 否则改完小名,
|
||
「我的」页说「加小汤圆的孕育顾问领取」、这里说「加顾问领取」,
|
||
同一句话又变成两个说法。静态兜底同样写「宝宝的」。 -->
|
||
<span class="rlg-sub" id="rlgSub">加宝宝的孕育顾问领取</span>
|
||
</span>
|
||
</span>
|
||
<!-- 实心 CTA,现在是 .rl-gift 的直接子元素、通栏 248px
|
||
(上一版收在右列里只有 170px)。
|
||
原来这里只有一个 .rlg-chev「›」,尖括号在这一页的语义是
|
||
「还有下一层可以翻」,而这条 banner 是要人**领东西**。
|
||
⚠️ 「›」已删除:一张卡上同时摆按钮和尖括号 = 两个「点我」信号打架。
|
||
⚠️ 必须是 <span>:外层 .rl-gift 本身是 <button>,按钮套按钮非法。 -->
|
||
<span class="rlg-cta">立即免费领取</span>
|
||
</button>
|
||
<!-- 静态文案(原「还没解锁 / 已解锁」两版已随闸门一起取消)。
|
||
「首次领取需添加顾问微信」这句必须提前说:让人一路读到底、点了
|
||
「立即领取」才撞上二维码,是把条件藏到最后一步才亮出来。 -->
|
||
<p class="rl-lead"><b>128</b> 份资源按孕周持续更新 · 首次领取需添加顾问微信</p>
|
||
<div class="chips-row" id="resChips">
|
||
<button class="chip is-active" data-rescat="all">全部</button>
|
||
<button class="chip" data-rescat="产检">产检</button>
|
||
<button class="chip" data-rescat="营养">营养</button>
|
||
<button class="chip" data-rescat="胎教">胎教</button>
|
||
<button class="chip" data-rescat="运动">运动</button>
|
||
<button class="chip" data-rescat="心理">心理</button>
|
||
<!-- 收藏不是分类而是筛选,所以默认排在最后。但一旦用户有了收藏,
|
||
renderResList() 会把它挪到「全部」后面并带上数量 —— 常用的东西
|
||
不该让人横向滑到头才找得着。这里写的是「还没收藏过」时的样子。
|
||
⚠️ 原来的「✓ 已领」chip 已删除:9.19 需求取消了「立即领取即到手」
|
||
这个动作(资料由顾问在微信里发),H5 侧没有「已领」这个概念了。 -->
|
||
<button class="chip chip-fav" data-rescat="fav">★ 收藏</button>
|
||
</div>
|
||
<div class="res-list" id="resList"></div>
|
||
<p class="unlock" id="resEmptyHint"></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 资源 内容页 ================= -->
|
||
<section class="detail" id="detailRes">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title">资源详情</span>
|
||
<button class="dt-star" id="resStar">☆</button>
|
||
</div>
|
||
<div class="detail-body">
|
||
<div class="rd-cover" id="rdCover"><img id="rdImg" src="assets/img/9f3fa8edf4aa.png" alt=""></div>
|
||
<span class="rd-cat" id="rdCat">产检</span>
|
||
<h1 class="rd-title" id="rdTitle">《糖耐检查全攻略》</h1>
|
||
<p class="rd-desc" id="rdDesc">孕24-28周必看 · 附检查前饮食清单</p>
|
||
<div class="rd-meta" id="rdMeta"></div>
|
||
<div class="rd-body" id="rdBody"></div>
|
||
<h3 class="d-sec">相关推荐</h3>
|
||
<div class="res-list slim" id="rdMore"></div>
|
||
</div>
|
||
<!-- 其他资源 / 立即领取吸底浮动:移出 .detail-body,怎么滑都跟着。
|
||
左边这颗原来是「★ 收藏」,和右上角星星功能完全重复(它就是转发点击给星星)。
|
||
收藏保留在星星上,这个位置让给「去看看别的」这个真正缺的出口。
|
||
文案用「其他资源」而不是「资源库」:用户此刻就在一份资源里,
|
||
「其他」说的是和手上这份的关系,比页面名更能说清点下去会看到什么。 -->
|
||
<div class="rd-cta" id="rdCta">
|
||
<button class="dl-btn ghost" id="rdLib">其他资源</button>
|
||
<button class="dl-btn main" id="rdGet">立即领取</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 档案图片 预览页 =================
|
||
周档案 / 完整档案共用这一个壳。图是进来时用 canvas 现画的,
|
||
画完顺手存成 data URI —— 「保存图片」直接下载它,
|
||
「分享朋友圈」把它交给系统分享面板(不支持就提示长按图片),
|
||
「打印」走 window.print(),样式表里 @media print 只留这张图。 -->
|
||
<section class="detail" id="detailPoster">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title" id="pstBar">本周档案</span>
|
||
</div>
|
||
<div class="detail-body">
|
||
<!-- 抬头卡:图标 + 档案名 + 一句说明,比孤零零一行灰字有分量 -->
|
||
<div class="pst-hero">
|
||
<span class="pst-ico" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24" width="24" height="24">
|
||
<path d="M7 3.5h7.5L19 8v12.5H7z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
||
<path d="M14 3.5V8h5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
|
||
<path d="M10 12h6M10 15.5h6M10 19h3.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
|
||
</svg>
|
||
</span>
|
||
<div class="pst-h-txt">
|
||
<h2 class="pst-h-title" id="pstName">本周档案</h2>
|
||
<p class="pst-lead" id="pstLead">这一周的记录已经排好版了。</p>
|
||
</div>
|
||
</div>
|
||
<!-- 这张图里都装了什么,用几粒胶囊先交代清楚 -->
|
||
<div class="pst-chips" id="pstChips"></div>
|
||
<!-- 由 JS 往里塞 N 个 .pst-frame(白卡纸 + 一道虚线裁切位,像待打印的样张)。
|
||
本周档案是一张长图,完整档案是一页一张 A4 —— 屏幕上就按纸的样子一张张往下排。
|
||
画布都按 2 倍图给(750 宽),按 375 显示在手机上不糊。 -->
|
||
<div class="pst-pages" id="pstPages"></div>
|
||
<p class="pst-tip" id="pstTip">图片已生成。在微信里也可以长按上面这张图,直接保存或转发。</p>
|
||
</div>
|
||
<div class="rd-cta pst-cta" id="pstCta">
|
||
<!-- data-export 是委托用的:这三颗按钮不逐个绑监听,统一走 app.js 的
|
||
$$('[data-export]') 委托 → exportAct。id 还留着,
|
||
renderPoster() 要按「本周/完整」换这两颗的主次样式。 -->
|
||
<button class="dl-btn ghost" id="pstPrint" data-export="print">打印</button>
|
||
<button class="dl-btn ghost" id="pstSave" data-export="save">保存图片</button>
|
||
<button class="dl-btn main" id="pstShare" data-export="share">分享朋友圈</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 设置与服务 二级页 =================
|
||
隐私与权限 / 帮助与反馈 / 关于兜爸心选 三项共用这一个壳,
|
||
内容由 js 里的 SETTINGS 表渲染进 #stBody,避免写四份几乎一样的结构 -->
|
||
<section class="detail" id="detailSetting">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title" id="stTitle">隐私与权限</span>
|
||
<button class="dt-plain" id="stMore" aria-label="更多">⋯</button>
|
||
</div>
|
||
<div class="detail-body">
|
||
<div id="stHero"></div>
|
||
<p class="st-lead" id="stLead"></p>
|
||
<div id="stBody"></div>
|
||
<p class="unlock" id="stFoot"></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 孕期盲盒(2026-10-01,需求文档 v1.0 第三节) =================
|
||
上半是「开盒舞台」,下半是卡册(按孕早/中/晚期分三组)+ 规则与概率说明(合规:公示每档概率)。
|
||
.bx-reveal 是开盒后的翻卡层,盖在本页之上。全部渲染在 app.js 的 blindBox 段。 -->
|
||
<section class="detail bx" id="detailBox">
|
||
<div class="detail-bar">
|
||
<button class="dt-back" data-detail="close">‹</button>
|
||
<span class="dt-title">孕期盲盒</span>
|
||
<button class="dt-plain bx-rule-btn" id="bxRuleBtn" type="button">规则</button>
|
||
</div>
|
||
<div class="detail-body bx-body">
|
||
<div class="bx-stage" id="bxStage">
|
||
<span class="bx-rays" aria-hidden="true"></span>
|
||
<span class="bx-sp s1" aria-hidden="true">✦</span><span class="bx-sp s2" aria-hidden="true">✦</span><span class="bx-sp s3" aria-hidden="true">✦</span><span class="bx-sp s4" aria-hidden="true">✦</span>
|
||
<div class="bx-week" id="bxWeek"></div>
|
||
<div class="bx-hint" id="bxHint"></div>
|
||
<button class="bx-box" id="bxBox" type="button" aria-label="开启盲盒"></button>
|
||
<button class="bx-mini hide" id="bxMini" type="button" aria-label="查看这张宝宝卡"></button>
|
||
<span class="bx-shadow" aria-hidden="true"></span>
|
||
<button class="bx-open" id="bxOpen" type="button"></button>
|
||
<div class="bx-misc" id="bxMisc"></div>
|
||
</div>
|
||
<!-- 下周预告:下一孕周卡片的剪影 + 倒计时(营造等待感)。本周已开、且还没到 40 周时显示 -->
|
||
<div class="bx-next hide" id="bxNext">
|
||
<div class="bx-next-img" id="bxNextImg" aria-hidden="true"></div>
|
||
<div class="bx-next-t"><b id="bxNextW"></b><span id="bxNextS"></span></div>
|
||
<div class="bx-next-cd"><b id="bxNextD"></b><span>天后开启</span></div>
|
||
</div>
|
||
<!-- 待解锁(2026-10-01 价值感改造):参与之后漏开的周不再白送,完成一个孕期工具任务解锁一周。
|
||
任务是否完成由服务端查数胎动每日足迹核验(GET /blindbox 的 tasks),解锁 POST /blindbox/unlock -->
|
||
<div class="bx-lock hide" id="bxLock">
|
||
<div class="bx-lock-h"><span class="bx-lock-ico" aria-hidden="true">🔒</span>
|
||
<div><b>错过的 <em id="bxLockN"></em> 周待解锁</b><p>用一次孕期小工具,就能解锁一周补开</p></div></div>
|
||
<div class="bx-chips" id="bxLockChips"></div>
|
||
<div class="bx-tasks" id="bxTasks"></div>
|
||
</div>
|
||
<div class="bx-pend hide" id="bxPend">
|
||
<div class="bx-pend-t">还有 <b id="bxPendN"></b> 个盲盒等你打开 <em>错过的周会一直保留到孕 40 周</em></div>
|
||
<div class="bx-chips" id="bxChips"></div>
|
||
</div>
|
||
<section class="bx-album">
|
||
<div class="bx-ah">
|
||
<h3>我的宝宝卡册</h3>
|
||
<span class="bx-cnt"><b id="bxGot">0</b>/<span id="bxAll">37</span></span>
|
||
</div>
|
||
<div class="bx-prog"><i id="bxBar"></i></div>
|
||
<!-- 分段集齐奖励:孕早/中/晚期各一段 + 37 张全集。达成即记账,兜豆系统上线前由工作人员人工发放 -->
|
||
<div class="bx-goal" id="bxGoal"></div>
|
||
<p class="bx-anote" id="bxAnote"></p>
|
||
<div id="bxGroups"></div>
|
||
</section>
|
||
<details class="bx-rules" id="bxRules">
|
||
<summary>规则与概率说明</summary>
|
||
<div class="bx-rules-b" id="bxRulesBody"></div>
|
||
</details>
|
||
</div>
|
||
<div class="bx-reveal" id="bxReveal" aria-hidden="true">
|
||
<span class="bx-glow" aria-hidden="true"></span>
|
||
<span class="bx-flash" aria-hidden="true"></span>
|
||
<div class="bx-confetti" id="bxConfetti" aria-hidden="true"></div>
|
||
<div class="bx-rv-in">
|
||
<div class="bx-tag" id="bxTag"></div>
|
||
<div class="bx-persp">
|
||
<div class="bx-card3d" id="bxCard3d">
|
||
<div class="bx-face bx-back" id="bxBack"></div>
|
||
<div class="bx-face bx-front" id="bxFront"></div>
|
||
</div>
|
||
</div>
|
||
<p class="bx-dev" id="bxDev"></p>
|
||
<div class="bx-diary" id="bxDiary"></div>
|
||
<div class="bx-reward" id="bxReward"></div>
|
||
<button class="bx-keep" id="bxKeep" type="button"></button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 记一下 底部弹层 ================= -->
|
||
<div class="scrim" id="scrim"></div>
|
||
<section class="sheet" id="sheet">
|
||
<div class="sheet-grip" id="sheetGrip"><span></span></div>
|
||
<div class="sheet-head">
|
||
<div>
|
||
<h2>记一下</h2>
|
||
<p class="sk-sub" id="skSub"></p>
|
||
<!-- ⚠️ 临时隐藏(2026-09-22):「今天已记 N 条」依赖记录/统计功能,尚未实现 -->
|
||
<p class="tbd-hide"><span id="noteWhen">—</span> · 今天已记 <b id="todayCount">4</b> 条</p>
|
||
</div>
|
||
<button class="sheet-close" data-sheet="close" aria-label="关闭"><svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></button>
|
||
</div>
|
||
<div class="sheet-scroll">
|
||
<!-- ⚠️ 临时隐藏整块(2026-09-22):「今天已使用」快捷区 + 下方 .quick-row 的功能还没实现
|
||
(数据是写死的演示值 58.2kg / 待记录)。
|
||
**只挂 .tbd-hide,不要删 DOM**:JS 里 $('#quickKick') 没有判空,
|
||
还有 #kickCount / #todayCount / #noteWhen 会被回填,删掉会直接抛错。
|
||
恢复:去掉这三处 .tbd-hide 即可(含 <p> 那处),dedupeApps 会自动重新生效。 -->
|
||
<div class="apps-head first tbd-hide">今天已使用 <button class="sec-more" data-toast="点一下可直接补记">点一下直接记录 ›</button></div>
|
||
<div class="quick-row tbd-hide">
|
||
<button class="quick q1 ripple" id="quickKick"><img class="q-ico" src="assets/img/df905dcf3a1c.png" alt="" aria-hidden="true"><span class="q-t">数胎动</span><span class="q-v">+<b id="kickCount">1</b> 次</span></button>
|
||
<button class="quick q2 ripple" data-toast="已记录体重 58.2kg"><img class="q-ico" src="assets/img/a9e3b27a4a23.png" alt="" aria-hidden="true"><span class="q-t">孕期体重</span><span class="q-v">58.2kg</span></button>
|
||
<button class="quick q3 ripple" data-toast="开始测量胎心……"><img class="q-ico" src="assets/img/30de43bbc9aa.png" alt="" aria-hidden="true"><span class="q-t">胎心记录</span><span class="q-v">待记录</span></button>
|
||
<!-- 「今日心情」已按需求删除:记一下里只放工具,不放心情打卡。
|
||
删掉后 .quick-row 由 4 列改成 3 列,见 style.css -->
|
||
</div>
|
||
|
||
<!-- 2026-10-02 用户:「记一下弹窗有点单薄」→ 工具宫格上面加两层,数据都来自今日脚印接口(_fpData),不编数据:
|
||
① 今天卡:日期 + 孕周 + 一圈「今天记了几项」进度环 + 已记的工具小胶囊;
|
||
② 「先记这件」:今天还没用的前 2 个工具,配一句该做的事(todoLine),大卡可点。
|
||
接口没回来 / 访客 → 这两块保持隐藏,只剩副标题 + 宫格(和原来一样)。 -->
|
||
<!-- 2026-10-02 二改:用户要求弹窗别超过半屏 → 「今天卡」和「先记这件」合成一条:进度环 + 今天记了几项 + 下一件该做的事(去记),
|
||
已记的工具改成宫格图标上的小勾。整个弹窗 max-height 50%,工具多了宫格内部滚动。 -->
|
||
<div class="sk-today hide" id="skToday">
|
||
<div class="sk-ring" id="skRing" aria-hidden="true"><svg viewBox="0 0 44 44"><circle cx="22" cy="22" r="18"/><circle class="sk-arc" id="skArc" cx="22" cy="22" r="18"/></svg><b id="skNum">0</b></div>
|
||
<div class="sk-tt"><b id="skLine"></b><span id="skDone"></span></div>
|
||
<button class="sk-go hide" id="skGo" type="button">去记</button>
|
||
</div>
|
||
<div class="apps-head for-all tbd-hide">全部孕期工具 <button class="sec-more" data-toast="共 16 个孕期工具">共 16 个 ›</button></div>
|
||
<div class="apps-grid" id="appsGrid">
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/505ace532176.png" alt="" aria-hidden="true">数胎动</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/8b0f0a53938b.png" alt="" aria-hidden="true">孕期体重</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/9a2e7fa472dc.png" alt="" aria-hidden="true">孕检日历</button>
|
||
<!-- ⚠️ 下面这十几枚是**接口数据到达前的静态占位**:loadPublishedApps() 拉到
|
||
/api/mp/apps 后会用 renderAppGrid() 整个 innerHTML 覆盖。所以这里改不改
|
||
只影响首帧闪现;本批把「生长曲线」同步改成「数宫缩」,与首页卡口径一致。 -->
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/f989a64fe960.png" alt="" aria-hidden="true">数宫缩</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/fd875eb78785.png" alt="" aria-hidden="true">胎心记录</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/97c33531806b.png" alt="" aria-hidden="true">孕肚照</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/de0bc9e250f2.png" alt="" aria-hidden="true">B超影像</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/b855b45df1f3.png" alt="" aria-hidden="true">产检报告</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/c2ae6e98283b.png" alt="" aria-hidden="true">血压血糖</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/4657f50f42c8.png" alt="" aria-hidden="true">用药记录</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/72910df66ee3.png" alt="" aria-hidden="true">运动记录</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/dd5639fde61d.png" alt="" aria-hidden="true">饮食记录</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/f0d5e062f11a.png" alt="" aria-hidden="true">睡眠记录</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/056212807d86.png" alt="" aria-hidden="true">胎教音乐</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/7b7d81e02f42.png" alt="" aria-hidden="true">妈妈手记</button>
|
||
<button class="app ripple"><img class="a-ico" src="assets/img/f34fb7fdeea5.png" alt="" aria-hidden="true">更多工具</button>
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
<!-- ================= 编辑首页工具(2026-11-01,app.js htEditor) =================
|
||
上半「首页显示的工具」:长按整行(或按住右侧把手)拖动排序,↑↓ 兜底,「−」移除;
|
||
下半「更多孕期工具」:App 表里 category=孕期工具 的已上架应用,点「+」加入。上限 8 个(4×2),下限 1 个;「全部工具」在模块标题右侧,不占格子。
|
||
关闭(完成 / 叉 / 点遮罩)即保存到 localStorage mmbox.homeTools.v1,首页立即重排;「恢复默认」= 删掉这个键,回到默认顺序 + 孕周替补。 -->
|
||
<div class="scrim hts-scrim" id="htScrim"></div>
|
||
<section class="hts" id="htSheet" role="dialog" aria-modal="true" aria-labelledby="htsT" aria-hidden="true">
|
||
<div class="hts-grip" id="htsGrip"><span></span></div>
|
||
<div class="hts-head">
|
||
<div>
|
||
<h2 id="htsT">编辑首页工具</h2>
|
||
<p id="htsSub">长按拖动排序,首页最多放 8 个</p>
|
||
</div>
|
||
<button class="sheet-close" id="htsX" type="button" aria-label="关闭"><svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true"><path d="M3.5 3.5l9 9M12.5 3.5l-9 9" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></button>
|
||
</div>
|
||
<div class="hts-scroll" id="htsScroll">
|
||
<div class="hts-sec"><b>首页显示的工具</b><span id="htsCnt"></span></div>
|
||
<ul class="hts-list" id="htsList"></ul>
|
||
<div class="hts-sec"><b>更多孕期工具</b><span>点 + 加到首页</span></div>
|
||
<div class="hts-more" id="htsMore"></div>
|
||
</div>
|
||
<div class="hts-foot">
|
||
<button class="hts-reset" id="htsReset" type="button">恢复默认</button>
|
||
<button class="hts-done" id="htsDone" type="button">完成</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 搜索层 ================= -->
|
||
<section class="search-layer" id="searchLayer">
|
||
<div class="sl-bar">
|
||
<!-- ⚠️ 占位符里列的是可搜的东西。来信已整块移出本站(第三方 H5),
|
||
别再把它写回这句 —— 搜索框不该教用户搜一个界面上不存在的东西。
|
||
⚠️ 这句是 placeholder **属性**,不是文字节点 —— 只扫 textContent 的检查
|
||
抓不到它,改口时别忘了它。 -->
|
||
<div class="sl-input"><span>🔍</span><input id="searchInput" placeholder="搜索档案、记录……"></div>
|
||
<button class="sl-cancel" data-search="close">取消</button>
|
||
</div>
|
||
<div class="sl-body">
|
||
<div class="sl-sec">最近搜索</div>
|
||
<div class="chips-row wrap">
|
||
<button class="chip">第一次胎动</button><button class="chip">大排畸</button><button class="chip">体重</button><button class="chip">胎心</button>
|
||
</div>
|
||
<div class="sl-sec">大家都在搜</div>
|
||
<div class="sl-hot">
|
||
<button class="hot"><i>1</i>糖耐检查怎么准备</button>
|
||
<button class="hot"><i>2</i>孕<span data-wk="n">—</span>周胎动多少正常</button>
|
||
<button class="hot"><i>3</i>孕中期体重增长标准</button>
|
||
<button class="hot"><i>4</i>数胎动的正确方法</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
|
||
<!-- ================= 通用弹窗(往期小结 / 企业微信 / 我的资料) ================= -->
|
||
<div class="modal-scrim" id="modalScrim"></div>
|
||
|
||
<!-- ================= 往期小结 =================
|
||
原来点往期列表是把 AI 小结页顶上的今日卡整个换掉,看完想回到「今天」没有出口。
|
||
改成在原页上浮一层:内容只读,看完点底下的叉就走。
|
||
叉放在最下面而不是右上角 —— 这一屏是一路往下读完的,
|
||
读完手指就停在底部,再让人抬回右上角去关不合理。 -->
|
||
<section class="modal" id="modalAiLog" role="dialog" aria-modal="true" aria-labelledby="alogTitle">
|
||
<div class="alog-head">
|
||
<span class="alog-week" id="alogWeek">孕24周+2</span>
|
||
<span class="alog-mood" id="alogMood">安心</span>
|
||
</div>
|
||
<h3 class="alog-date" id="alogTitle">9月2日 周一</h3>
|
||
<p class="alog-txt" id="alogTxt"></p>
|
||
<!-- 只留这组数(胎动 / 体重 / 睡眠)—— 这是当天从小程序里真取到的记录。
|
||
下面本来还跟着一组 1/2/3 的建议卡(.alog-tips),删了:
|
||
那是 AI 当天现写的话,隔了几天再翻出来看已经没有用了,
|
||
而且它和上面那句 alogTxt 说的是同一件事,等于把结论又铺开讲三遍。
|
||
往期该回答的只有一个问题——那天的数是多少。建议留在「今日小建议」里。 -->
|
||
<div class="ai-stats alog-stats" id="alogStats"></div>
|
||
<button class="modal-x modal-x-btm" data-modal="close" aria-label="关闭">
|
||
<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true">
|
||
<path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</section>
|
||
|
||
<!-- ================= 百度网盘领取(已下线) =================
|
||
⚠️ 2026-09-19(9.19 需求 1.2 + 需求方确认):资料改由企业微信顾问**直接发放**,
|
||
H5 不再发网盘链接和提取码 —— 原来这个 #modalPan 弹窗、js 里的 PAN/PAN_DEFAULT
|
||
链接表、givePan()、「已领」标记已整块删除。要恢复「H5 自己发链接」,
|
||
得先回问需求方(那等于把「解锁」概念加回来)。
|
||
⚠️ 后端 /api/mp/public/mama-box/config 里的 pan / panDefault / wxCode 三个字段
|
||
也随之失效(box_app 侧后续清理)。 -->
|
||
|
||
<!-- ================= 加企业微信顾问 =================
|
||
⚠️ 2026-09-19(9.19 需求 1.1 / 1.2):这个弹窗从「兑换码闸门」简化成**纯提示**。
|
||
改动前后:
|
||
· 删掉兑换码输入框 + 「以后再说」「解锁全部资料」两颗按钮(需求 1.2);
|
||
· 原来的 is-gate / is-gift / is-done 三模式**合并成单态** —— 不再有「解锁」
|
||
这个状态,弹窗只负责把人引导到顾问那儿,资料由顾问在微信里直接发(需求方确认);
|
||
· 二维码下方文案改成需求指定的「请添加资料小助手,回复『领资料』」(需求 1.1)。
|
||
三个入口(资料详情「立即领取」、「我的」页服务卡、资源库试用装 banner)
|
||
共用这一个壳、同一句话,openWx() 不再按入口改写文案。
|
||
⚠️ data-autofocus="off":这个弹窗的主角是中间那张二维码,用户第一件事
|
||
是举起另一台手机去扫它。默认的自动聚焦会把输入法键盘顶起来,
|
||
正好盖住二维码下半截 —— 人得先把键盘收掉才能扫。
|
||
⚠️ 弹窗**没有底部按钮**:唯一出口是右上角 .modal-x(外加遮罩 / Esc)。
|
||
别把「优化掉没有按钮的头部」这种想法落到这颗叉上 —— 那会把人关在弹窗里。 -->
|
||
<section class="modal wx-modal" id="modalWx" data-autofocus="off"
|
||
role="dialog" aria-modal="true" aria-labelledby="wxTitle">
|
||
<div class="modal-head">
|
||
<!-- 兜底写「宝宝的」;填过小名的由 syncBabyWords() 刷成小名。
|
||
⚠️ 这行藏在弹窗里,改完小名不点开就看不见 —— 属于肉眼巡查
|
||
永远扫不到的挂点,只能靠 smoke 里那条断言守着。 -->
|
||
<h3 id="wxTitle">宝宝的孕育顾问</h3>
|
||
<button class="modal-x" data-modal="close" aria-label="关闭">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true">
|
||
<path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<!-- 单态文案:说清「加顾问 → 说一句领资料 → 她直接发」,不要求用户填任何东西。
|
||
⚠️ 称呼是「顾问」(与标题一致);二维码下方那句按需求原文写「资料小助手」。
|
||
这一处不一致是需求方明确保留的(见改动清单 D3),别顺手「统一」。 -->
|
||
<p class="modal-lead" id="wxLead">扫码添加顾问,说一句「领资料」,她会把资料直接发给你。</p>
|
||
<div class="wx-qr-box">
|
||
<!-- 真实企业微信顾问二维码(2026-09-22 换上,替换掉原来的占位 svg)。
|
||
文件 assets/img/4834fe8d686a.png ,396×396 PNG,
|
||
md5 = 4834fe8d686a6ca129c8e51e87fe62f8(**前 12 位就是文件名**)。
|
||
|
||
⚠️ 换码时的几条规矩:
|
||
① 文件名取**文件内容 md5 的前 12 位**(md5sum 新图 | cut -c1-12)。
|
||
该目录下 35 张图全按这个规则,别起描述性名字 —— 内容一变 URL 就变,
|
||
天然不会被上一版二维码的缓存顶住。
|
||
② 只动下面这一行。.wx-qr 挂在元素本身、svg 与 img 通吃(见 mama-box.css),
|
||
CSS 一个字都不用改:168×168、14px 圆角都是现成的。
|
||
14px 圆角只吃掉四角极角的**白色静默区**(本图静默区 13/396 → 显示约 5.5px,
|
||
对角裁切 4.1px < 到黑色模块的 7.8px),切不到码点,不影响扫码。
|
||
③ 注释里除了上面那条**真实存在**的路径,别再写别的图片路径字面量 ——
|
||
构建脚本连 HTML 注释一起扫,写了不存在的就报「缺少资源文件」。 -->
|
||
<img class="wx-qr" src="assets/img/4834fe8d686a.png" alt="企业微信顾问二维码">
|
||
<!-- 需求 1.1 指定的文案,逐字照抄(直角引号沿用站内习惯) -->
|
||
<p class="wx-qr-cap">请添加资料小助手,回复「领资料」</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ================= 我的资料(妈妈 + 宝宝,可换头像) =================
|
||
⚠️ 这里原来有**两个**弹窗:这张「我的资料」(头像 / 昵称 / 一句话签名)
|
||
和它上面一张 #modalPreg「编辑孕期信息」(小名 / 性别 / 预产期 / 孕周)。
|
||
本批按用户要求「我的资料里加上宝宝小名、性别、预产期」,
|
||
做法是把 #modalPreg **整个并进来**,而不是把三个字段抄一份过来。
|
||
|
||
为什么不抄一份:抄完这三个字段就有两套输入框写同一份 state。
|
||
两套控件迟早会漂 —— 一边加了校验另一边没加、一边保存后调了
|
||
syncPregnancy() 另一边忘了调,而且这种不一致在两个弹窗**分别**
|
||
打开时都看不出来,只有用户在 A 改完去 B 看才暴露。
|
||
合并之后 pgName/pgSex/pgDue/pgWeek/pgDay 这五个 id 一个没改,
|
||
原来挂在它们身上的联动(改预产期→算孕周、改孕周→反推预产期)
|
||
原样继续生效,只是保存按钮从 #pgSave 并进了 #pfSave。
|
||
|
||
⚠️ 「孕期信息」那一节的「编辑 ›」和整张孕期卡现在都指向这个弹窗
|
||
(data-modal 从 modalPreg 改成了 modalProfile),别再找 modalPreg 了。
|
||
|
||
⚠️ 高度预算(.modal 是 max-height:92% + overflow-y:auto,撑爆不会破版、
|
||
只会要用户滚一下才够得着「保存」,但那已经算体验问题了):
|
||
22 内边 + 30 头 + 头像块 121 + 昵称/小名同行 78 + 性别 77
|
||
+ 预产期 78 + 孕周行 78 + 提示 43 + 底部按钮 68 + 20 内边 ≈ 615px
|
||
设计稿机身 932px × 92% = 857 ✓;最窄的 iPhone SE 667 × 92% = 613 ——
|
||
**贴着线**。所以下面做了两件省高度的事,别随手退回去:
|
||
① 昵称和宝宝小名并成一行 .fld-row(省 78px);
|
||
② 这个弹窗里的大头像从 92px 收到 76px(见 css 的 #modalProfile .av-big)。
|
||
再往里加字段之前,先回来把这笔账重算一遍。 -->
|
||
<!-- 盲盒 · 集齐全集的实物奖励:收货信息。POST /api/mp/public/mama-box/blindbox/claim -->
|
||
<section class="modal" id="modalBxAddr" role="dialog" aria-modal="true" aria-labelledby="modalBxAddrTitle">
|
||
<div class="modal-head">
|
||
<h3 id="modalBxAddrTitle">领取孕期纪念礼</h3>
|
||
<button class="modal-x" data-modal="close" aria-label="关闭">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||
</button>
|
||
</div>
|
||
<p class="bx-addr-tip">恭喜集齐 37 张宝宝卡!填好收货信息,工作人员会在 7 个工作日内为你寄出。</p>
|
||
<div class="fld-row">
|
||
<label class="fld"><span>收货人</span><input id="bxAddrName" type="text" maxlength="20" placeholder="姓名"></label>
|
||
<label class="fld"><span>手机号</span><input id="bxAddrPhone" type="tel" maxlength="20" placeholder="手机号"></label>
|
||
</div>
|
||
<label class="fld"><span>收货地址</span><input id="bxAddrAddr" type="text" maxlength="120" placeholder="省市区 + 详细地址"></label>
|
||
<div class="modal-foot"><button class="dl-btn main" id="bxAddrSave">提交</button></div>
|
||
</section>
|
||
|
||
<!-- 星座宝宝(2026-10-04):点头图孕囊旁的「xx宝宝」小牌打开(js/hero-fx.js 派发 mb-zodiac → app.js 填内容 + openModal)。
|
||
幸运色 → 性格 → 适合的职业;预产期落在星座交界时顶部给两个可切换的小标签。内容是星座小趣味,底部写明。 -->
|
||
<section class="modal zd-modal" id="modalZodiac" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="zdName">
|
||
<!-- 2026-10-04 二版(用户:「弹出的页面重新设计,要有针对星座的设计感,背景色按火象、水象这些」):
|
||
顶部一条按四象配色的头带(火 / 土 / 风 / 水),右上角淡淡画出这个星座的星图(星星会闪),
|
||
正中玻璃圆里是星座符号;头带底边是元素纹样(火焰 / 山脊 / 云 / 水波),最下一层用正文底色填,头带「长」进正文。
|
||
素材在 js/zodiac-art.js。 -->
|
||
<div class="zd-band" id="zdBand">
|
||
<svg class="zd-sky" id="zdSky" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
|
||
<button class="modal-x" data-modal="close" aria-label="关闭">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||
</button>
|
||
<span class="zd-glyph" id="zdGlyph" aria-hidden="true"></span>
|
||
<h3 id="zdName"></h3>
|
||
<p class="zd-range"><span class="zd-el" id="zdEl"></span><span id="zdRange"></span></p>
|
||
<div class="zd-switch" id="zdSwitch" hidden></div>
|
||
<svg class="zd-motif" id="zdMotif" viewBox="0 0 375 56" preserveAspectRatio="none" aria-hidden="true"></svg>
|
||
</div>
|
||
<p class="zd-words" id="zdWords"></p>
|
||
<div class="zd-sec zd-color">
|
||
<i class="zd-sw" aria-hidden="true"></i>
|
||
<div><span class="zd-label">宝宝幸运色</span><b id="zdColor"></b><p id="zdColorTip"></p></div>
|
||
</div>
|
||
<div class="zd-sec">
|
||
<span class="zd-label">宝宝的性格</span>
|
||
<div class="zd-tags" id="zdTraits"></div>
|
||
<p class="zd-para" id="zdPara"></p>
|
||
</div>
|
||
<div class="zd-sec">
|
||
<span class="zd-label">长大后可能会喜欢的职业</span>
|
||
<div class="zd-jobs" id="zdJobs"></div>
|
||
</div>
|
||
<p class="zd-foot">星座小趣味,听听就好 —— 每个宝宝都是独一无二的小宇宙</p>
|
||
</section>
|
||
|
||
<!-- 意见反馈(2026-10-04)。类型 → 描述 → 截图(选填,最多 3 张,走 /api/upload)→ 联系方式(选填)→ 提交。
|
||
底部「我提交过的」列出最近几条和处理状态 / 回复(运营在管理端 PUT /api/mama-box/feedbacks/{id} 标记)。 -->
|
||
<section class="modal fb-modal" id="modalFeedback" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="fbTitle">
|
||
<div class="modal-head">
|
||
<h3 id="fbTitle">意见反馈</h3>
|
||
<button class="modal-x" data-modal="close" aria-label="关闭">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||
</button>
|
||
</div>
|
||
<p class="fb-lead">哪里不好用、想要什么新功能,都可以告诉我们,每一条都会认真看。</p>
|
||
<div class="fb-kinds" id="fbKinds" role="radiogroup" aria-label="反馈类型">
|
||
<button type="button" class="fb-kind" data-kind="bug" role="radio" aria-checked="false">功能问题</button>
|
||
<button type="button" class="fb-kind on" data-kind="idea" role="radio" aria-checked="true">功能建议</button>
|
||
<button type="button" class="fb-kind" data-kind="other" role="radio" aria-checked="false">其他</button>
|
||
</div>
|
||
<div class="fb-ta-wrap">
|
||
<textarea class="fb-ta" id="fbText" maxlength="500" placeholder="说说你遇到的问题或想法…"></textarea>
|
||
<span class="fb-count" id="fbCount">0/500</span>
|
||
</div>
|
||
<div class="fb-imgs" id="fbImgs">
|
||
<label class="fb-add" id="fbAdd"><input type="file" accept="image/*" id="fbFile" hidden><svg viewBox="0 0 24 24" width="22" height="22" aria-hidden="true"><path d="M12 6v12M6 12h12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg><span>截图</span></label>
|
||
<span class="fb-imgs-tip">选填,最多 3 张</span>
|
||
</div>
|
||
<label class="fld fb-contact"><span>联系方式(选填)</span><input id="fbContact" type="text" maxlength="40" placeholder="手机号或微信号,方便我们回复你"></label>
|
||
<div class="modal-foot"><button class="dl-btn main" id="fbSubmit">提交</button></div>
|
||
<div class="fb-mine" id="fbMine" hidden>
|
||
<h4>我提交过的</h4>
|
||
<div id="fbMineList"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 同周悄悄话 · 全屏页(2026-10-02 二改)。「深夜星河」:深靛紫夜空 + 星点,悄悄话是一盏盏漂浮的玻璃泡,
|
||
抱抱越多越亮越大;最上面是今晚抱抱最多的一句,大字。底部一颗发光的「说一句悄悄话」。
|
||
层级 z 110:盖住 tabbar(60),低于说一句弹窗(modal 120+),所以在这页里点「说一句」弹窗能盖在上面。 -->
|
||
<section class="wh-page" id="whPage" role="dialog" aria-modal="true" aria-labelledby="whpTitle" aria-hidden="true">
|
||
<div class="whp-sky" aria-hidden="true"><i class="s1"></i><i class="s2"></i><i class="s3"></i><i class="moon"></i></div>
|
||
<!-- 2026-10-02 五改(用户:「打开页面夜空里特别多星星;点开一颗,它像流星一样滑落,白色的头往下滑,
|
||
尾巴就是这句话的字;先保证看清,刚开始慢一点,说完了唰地就快了;同时把对应内容呈现出来」):
|
||
夜空 = 每句一颗可点的亮星 + 一百多颗装饰小星(偶尔有无字的小流星划过);点亮星 → 流星 + 底部内容卡。 -->
|
||
<div class="whv-aura" id="whvAura" aria-hidden="true"><i></i><i></i></div>
|
||
<div class="wsk" id="wsk">
|
||
<div class="wsk-deco" id="wskStars" aria-hidden="true"></div>
|
||
<i class="wsk-shoot" aria-hidden="true"></i><i class="wsk-shoot s2" aria-hidden="true"></i>
|
||
<div class="wsk-bright" id="wskBright" role="group" aria-label="夜空里的星星,每颗是一句悄悄话"></div>
|
||
</div>
|
||
<header class="whv-top">
|
||
<button class="whp-back" id="whpBack" type="button" aria-label="返回">
|
||
<svg viewBox="0 0 24 24" width="20" height="20"><path d="M15 5l-7 7 7 7" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||
</button>
|
||
<span class="whp-tag" id="whpTag"></span>
|
||
<button class="whv-snd" id="whvSnd" type="button" aria-label="关闭声音"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 9.5h3.5L12 5.5v13l-4.5-4H4z" fill="currentColor" stroke="none"/><path class="on" d="M15.5 9a4 4 0 010 6M18 6.5a7.5 7.5 0 010 11"/><path class="off" d="M16 9.5l5 5M21 9.5l-5 5"/></svg></button>
|
||
<button class="whv-all" id="whvAll" type="button">全部</button>
|
||
</header>
|
||
<div class="wsk-title" id="wskTitle"></div>
|
||
<p class="wsk-tip" id="wskTip"><i></i>点一下小星星,听听她们说了什么</p>
|
||
<div class="wsk-done" id="wskDone"><p>星星都落下来啦<br><span>她们的话,你都听到了</span></p><button type="button" id="wskBack">让星星回来</button></div>
|
||
<div class="wsc" id="wsc" aria-live="polite"></div>
|
||
<h2 class="sr-only" id="whpTitle">同孕周悄悄话</h2>
|
||
<div class="whd" id="whDrawer" aria-hidden="true">
|
||
<div class="whd-panel" role="dialog" aria-label="全部悄悄话">
|
||
<div class="whd-head"><b>全部悄悄话</b><span id="whpCount"></span><button type="button" class="whd-x" id="whdX" aria-label="收起"><svg viewBox="0 0 24 24" width="14" height="14"><path d="M6 6l12 12M18 6L6 18" stroke="currentColor" stroke-width="2.4" stroke-linecap="round"/></svg></button></div>
|
||
<div class="whp-list" id="whpList"></div>
|
||
</div>
|
||
</div>
|
||
<div class="whp-bar">
|
||
<button class="whp-say" id="whSay" type="button"><span>说一句悄悄话</span></button>
|
||
<p class="whp-left" id="whpLeft"></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 此刻 · 说一句悄悄话(2026-10-02)。预设句点一下就填进输入框;自由输入由服务端过微信内容安全审核 -->
|
||
<section class="modal wh-modal" id="modalWhisper" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="whMTitle">
|
||
<div class="modal-head">
|
||
<h3 id="whMTitle">说一句悄悄话</h3>
|
||
<button class="modal-x" data-modal="close" aria-label="关闭">
|
||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/></svg>
|
||
</button>
|
||
</div>
|
||
<p class="wh-m-topic" id="whMTopic" style="display:none"></p>
|
||
<p class="wh-m-lead" id="whMLead">不显示昵称和头像,只有同孕期的妈妈能看到。她们会给你一个抱抱。</p>
|
||
<div class="wh-ta-box">
|
||
<textarea class="wh-ta" id="whTa" maxlength="40" rows="2" placeholder="今天想对谁说点什么?"></textarea>
|
||
<span class="wh-cnt" id="whCnt">0/40</span>
|
||
</div>
|
||
<div class="wh-m-sub">不知道说什么?点一句</div>
|
||
<div class="wh-presets" id="whPresets"></div>
|
||
<div class="modal-foot">
|
||
<button class="dl-btn main" id="whSend" type="button">悄悄发出</button>
|
||
<p class="wh-left" id="whLeft"></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 盲盒 · 分段集齐达成的庆祝弹层(内容由 app.js showPrize() 填) -->
|
||
<section class="modal bx-prize" id="modalBxPrize" role="dialog" aria-modal="true" aria-labelledby="bxPrizeT">
|
||
<div class="bx-prize-ico" aria-hidden="true">🏆</div>
|
||
<h3 id="bxPrizeT"></h3>
|
||
<p id="bxPrizeP"></p>
|
||
<div class="modal-foot"><button class="dl-btn main" id="bxPrizeOk">太好了</button></div>
|
||
</section>
|
||
|
||
<!-- 新人欢迎礼(2026-10-10):统一兜豆账本 welcome 规则首次发放时弹一次;豆数用接口返回的 granted -->
|
||
<section class="modal bx-prize wg-modal" id="modalWelcome" role="dialog" aria-modal="true" aria-labelledby="wgT">
|
||
<div class="bx-prize-ico" aria-hidden="true">🎁</div>
|
||
<h3 id="wgT">新人欢迎礼 <b class="wg-n">+<span id="wgN">50</span></b> 兜豆</h3>
|
||
<p>已经存进你的兜豆账户,可以去兑换好物啦</p>
|
||
<div class="modal-foot">
|
||
<button class="dl-btn ghost" data-modal="close">收下了</button>
|
||
<button class="dl-btn main" id="wgGo">去看看</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 孕周开放门槛(2026-10-11):数胎动 16 / 数宫缩 20 / 胎儿估重 15 周后开放,没到时点入口弹这个,内容由 app.js openStageGate() 按孕周现填 -->
|
||
<section class="modal bx-prize sg-modal" id="modalStageGate" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="sgT">
|
||
<div class="sg-ico" id="sgIco" aria-hidden="true"></div>
|
||
<h3 id="sgT">孕 16 周后开放</h3>
|
||
<span class="sg-now" id="sgNow"></span>
|
||
<p id="sgP"></p>
|
||
<div class="sg-track" aria-hidden="true">
|
||
<div class="sg-rail"><i id="sgBar"></i></div>
|
||
<div class="sg-ends"><span id="sgFrom"></span><span id="sgTo"></span></div>
|
||
</div>
|
||
<div class="sg-left" id="sgLeft"></div>
|
||
<div class="modal-foot"><button class="dl-btn main" data-modal="close">好的,到时再来</button></div>
|
||
</section>
|
||
|
||
<!-- 2026-10-10 用户:退出登录前二次确认,写清只清授权信息、孕育数据保留 -->
|
||
<section class="modal bx-prize lg-modal" id="modalLogout" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="lgT">
|
||
<h3 id="lgT">确定退出登录?</h3>
|
||
<p>退出后不再显示你的昵称、头像和手机号。孕期资料和各项记录仍保存在这个微信上,重新授权就能继续使用。</p>
|
||
<div class="modal-foot">
|
||
<button class="dl-btn ghost" data-modal="close">再想想</button>
|
||
<button class="dl-btn main" id="lgOk">退出登录</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2026-10-11 用户:「我的资料」改名「孕期档案」,样式照数胎动的孕期档案弹层:一张白卡、一行一项,头像放第一行;
|
||
点「当前孕周」「预产期」从底部再弹一层滚轮(#pkSheet)。表单 id 全部沿用(#pgDue/#pgWeek/#pgDay/#pgName/#pgSex/#pfName/#avPick),
|
||
#pfSave 的校验与落库逻辑一行没改;三种填法切换 / 步进器 / 末次月经 / 小名建议已随改版去掉。 -->
|
||
<section class="modal pf-modal" id="modalProfile" data-autofocus="off" role="dialog" aria-modal="true" aria-labelledby="modalProfileTitle">
|
||
<div class="pf-grip" aria-hidden="true"></div>
|
||
<h3 class="pf-title" id="modalProfileTitle">孕期档案</h3>
|
||
<p class="pf-lead">填好预产期,孕周和倒计时都会自动算好</p>
|
||
|
||
<!-- 未授权(含退出登录后)不显示旧昵称/头像,换成授权提示;宝宝那几行不受影响 -->
|
||
<button type="button" class="pf-unauth ripple" id="pfUnauth" style="display:none">授权登录后显示你的昵称和头像<b>去授权 ›</b></button>
|
||
|
||
<div class="pf-list">
|
||
<div class="pf-row pf-row-av" id="pfMe" role="button" tabindex="0">
|
||
<span class="pr-l"><b>头像</b><em>点一下换张照片</em></span>
|
||
<button type="button" class="av-big" id="avPick" aria-label="更换头像">
|
||
<svg viewBox="0 0 40 40" aria-hidden="true">
|
||
<circle cx="20" cy="14.5" r="7" fill="#fff"/>
|
||
<path d="M6.5 35c0-7.2 6-11.5 13.5-11.5S33.5 27.8 33.5 35z" fill="#fff"/>
|
||
</svg>
|
||
<img id="avPreview" alt="">
|
||
</button>
|
||
<i class="chev" aria-hidden="true">›</i>
|
||
<!-- file input 藏起来但不能 display:none,否则部分安卓 WebView 点不动(0 尺寸 + opacity) -->
|
||
<input type="file" id="avFile" accept="image/*" class="av-file">
|
||
</div>
|
||
<button type="button" class="pf-row" id="pfWeekRow">
|
||
<span class="pr-l"><b>当前孕周</b><em>改孕周会同步更新预产期</em></span>
|
||
<span class="pr-v hot" id="pgWeekTxt">去填写</span><i class="chev" aria-hidden="true">›</i>
|
||
</button>
|
||
<button type="button" class="pf-row" id="pfDueRow">
|
||
<span class="pr-l"><b>预产期</b><em>以产检单 / B 超单为准</em></span>
|
||
<span class="pr-v hot" id="pgDueTxt">去填写</span><i class="chev" aria-hidden="true">›</i>
|
||
</button>
|
||
<div class="pf-row">
|
||
<span class="pr-l"><b>宝宝性别</b></span>
|
||
<div class="pf-seg" id="pgSex" role="group" aria-label="宝宝性别">
|
||
<button type="button" class="pick" data-sex="boy">男孩</button>
|
||
<button type="button" class="pick" data-sex="girl">女孩</button>
|
||
</div>
|
||
</div>
|
||
<label class="pf-row" id="pfMeTip">
|
||
<span class="pr-l"><b>妈妈昵称</b><em>选填</em></span>
|
||
<input class="pr-in" id="pfName" type="text" maxlength="16" placeholder="妈妈">
|
||
</label>
|
||
<label class="pf-row">
|
||
<span class="pr-l"><b>宝宝小名</b><em>选填</em></span>
|
||
<input class="pr-in" id="pgName" type="text" maxlength="12" placeholder="给宝宝起个小名">
|
||
</label>
|
||
</div>
|
||
<!-- 预产期 / 孕周的唯一数据源,滚轮确定后写这里,再 dispatch change 走原来的换算 -->
|
||
<input type="hidden" id="pgDue"><input type="hidden" id="pgWeek"><input type="hidden" id="pgDay">
|
||
|
||
<p class="pf-note">孕周和预产期会同步到各个孕期工具</p>
|
||
<div class="modal-foot pf-foot">
|
||
<button class="dl-btn ghost" data-modal="close">取消</button>
|
||
<button class="dl-btn main" id="pfSave">保存资料</button>
|
||
</div>
|
||
<!-- 显示规则同「我的」页 #meLogoutCard(已授权才显示),共用 doLogout -->
|
||
<button type="button" class="pf-logout" id="pfLogout" style="display:none">退出登录</button>
|
||
</section>
|
||
|
||
<!-- 孕期档案里的滚轮(2026-10-11):week = 孕周 + 天,due = 年 / 月 / 日;底下一行文字可互相切换 -->
|
||
<div class="pk-scrim" id="pkScrim"></div>
|
||
<section class="pk-sheet" id="pkSheet" role="dialog" aria-modal="true" aria-labelledby="pkT">
|
||
<h3 id="pkT">你现在怀孕多久了?</h3>
|
||
<p class="pk-sub" id="pkSub">按孕周推算预产期</p>
|
||
<div class="pk-wheels" id="pkWheels"></div>
|
||
<div class="pk-res"><span id="pkResL">预产期</span><b id="pkResV">—</b></div>
|
||
<button type="button" class="dl-btn main pk-ok" id="pkOk">确定</button>
|
||
<button type="button" class="pk-alt" id="pkAlt">知道预产期?直接选日期</button>
|
||
</section>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
</div>
|
||
|
||
<!-- 微信 JS-SDK:仅在 web-view 内给 wx.miniProgram 用(「进商城」跳原生页)。
|
||
加载失败/离线时 window.wx 为 undefined,goMall() 会降级为 toast 提示,
|
||
不影响应用其余功能。 -->
|
||
|
||
<!-- 统一头像面板(预设妈妈/宝宝头像 + 从相册上传 + 用微信头像),孕期档案点头像用 -->
|
||
<script src="/_bridge/avatar-picker.js?v=26101105"></script>
|
||
<script src="/_bridge/hand-icons.js?v=26101202"></script>
|
||
<script src="js/zodiac-art.js"></script>
|
||
<script src="guangchang/topics.js?v=26110127"></script>
|
||
<script src="js/app.js"></script>
|
||
<script>
|
||
/* 11-02 首页「孕妈广场」效果稿:地址带 ?gcv=1~6 时,把 #gcHome 换成 demo/gch/vN.css + vN.js 的版式并滚到这一块。
|
||
11-02 用户:「用第一版,放到预览页面上」;后改定彩色卡 → 不带参数也默认用 V6 合并版(广场卡堆 + 其他妈妈也在搜 + 测一测第 4 版彩色卡),不滚动、不显示效果稿角标 */
|
||
(function () {
|
||
var m = location.search.match(/[?&]gcv=([1-6])(?:&|$)/);
|
||
if (!m) window.__gcDefault = 1;
|
||
var n = m ? m[1] : '6', l = document.createElement('link'), s = document.createElement('script'), q = m ? Date.now() : 'v=26110130';
|
||
l.rel = 'stylesheet'; l.href = 'demo/gch/v' + n + '.css?' + q;
|
||
s.src = 'demo/gch/v' + n + '.js?' + q;
|
||
if (m) s.onload = function () { setTimeout(function () { var el = document.getElementById('gcHome'); if (el) el.scrollIntoView({ block: 'center' }); }, 900); };
|
||
document.head.appendChild(l); document.body.appendChild(s);
|
||
})();
|
||
</script>
|
||
<!-- 2026-10-03 首页彩蛋:宝宝在肚皮底下动(独立文件,删掉这一行即整体下线;开关在「隐私权限」) -->
|
||
<script src="js/bump.js"></script>
|
||
<!-- 2026-10-04 首页头图:按孕周换宝宝 + 阳光水波(独立文件) -->
|
||
<script src="js/hero-fx.js"></script>
|
||
<!-- 2026-10-05 首页头图:宝宝时不时动一动小手小脚(独立文件,删掉这一行即下线) -->
|
||
<script src="js/baby-limbs.js?v=26101201"></script>
|
||
<script src="js/coach.js?v=26101211"></script>
|
||
<script src="js/birth-flow.js?v=26110127"></script>
|
||
|
||
<!-- 禁止下拉回弹(2026-10-11 统一规则,与孕期体重同一段):竖向拖动时从手指下往上找还能朝该方向滚的容器,找不到才拦;横滑、双指、可滚列表不受影响 -->
|
||
<script>
|
||
(function () {
|
||
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) 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>
|