「我的资料」改「孕期档案」:照数胎动改成一行一项白卡,头像放第一行;孕周 / 预产期点开滚轮选择 v26101025
Co-Authored-By: AI 助手
This commit is contained in:
172
index.html
172
index.html
@@ -7,7 +7,7 @@
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<title>兜爸心选 · 孕育陪伴</title>
|
||||
<!-- V:26101024 缓存版本标记:改 css/js 时同步 bump 该值(与 js/app.js 的 VER 同源),静态资源按 mtime 走 ETag 自动刷新 -->
|
||||
<!-- V:26101025 缓存版本标记:改 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) -->
|
||||
@@ -1957,134 +1957,76 @@
|
||||
</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="modal-head">
|
||||
<h3 id="modalProfileTitle">我的资料</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>
|
||||
|
||||
<!-- 2026-10-01 资料弹窗改版(用户:「现在填写比较困难,让用户很轻松地就能填写完」):
|
||||
① 顶部一条实时结果「孕 N 周 +D 天 · 还有 X 天见面」—— 填的每一步都立刻看到算出了什么;
|
||||
② 预产期三种填法(分段切换):知道预产期 / 按当前孕周(大号 −/+ 步进,不用敲键盘)/ 按末次月经;
|
||||
三种最后都落到 #pgDue(唯一的数据源),保存逻辑一行没改;
|
||||
③ 头像缩到昵称左边,和昵称同一行;宝宝小名下面给几个一点即填的小名;
|
||||
④ 弹窗不再自动聚焦昵称(data-autofocus="off")—— 一打开就弹键盘,正好盖住要填的预产期。 -->
|
||||
<div class="pf-grip" aria-hidden="true"></div>
|
||||
<h3 class="pf-title" id="modalProfileTitle">孕期档案</h3>
|
||||
<p class="pf-lead">填好预产期,孕周和倒计时都会自动算好</p>
|
||||
|
||||
<div class="pf-sum" id="pgSum">
|
||||
<span class="ps-ico" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M12 20.5s-7.5-4.4-7.5-10A4.3 4.3 0 0 1 12 8a4.3 4.3 0 0 1 7.5 2.5c0 5.6-7.5 10-7.5 10z" fill="currentColor"/></svg>
|
||||
</span>
|
||||
<span class="ps-main"><b id="pgSumT">还没填预产期</b><span id="pgSumS">选一种方式填一下,马上就好</span></span>
|
||||
</div>
|
||||
<!-- 未授权(含退出登录后)不显示旧昵称/头像,换成授权提示;宝宝那几行不受影响 -->
|
||||
<button type="button" class="pf-unauth ripple" id="pfUnauth" style="display:none">授权登录后显示你的昵称和头像<b>去授权 ›</b></button>
|
||||
|
||||
<div class="pf-card">
|
||||
<div class="pf-ct">孕期信息<em>必填</em></div>
|
||||
<div class="seg" id="pgMode" role="tablist">
|
||||
<button type="button" class="seg-b is-active" data-mode="due">知道预产期</button>
|
||||
<button type="button" class="seg-b" data-mode="week">按当前孕周</button>
|
||||
<button type="button" class="seg-b" data-mode="lmp">按末次月经</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>
|
||||
|
||||
<div class="pg-pane is-on" data-pane="due">
|
||||
<label class="date-btn">
|
||||
<span class="db-ico" aria-hidden="true"><svg viewBox="0 0 24 24" width="20" height="20"><rect x="4" y="5.5" width="16" height="14.5" rx="3" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M4 10h16M8.5 3.5v4M15.5 3.5v4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></span>
|
||||
<span class="db-txt" id="pgDueTxt">点这里选预产期</span>
|
||||
<i class="chev">›</i>
|
||||
<input id="pgDue" type="date" aria-label="预产期">
|
||||
</label>
|
||||
<p class="pg-tip">产检单 / B 超单上写的「预产期」</p>
|
||||
</div>
|
||||
|
||||
<div class="pg-pane" data-pane="week">
|
||||
<div class="stp-row">
|
||||
<div class="stp">
|
||||
<span class="stp-l">孕周</span>
|
||||
<div class="stp-ctl">
|
||||
<button type="button" class="stp-b" data-stp="w" data-d="-1" aria-label="孕周减一">−</button>
|
||||
<input id="pgWeek" type="number" inputmode="numeric" min="0" max="42" placeholder="—">
|
||||
<button type="button" class="stp-b" data-stp="w" data-d="1" aria-label="孕周加一">+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stp">
|
||||
<span class="stp-l">又几天</span>
|
||||
<div class="stp-ctl">
|
||||
<button type="button" class="stp-b" data-stp="d" data-d="-1" aria-label="天数减一">−</button>
|
||||
<input id="pgDay" type="number" inputmode="numeric" min="0" max="6" placeholder="—">
|
||||
<button type="button" class="stp-b" data-stp="d" data-d="1" aria-label="天数加一">+</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="pg-tip" id="pgHint">比如「孕 24 周 +3 天」,就选 24 和 3</p>
|
||||
</div>
|
||||
|
||||
<div class="pg-pane" data-pane="lmp">
|
||||
<label class="date-btn">
|
||||
<span class="db-ico" aria-hidden="true"><svg viewBox="0 0 24 24" width="20" height="20"><rect x="4" y="5.5" width="16" height="14.5" rx="3" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M4 10h16M8.5 3.5v4M15.5 3.5v4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg></span>
|
||||
<span class="db-txt" id="pgLmpTxt">点这里选末次月经第一天</span>
|
||||
<i class="chev">›</i>
|
||||
<input id="pgLmp" type="date" aria-label="末次月经第一天">
|
||||
</label>
|
||||
<p class="pg-tip">按末次月经第一天 + 280 天推算预产期</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pf-card">
|
||||
<!-- 2026-10-05 用户:「小名」这行字挪到「宝宝」后面、放进括号 → 标题写成「宝宝(小名)」,输入框上方不再单独一行「小名」(读屏仍念「宝宝小名」) -->
|
||||
<div class="pf-ct">宝宝(小名)</div>
|
||||
<label class="fld pf-fld"><span class="sr-only">宝宝小名</span><input id="pgName" type="text" maxlength="12" placeholder="给宝宝起个小名"></label>
|
||||
<div class="nm-chips" id="pgNameChips">
|
||||
<button type="button" class="nm-c">小汤圆</button><button type="button" class="nm-c">豆豆</button><button type="button" class="nm-c">糖糖</button><button type="button" class="nm-c">小米粒</button><button type="button" class="nm-c">乐乐</button>
|
||||
</div>
|
||||
<div class="fld pf-fld">
|
||||
<span>性别</span>
|
||||
<div class="pick-row" id="pgSex">
|
||||
<button type="button" class="pick is-active" data-sex="unknown">还不知道</button>
|
||||
<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">
|
||||
|
||||
<div class="pf-card">
|
||||
<div class="pf-ct">妈妈</div>
|
||||
<!-- 2026-10-10 方案A:未授权(含退出登录后)不显示旧昵称/头像,换成授权提示;点它去授权。宝宝那栏不受影响 -->
|
||||
<button type="button" class="pf-unauth ripple" id="pfUnauth" style="display:none">授权登录后显示你的昵称和头像<b>去授权 ›</b></button>
|
||||
<div class="pf-me" id="pfMe">
|
||||
<div class="av-pick">
|
||||
<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="">
|
||||
<span class="av-cam">
|
||||
<svg viewBox="0 0 24 24" width="15" height="15" aria-hidden="true">
|
||||
<path d="M3 8.6A2.6 2.6 0 0 1 5.6 6h1.9l1.3-2h6.4L16.5 6h1.9A2.6 2.6 0 0 1 21 8.6v8.8a2.6 2.6 0 0 1-2.6 2.6H5.6A2.6 2.6 0 0 1 3 17.4z" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linejoin="round"/>
|
||||
<circle cx="12" cy="13" r="3.6" fill="none" stroke="currentColor" stroke-width="1.9"/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<input type="file" id="avFile" accept="image/*" class="av-file">
|
||||
<!-- file input 藏起来但不能 display:none,否则部分安卓 WebView 点不动(0 尺寸 + opacity) -->
|
||||
<input type="file" id="avFile" accept="image/*" class="av-file">
|
||||
</div>
|
||||
<label class="fld pf-fld"><span>怎么称呼你</span><input id="pfName" type="text" maxlength="16" placeholder="妈妈"></label>
|
||||
</div>
|
||||
<p class="pg-tip" id="pfMeTip">点头像换张照片</p>
|
||||
</div>
|
||||
|
||||
<!-- 2026-10-10 用户:「我的资料」里也要有「退出登录」。显示规则同「我的」页 #meLogoutCard(已授权才显示),共用 doLogout -->
|
||||
<button type="button" class="pf-logout ripple" id="pfLogout" style="display:none">退出登录</button>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
|
||||
128
js/app.js
128
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26101024';
|
||||
var VER = '26101025';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -1302,7 +1302,15 @@
|
||||
function syncDuePh() {
|
||||
const due = parseDay(pgDue.value);
|
||||
const t = $('#pgDueTxt');
|
||||
if (t) { t.textContent = due ? fmtDay(due) : '点这里选预产期'; t.parentNode.classList.toggle('is-set', !!due); }
|
||||
/* 孕期档案两行(2026-10-11 改版):右侧值都从 #pgDue 现算 */
|
||||
if (t) { t.textContent = due ? due.getFullYear() + ' 年 ' + (due.getMonth() + 1) + ' 月 ' + due.getDate() + ' 日' : '去填写'; t.classList.toggle('is-empty', !due); }
|
||||
const wt = $('#pgWeekTxt');
|
||||
if (wt) {
|
||||
const lf = due ? Math.round((midnight(due) - midnight(new Date())) / DAY_MS) : null;
|
||||
const g = due ? gaFromDue(due) : 0;
|
||||
wt.textContent = !due ? '去填写' : lf < 0 ? '宝宝已出生' : '孕 ' + Math.floor(g / 7) + ' 周' + (g % 7 ? ' +' + (g % 7) + ' 天' : '');
|
||||
wt.classList.toggle('is-empty', !due);
|
||||
}
|
||||
const sum = $('#pgSum');
|
||||
if (!sum) return;
|
||||
sum.classList.toggle('is-set', !!due);
|
||||
@@ -1382,11 +1390,112 @@
|
||||
}));
|
||||
|
||||
/* 性别三选一 */
|
||||
/* 性别:男孩 / 女孩二选一,再点一下已选的就取消(= 还不知道,保存成 unknown) */
|
||||
$$('#pgSex .pick').forEach(b => b.addEventListener('click', () => {
|
||||
$$('#pgSex .pick').forEach(x => x.classList.toggle('is-active', x === b));
|
||||
const on = !b.classList.contains('is-active');
|
||||
$$('#pgSex .pick').forEach(x => x.classList.toggle('is-active', on && x === b));
|
||||
haptic();
|
||||
}));
|
||||
|
||||
/* ---------- 孕期档案 · 滚轮选择(2026-10-11,照数胎动的孕期档案) ----------
|
||||
week:孕 0–42 周 × 0–6 天,下面实时显示对应预产期;due:年 / 月 / 日,下面显示对应孕周。
|
||||
确定后写 #pgWeek/#pgDay 或 #pgDue 并 dispatch change —— 换算、行内文字都走原来那两个监听,不另算一套。 */
|
||||
const PK_H = 40; /* 每行高度,CSS .pk-col i 同值 */
|
||||
const pkSheet = $('#pkSheet'), pkScrim = $('#pkScrim'), pkWheels = $('#pkWheels');
|
||||
let pkMode = 'week';
|
||||
function pkCol(key, items, sel) {
|
||||
return '<div class="pk-col" data-k="' + key + '">' + items.map((t, i) => '<i data-i="' + i + '">' + t + '</i>').join('') + '</div>';
|
||||
}
|
||||
function pkIdx(col) { return Math.max(0, Math.min(col.children.length - 1, Math.round(col.scrollTop / PK_H))); }
|
||||
function pkSet(col, i) {
|
||||
col.scrollTop = i * PK_H;
|
||||
$$('i', col).forEach((x, k) => x.classList.toggle('on', k === i));
|
||||
}
|
||||
function pkGet(k) { const c = $('.pk-col[data-k="' + k + '"]', pkWheels); return c ? pkIdx(c) : 0; }
|
||||
const pkYears = () => { const y = new Date().getFullYear(); return [y - 1, y, y + 1]; };
|
||||
function pkDayCol(keep) {
|
||||
const ys = pkYears(), y = ys[pkGet('y')], m = pkGet('m');
|
||||
const n = new Date(y, m + 1, 0).getDate();
|
||||
const old = $('.pk-col[data-k="d"]', pkWheels);
|
||||
const tmp = document.createElement('div');
|
||||
tmp.innerHTML = pkCol('d', Array.from({ length: n }, (_, i) => (i + 1) + ' 日'));
|
||||
const col = tmp.firstChild;
|
||||
old.replaceWith(col);
|
||||
pkBind(col);
|
||||
pkSet(col, Math.min(keep, n - 1));
|
||||
}
|
||||
function pkResult() {
|
||||
if (pkMode === 'week') {
|
||||
const due = dueFromGA(pkGet('w') * 7 + pkGet('dd'));
|
||||
$('#pkResL').textContent = '预产期';
|
||||
$('#pkResV').textContent = toISO(due);
|
||||
} else {
|
||||
const ys = pkYears(), due = new Date(ys[pkGet('y')], pkGet('m'), pkGet('d') + 1);
|
||||
const left = Math.round((midnight(due) - midnight(new Date())) / DAY_MS), g = gaFromDue(due);
|
||||
$('#pkResL').textContent = '对应孕周';
|
||||
$('#pkResV').textContent = left < 0 ? '已过预产期' : left > TERM ? '还没怀上哦' : '孕 ' + Math.floor(g / 7) + ' 周' + (g % 7 ? ' +' + (g % 7) + ' 天' : '');
|
||||
}
|
||||
}
|
||||
function pkBind(col) {
|
||||
let tm = 0;
|
||||
col.addEventListener('scroll', () => {
|
||||
clearTimeout(tm);
|
||||
tm = setTimeout(() => {
|
||||
const i = pkIdx(col);
|
||||
$$('i', col).forEach((x, k) => x.classList.toggle('on', k === i));
|
||||
if (col.dataset.k === 'y' || col.dataset.k === 'm') pkDayCol(pkGet('d'));
|
||||
pkResult();
|
||||
}, 90);
|
||||
}, { passive: true });
|
||||
col.addEventListener('click', e => { const it = e.target.closest('i'); if (it) col.scrollTo({ top: +it.dataset.i * PK_H, behavior: 'smooth' }); });
|
||||
}
|
||||
function openPicker(mode) {
|
||||
pkMode = mode;
|
||||
const cur = parseDay(pgDue.value);
|
||||
if (mode === 'week') {
|
||||
$('#pkT').textContent = '你现在怀孕多久了?';
|
||||
$('#pkSub').textContent = '按孕周推算预产期';
|
||||
$('#pkAlt').textContent = '知道预产期?直接选日期';
|
||||
pkWheels.innerHTML = pkCol('w', Array.from({ length: 43 }, (_, i) => '孕 ' + i + ' 周')) + pkCol('dd', Array.from({ length: 7 }, (_, i) => i + ' 天'));
|
||||
const g = cur ? gaFromDue(cur) : 12 * 7;
|
||||
$$('.pk-col', pkWheels).forEach(pkBind);
|
||||
pkSet($('.pk-col[data-k="w"]', pkWheels), Math.floor(g / 7));
|
||||
pkSet($('.pk-col[data-k="dd"]', pkWheels), g % 7);
|
||||
} else {
|
||||
$('#pkT').textContent = '预产期是哪一天?';
|
||||
$('#pkSub').textContent = '以产检单 / B 超单上写的为准';
|
||||
$('#pkAlt').textContent = '不知道预产期?按孕周填';
|
||||
const d = cur || dueFromGA(12 * 7), ys = pkYears();
|
||||
pkWheels.innerHTML = pkCol('y', ys.map(y => y + ' 年')) + pkCol('m', Array.from({ length: 12 }, (_, i) => (i + 1) + ' 月')) + pkCol('d', ['1 日']);
|
||||
$$('.pk-col', pkWheels).forEach(pkBind);
|
||||
pkSet($('.pk-col[data-k="y"]', pkWheels), Math.max(0, ys.indexOf(d.getFullYear())));
|
||||
pkSet($('.pk-col[data-k="m"]', pkWheels), d.getMonth());
|
||||
pkDayCol(d.getDate() - 1);
|
||||
}
|
||||
pkWheels.className = 'pk-wheels n' + $$('.pk-col', pkWheels).length;
|
||||
pkResult();
|
||||
pkScrim.classList.add('show');
|
||||
pkSheet.classList.add('show');
|
||||
haptic();
|
||||
}
|
||||
function closePicker() { pkScrim.classList.remove('show'); pkSheet.classList.remove('show'); }
|
||||
$('#pfWeekRow').addEventListener('click', () => openPicker('week'));
|
||||
$('#pfDueRow').addEventListener('click', () => openPicker('due'));
|
||||
$('#pkAlt').addEventListener('click', () => openPicker(pkMode === 'week' ? 'due' : 'week'));
|
||||
pkScrim.addEventListener('click', closePicker);
|
||||
$('#pkOk').addEventListener('click', () => {
|
||||
if (pkMode === 'week') {
|
||||
pgWeek.value = pkGet('w'); pgDay.value = pkGet('dd');
|
||||
pgWeek.dispatchEvent(new Event('change'));
|
||||
} else {
|
||||
const ys = pkYears();
|
||||
pgDue.value = toISO(new Date(ys[pkGet('y')], pkGet('m'), pkGet('d') + 1));
|
||||
pgDue.dispatchEvent(new Event('change'));
|
||||
}
|
||||
closePicker();
|
||||
haptic();
|
||||
});
|
||||
|
||||
/* 环的目标值改了要顺手清掉上一轮动画的终值,否则 animateRings 不会重跑 */
|
||||
function setRing(el, p) {
|
||||
if (!el) return;
|
||||
@@ -1575,7 +1684,7 @@
|
||||
$('#arTitleName').textContent = nm;
|
||||
$('#arLine1').textContent = '完善孕期信息后开启';
|
||||
$('#arDays').textContent = '--';
|
||||
$('#arLine2').textContent = '先去「我的资料」填预产期';
|
||||
$('#arLine2').textContent = '先去「孕期档案」填预产期';
|
||||
$('#arPct').textContent = '0%';
|
||||
setArBar(0);
|
||||
$('#genWeekTag').textContent = '--';
|
||||
@@ -1761,7 +1870,13 @@
|
||||
/* 点大圆 → 转交给隐藏的 file input。openModal 里会 focus 第一个输入框,
|
||||
这里 avFile 排在 pfName 前面,所以 openModal 用的选择器只取 .modal-ta/input
|
||||
可能命中 file input——用 :not([type=file]) 排除掉,见 openModal */
|
||||
avBig.addEventListener('click', () => avFile.click());
|
||||
avBig.addEventListener('click', e => { e.stopPropagation(); avFile.click(); });
|
||||
/* 孕期档案里头像是一整行,点行上任何地方都换头像 */
|
||||
const pfMeRow = $('#pfMe');
|
||||
if (pfMeRow) {
|
||||
pfMeRow.addEventListener('click', e => { if (e.target !== avFile) avFile.click(); });
|
||||
pfMeRow.addEventListener('keydown', e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); avFile.click(); } });
|
||||
}
|
||||
|
||||
avFile.addEventListener('change', () => {
|
||||
const f = avFile.files && avFile.files[0];
|
||||
@@ -1786,8 +1901,7 @@
|
||||
/* 预产期是一切的源头:孕周、剩余天数、信里的日期全从它算。没有它没什么可存的。 */
|
||||
if (!parseDay(pgDue.value)) {
|
||||
toast('先填一下预产期,孕周会自动算出来');
|
||||
setPgMode('due');
|
||||
pgDue.focus();
|
||||
openPicker('week');
|
||||
return;
|
||||
}
|
||||
const name = $('#pfName').value.trim() || '妈妈';
|
||||
|
||||
52
mama-box.css
52
mama-box.css
@@ -4785,3 +4785,55 @@ a.skip:focus{left:16px;top:16px}
|
||||
/* 首页工具卡自动换成替补(swapHomeCards):尺寸、底色沿用坑位原样,只换内容;插画是白色线稿 svg */
|
||||
.mini-card .sw-art{height:auto;aspect-ratio:1;opacity:.95}
|
||||
|
||||
/* ================= 孕期档案弹窗(2026-10-11 改版,原「我的资料」)=================
|
||||
照数胎动的孕期档案:居中标题 + 一张白卡一行一项,右侧值橘色;点孕周 / 预产期再弹滚轮 #pkSheet。 */
|
||||
.pf-modal{padding-top:10px}
|
||||
.pf-grip{width:38px;height:4px;border-radius:2px;background:#E2D6CE;margin:0 auto 12px}
|
||||
.pf-title{text-align:center;font-size:18px;font-weight:900;letter-spacing:-.2px}
|
||||
.pf-modal .pf-lead{text-align:center;font-size:12px;color:var(--muted);margin-top:4px}
|
||||
.pf-list{margin-top:14px;border-radius:20px;background:#fff;box-shadow:0 4px 14px rgba(160,110,90,.08);overflow:hidden}
|
||||
.pf-row{display:flex;align-items:center;gap:10px;width:100%;min-height:62px;padding:12px 14px 12px 16px;text-align:left;position:relative;cursor:pointer}
|
||||
.pf-row+.pf-row::before{content:"";position:absolute;left:16px;right:0;top:0;height:1px;background:#F2EAE4}
|
||||
.pf-row:active{background:#FBF6F2}
|
||||
.pf-row .pr-l{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
|
||||
.pf-row .pr-l b{font-size:15px;font-weight:800;color:var(--ink)}
|
||||
.pf-row .pr-l em{font-style:normal;font-size:11.5px;color:var(--muted)}
|
||||
.pf-row .pr-v{flex:none;font-size:15px;font-weight:800;color:var(--ink)}
|
||||
.pf-row .pr-v.hot{color:var(--brand)}
|
||||
.pf-row .pr-v.is-empty{color:#B9ABA2;font-weight:700}
|
||||
.pf-row .chev{flex:none;margin-left:-4px}
|
||||
.pf-row .pr-in{flex:0 1 52%;min-width:0;border:0;background:none;text-align:right;font:inherit;font-size:15px;font-weight:800;color:var(--ink);padding:6px 0}
|
||||
.pf-row .pr-in::placeholder{color:#B9ABA2;font-weight:700}
|
||||
.pf-row .pr-in:focus{outline:none}
|
||||
.pf-row-av .av-big{width:46px;height:46px;margin:0;flex:none}
|
||||
.pf-row-av .av-big>svg{width:26px;height:26px}
|
||||
.pf-seg{flex:none;display:flex;gap:4px;padding:3px;border-radius:12px;background:#F3ECE6}
|
||||
.pf-seg .pick{flex:none;padding:6px 16px;border-radius:9px;background:none;font-size:13.5px;font-weight:700;color:var(--ink-2);box-shadow:none}
|
||||
.pf-seg .pick.is-active{background:#fff;color:var(--brand);box-shadow:0 2px 6px rgba(160,110,90,.14)}
|
||||
.pf-modal .pf-unauth{margin-top:14px}
|
||||
.pf-note{margin-top:12px;text-align:center;font-size:11.5px;color:var(--muted)}
|
||||
.pf-modal .pf-foot{margin-top:12px}
|
||||
.pf-modal .pf-logout{background:none;color:var(--muted);font-size:13px;font-weight:600;margin:0 auto;padding:4px 12px calc(10px + env(safe-area-inset-bottom));width:auto}
|
||||
|
||||
.pk-scrim{position:absolute;inset:0;z-index:130;background:rgba(50,30,22,.32);opacity:0;visibility:hidden;transition:opacity .25s,visibility .25s}
|
||||
.pk-scrim.show{opacity:1;visibility:visible}
|
||||
.pk-sheet{position:absolute;left:0;right:0;bottom:0;z-index:131;background:#FAF5F1;border-radius:28px 28px 0 0;
|
||||
padding:24px 22px calc(14px + env(safe-area-inset-bottom));text-align:center;
|
||||
transform:translateY(102%);transition:transform .36s var(--ease)}
|
||||
.pk-sheet.show{transform:none;box-shadow:0 -10px 40px rgba(90,50,35,.22)}
|
||||
.pk-sheet h3{font-size:18px;font-weight:900}
|
||||
.pk-sub{margin-top:4px;font-size:12px;color:var(--muted)}
|
||||
.pk-wheels{position:relative;display:flex;height:200px;margin:16px 0 0}
|
||||
.pk-wheels::before{content:"";position:absolute;left:0;right:0;top:80px;height:40px;border-radius:12px;background:#fff;box-shadow:0 2px 10px rgba(160,110,90,.08);z-index:0}
|
||||
.pk-wheels::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:2;
|
||||
background:linear-gradient(#FAF5F1,rgba(250,245,241,0) 34%,rgba(250,245,241,0) 66%,#FAF5F1)}
|
||||
.pk-col{position:relative;z-index:1;flex:1;height:200px;overflow-y:auto;scroll-snap-type:y mandatory;overscroll-behavior:contain;
|
||||
padding:80px 0;scrollbar-width:none;-webkit-overflow-scrolling:touch}
|
||||
.pk-col::-webkit-scrollbar{display:none}
|
||||
.pk-col i{display:block;height:40px;line-height:40px;font-style:normal;font-size:15px;color:var(--ink-2);scroll-snap-align:center;transition:color .15s,font-size .15s}
|
||||
.pk-col i.on{font-size:17px;font-weight:800;color:var(--brand)}
|
||||
.pk-res{margin-top:14px;font-size:13px;color:var(--muted)}
|
||||
.pk-res b{margin-left:8px;font-size:16px;font-weight:900;color:var(--brand)}
|
||||
.pk-ok{display:block;width:100%;margin-top:16px}
|
||||
.pk-alt{margin-top:12px;font-size:12.5px;color:var(--muted);text-decoration:underline;text-underline-offset:3px}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user