首页兜豆模块加横滑可兑好物;我的页孕期卡与兜豆卡对调;资料弹窗改版(实时结果条、预产期三种填法、孕周步进、小名建议)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
137
js/app.js
137
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26100137';
|
||||
var VER = '26100138';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -890,14 +890,10 @@
|
||||
return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate());
|
||||
}
|
||||
|
||||
/* 2026-10-01 资料弹窗改版后:孕周两格不再锁(「按当前孕周」那页本来就是让人从零填的),
|
||||
这里只负责没预产期时把两格清空。函数名留着,调用点不用动。 */
|
||||
function lockWeekFields(locked) {
|
||||
pgWeek.disabled = pgDay.disabled = locked;
|
||||
/* 锁着的时候连数字也不留 —— 没填预产期就没有「当前孕周」这回事,
|
||||
留个旧值在灰格子里反而像是已经填好了 */
|
||||
if (locked) { pgWeek.value = ''; pgDay.value = ''; }
|
||||
pgHint.textContent = locked
|
||||
? '还没填预产期,孕周先锁着 —— 选好上面的预产期就会自动算出来。'
|
||||
: '已按预产期自动算出,觉得不准可以自己微调。';
|
||||
}
|
||||
/* 缓存戳重载:只换查询串(?t=…),两处都不能丢:
|
||||
① URL 已有 query 时必须用 & 拼接 —— 直接拼 '?t=' 会把第二个 ? 吃进已有参数值里
|
||||
@@ -944,6 +940,8 @@
|
||||
lockWeekFields(true);
|
||||
}
|
||||
syncDuePh();
|
||||
setPgMode('due');
|
||||
if (pgLmp) { pgLmp.value = ''; pgLmp.dispatchEvent(new Event('change')); }
|
||||
/* 头像预览跟随卡片(有正式头像才显示;新用户空圆 + +号) */
|
||||
const _me = $('#meAvatar');
|
||||
if (_me && _me.classList.contains('has-img') && meAvatarImg && meAvatarImg.src) {
|
||||
@@ -955,13 +953,72 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 预产期占位层:空值显示「- 年 - 月 - 日」,选了值隐藏 */
|
||||
/* 预产期按钮上的文字 + 顶部结果条,都从 #pgDue 现算(唯一数据源)。
|
||||
函数名沿用 syncDuePh(原来只管「- 年 - 月 - 日」占位层),调用点不用动。 */
|
||||
const WK = '日一二三四五六';
|
||||
function fmtDay(d) { return d.getFullYear() + '年' + (d.getMonth() + 1) + '月' + d.getDate() + '日 周' + WK[d.getDay()]; }
|
||||
function syncDuePh() {
|
||||
const ph = $('#pgDuePh');
|
||||
if (ph) ph.style.display = pgDue.value ? 'none' : 'block';
|
||||
pgDue.classList.toggle('due-empty', !pgDue.value);
|
||||
const due = parseDay(pgDue.value);
|
||||
const t = $('#pgDueTxt');
|
||||
if (t) { t.textContent = due ? fmtDay(due) : '点这里选预产期'; t.parentNode.classList.toggle('is-set', !!due); }
|
||||
const sum = $('#pgSum');
|
||||
if (!sum) return;
|
||||
sum.classList.toggle('is-set', !!due);
|
||||
if (!due) {
|
||||
$('#pgSumT').textContent = '还没填预产期';
|
||||
$('#pgSumS').textContent = '选一种方式填一下,马上就好';
|
||||
return;
|
||||
}
|
||||
const left = Math.round((midnight(due) - midnight(new Date())) / DAY_MS);
|
||||
if (left < 0) {
|
||||
$('#pgSumT').textContent = '宝宝已经出生啦';
|
||||
$('#pgSumS').textContent = '预产期 ' + fmtDay(due);
|
||||
return;
|
||||
}
|
||||
const ga = gaFromDue(due);
|
||||
$('#pgSumT').textContent = '孕 ' + Math.floor(ga / 7) + ' 周' + (ga % 7 ? ' +' + (ga % 7) + ' 天' : '');
|
||||
$('#pgSumS').textContent = (left ? '还有 ' + left + ' 天见面' : '就是今天啦') + ' · 预产期 ' + (due.getMonth() + 1) + '月' + due.getDate() + '日';
|
||||
}
|
||||
|
||||
/* 三种填法切换(只切面板;数据都落在 #pgDue) */
|
||||
function setPgMode(m) {
|
||||
$$('#pgMode .seg-b').forEach(b => b.classList.toggle('is-active', b.dataset.mode === m));
|
||||
$$('#modalProfile .pg-pane').forEach(p => p.classList.toggle('is-on', p.dataset.pane === m));
|
||||
}
|
||||
$$('#pgMode .seg-b').forEach(b => b.addEventListener('click', () => { setPgMode(b.dataset.mode); haptic(); }));
|
||||
|
||||
/* 孕周步进:空着时从 12 周起步(一般建档时间),天数 6 再 + 进位到下一周 */
|
||||
$$('#modalProfile .stp-b').forEach(b => b.addEventListener('click', () => {
|
||||
let w = parseInt(pgWeek.value, 10), d = parseInt(pgDay.value, 10);
|
||||
if (isNaN(w)) w = 12;
|
||||
if (isNaN(d)) d = 0;
|
||||
const k = +b.dataset.d;
|
||||
if (b.dataset.stp === 'w') w += k;
|
||||
else {
|
||||
d += k;
|
||||
if (d > 6) { d = 0; w += 1; }
|
||||
if (d < 0) { d = w > 0 ? 6 : 0; if (w > 0) w -= 1; }
|
||||
}
|
||||
pgWeek.value = Math.min(42, Math.max(0, w));
|
||||
pgDay.value = d;
|
||||
pgWeek.dispatchEvent(new Event('change'));
|
||||
haptic();
|
||||
}));
|
||||
|
||||
/* 末次月经第一天 + 280 天 = 预产期 */
|
||||
const pgLmp = $('#pgLmp');
|
||||
if (pgLmp) pgLmp.addEventListener('change', () => {
|
||||
const l = parseDay(pgLmp.value);
|
||||
const t = $('#pgLmpTxt');
|
||||
if (t) { t.textContent = l ? fmtDay(l) : '点这里选末次月经第一天'; t.parentNode.classList.toggle('is-set', !!l); }
|
||||
if (!l) return;
|
||||
pgDue.value = toISO(new Date(l.getFullYear(), l.getMonth(), l.getDate() + 280));
|
||||
pgDue.dispatchEvent(new Event('change'));
|
||||
});
|
||||
|
||||
/* 小名建议:点一下填进去 */
|
||||
$$('#pgNameChips .nm-c').forEach(b => b.addEventListener('click', () => { pgName.value = b.textContent; haptic(); }));
|
||||
|
||||
/* 预产期一变,孕周 / 额外天数自动算出来 */
|
||||
pgDue.addEventListener('change', () => {
|
||||
syncDuePh();
|
||||
@@ -979,6 +1036,7 @@
|
||||
const d = Math.min(6, Math.max(0, parseInt(pgDay.value, 10) || 0));
|
||||
pgWeek.value = w; pgDay.value = d;
|
||||
pgDue.value = toISO(dueFromGA(w * 7 + d));
|
||||
syncDuePh();
|
||||
}));
|
||||
|
||||
/* 性别三选一 */
|
||||
@@ -1373,7 +1431,8 @@
|
||||
$('#pfSave').addEventListener('click', () => {
|
||||
/* 预产期是一切的源头:孕周、剩余天数、信里的日期全从它算。没有它没什么可存的。 */
|
||||
if (!parseDay(pgDue.value)) {
|
||||
toast('先选一下预产期,孕周会自动算出来');
|
||||
toast('先填一下预产期,孕周会自动算出来');
|
||||
setPgMode('due');
|
||||
pgDue.focus();
|
||||
return;
|
||||
}
|
||||
@@ -4172,27 +4231,49 @@
|
||||
function setExchSub(t) {
|
||||
$$('#meExchSub, #homeExchSub').forEach(function (el) { el.textContent = t; });
|
||||
}
|
||||
function douImg(g) {
|
||||
return /^https?:/.test(g.img || '') ? g.img : EXCH_URL + String(g.img || '').replace(/^\//, '');
|
||||
}
|
||||
/* 一件商品的小卡(「我的」页 3 件 / 首页横滑 6 件共用),全用 DOM 拼,商品名不进 innerHTML */
|
||||
function douItem(g, cls, more) {
|
||||
const it = document.createElement('span'); it.className = cls;
|
||||
const pic = document.createElement('span'); pic.className = 'gi-pic';
|
||||
const im = document.createElement('img'); im.alt = ''; im.loading = 'lazy'; im.src = douImg(g);
|
||||
pic.appendChild(im);
|
||||
if (more && g.badge) { const bd = document.createElement('i'); bd.className = 'gi-badge'; bd.textContent = g.badge; pic.appendChild(bd); }
|
||||
if (more && g.stock <= 5) { const st = document.createElement('i'); st.className = 'gi-left'; st.textContent = '仅剩 ' + g.stock + ' 件'; pic.appendChild(st); }
|
||||
const nm = document.createElement('span'); nm.className = 'bd-nm'; nm.textContent = g.name || '';
|
||||
const pr = document.createElement('b'); pr.textContent = g.price + ' 兜豆';
|
||||
it.append(pic, nm, pr);
|
||||
return it;
|
||||
}
|
||||
function renderDrop(d) {
|
||||
const box = $('#meExchDrop'); if (!box) return;
|
||||
const now = d && d.server_time ? new Date(d.server_time).getTime() : Date.now();
|
||||
const goods = ((d && d.goods) || []).filter(function (g) {
|
||||
return g.stock > 0 && (!g.opens_at || new Date(g.opens_at).getTime() <= now);
|
||||
})
|
||||
.sort(function (x, y) { return (y.heat_30m || 0) - (x.heat_30m || 0); }).slice(0, 3);
|
||||
if (!goods.length) { box.classList.add('hide'); return; }
|
||||
const dr = d.drop || {};
|
||||
$('#meExchDropT').textContent = (dr.title || '本场好物') + (dr.open && dr.left != null ? ' · 剩 ' + dr.left + ' 件' : '');
|
||||
const wrap = $('#meExchGoods'); wrap.textContent = '';
|
||||
goods.forEach(function (g) {
|
||||
const it = document.createElement('span'); it.className = 'bd-it';
|
||||
const im = document.createElement('img'); im.alt = ''; im.loading = 'lazy';
|
||||
im.src = /^https?:/.test(g.img || '') ? g.img : EXCH_URL + String(g.img || '').replace(/^\//, '');
|
||||
const nm = document.createElement('span'); nm.className = 'bd-nm'; nm.textContent = g.name || '';
|
||||
const pr = document.createElement('b'); pr.textContent = g.price + ' 兜豆';
|
||||
it.append(im, nm, pr); wrap.appendChild(it);
|
||||
});
|
||||
box.classList.remove('hide');
|
||||
}).sort(function (x, y) { return (y.heat_30m || 0) - (x.heat_30m || 0); });
|
||||
/* 「我的」页:本场标题 + 热门前 3 */
|
||||
const box = $('#meExchDrop');
|
||||
if (box) {
|
||||
if (!goods.length) box.classList.add('hide');
|
||||
else {
|
||||
const dr = d.drop || {};
|
||||
$('#meExchDropT').textContent = (dr.title || '本场好物') + (dr.open && dr.left != null ? ' · 剩 ' + dr.left + ' 件' : '');
|
||||
const wrap = $('#meExchGoods'); wrap.textContent = '';
|
||||
goods.slice(0, 3).forEach(function (g) { wrap.appendChild(douItem(g, 'bd-it')); });
|
||||
box.classList.remove('hide');
|
||||
}
|
||||
}
|
||||
/* 首页:横滑前 6 件,带「热门」角标和「仅剩 N 件」 */
|
||||
const row = $('#homeExchGoods');
|
||||
if (row) {
|
||||
row.textContent = '';
|
||||
goods.slice(0, 6).forEach(function (g) { row.appendChild(douItem(g, 'ex-it', true)); });
|
||||
row.classList.toggle('hide', !goods.length);
|
||||
}
|
||||
}
|
||||
const _hxg = $('#homeExchGoods');
|
||||
if (_hxg) _hxg.addEventListener('click', function (e) { if (e.target.closest('.ex-it')) openExchange(); });
|
||||
function loadDou() {
|
||||
const oid = hashParam('openid'), uid = hashParam('unionid');
|
||||
const dropP = fetch(DOU_API + '/mall/drop').then(function (r) { return r.ok ? r.json() : null; }).catch(function () { return null; });
|
||||
|
||||
Reference in New Issue
Block a user