v26110446 预览:专属福利不跟后台开关一直显示;「宝宝出生了」改成和我的收藏同款列表行;踢腿音效改到手机喇叭能放的频段+绕开 iPhone 静音键+每次触摸恢复声音
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26110445';
|
||||
var VER = '26110446';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
|
||||
@@ -124,28 +124,55 @@
|
||||
· 浏览器规定用户碰过页面后才能出声 → 第一次点 / 摸屏幕时才建 AudioContext,之前的踢腿不响。
|
||||
· 页面在后台 / 首页不在前台时本来就不动,也就不响;系统「减少动态效果」整个文件不跑。
|
||||
· URL 带 kicksound=0 关掉(调试用)。 */
|
||||
let ac = null;
|
||||
/* 11-05 用户:「音效我打开了,但是没有声音」→ 三处原因一起修:
|
||||
① 原来是 60~150Hz 的低音,手机外放喇叭基本放不出 → 改到 180~420Hz 的「咚」+ 一点低通噪声当「闷擦」,音量略加;
|
||||
② iPhone 静音键开着时 WebAudio 会被静音 → 有 navigator.audioSession 就设成 playback,没有就在手势里放一段极短的静音 <audio> 把会话切到「播放」类;
|
||||
③ 原来只在第一次触摸建一次 AudioContext,没起来或切后台被挂起后就再也不响 → 每次触摸都检查,挂起了就 resume。 */
|
||||
let ac = null, nb = null, primed = false;
|
||||
const soundOff = /[?&#]kicksound=0/.test(location.href);
|
||||
function silentWav() { // 0.05 秒静音 wav(8kHz 单声道 8bit)
|
||||
const n = 400, buf = new ArrayBuffer(44 + n), v = new DataView(buf), w = (o, str) => { for (let i = 0; i < str.length; i++) v.setUint8(o + i, str.charCodeAt(i)); };
|
||||
w(0, 'RIFF'); v.setUint32(4, 36 + n, true); w(8, 'WAVEfmt '); v.setUint32(16, 16, true); v.setUint16(20, 1, true); v.setUint16(22, 1, true);
|
||||
v.setUint32(24, 8000, true); v.setUint32(28, 8000, true); v.setUint16(32, 1, true); v.setUint16(34, 8, true); w(36, 'data'); v.setUint32(40, n, true);
|
||||
for (let i = 0; i < n; i++) v.setUint8(44 + i, 128);
|
||||
return URL.createObjectURL(new Blob([buf], { type: 'audio/wav' }));
|
||||
}
|
||||
const unlock = () => {
|
||||
if (ac || soundOff) return;
|
||||
try { const A = window.AudioContext || window.webkitAudioContext; if (A) { ac = new A(); if (ac.state === 'suspended') ac.resume(); } } catch (e) { ac = null; }
|
||||
if (soundOff) return;
|
||||
try {
|
||||
if (!primed) {
|
||||
primed = true;
|
||||
if (navigator.audioSession) navigator.audioSession.type = 'playback';
|
||||
else { const au = new Audio(silentWav()); au.setAttribute('playsinline', ''); au.volume = 0.01; const pr = au.play(); if (pr && pr.catch) pr.catch(() => {}); }
|
||||
}
|
||||
if (!ac) { const A = window.AudioContext || window.webkitAudioContext; if (A) ac = new A(); }
|
||||
if (ac && ac.state !== 'running') ac.resume();
|
||||
if (ac && !nb) { // 0.25 秒白噪声,做「闷擦」用
|
||||
nb = ac.createBuffer(1, Math.floor(ac.sampleRate * .25), ac.sampleRate);
|
||||
const d = nb.getChannelData(0); for (let i = 0; i < d.length; i++) d[i] = Math.random() * 2 - 1;
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
['touchstart', 'pointerdown', 'click'].forEach(t => addEventListener(t, unlock, { passive: true, once: false, capture: true }));
|
||||
['touchstart', 'touchend', 'pointerdown', 'click'].forEach(t => addEventListener(t, unlock, { passive: true, capture: true }));
|
||||
function kickSound(delay) {
|
||||
if (!ac || ac.state !== 'running') return;
|
||||
try { if (localStorage.getItem('mb_kick_snd') === '0') return; } catch (e) {} // 11-05 「我的 → 隐私与权限 → 宝宝踢腿音效」关了就不响
|
||||
const t = ac.currentTime + delay / 1000;
|
||||
// 闷响:正弦 150→60Hz 快速下滑,低通滤掉高频,像隔着肚皮
|
||||
const o = ac.createOscillator(), g = ac.createGain(), lp = ac.createBiquadFilter();
|
||||
o.type = 'sine'; o.frequency.setValueAtTime(150, t); o.frequency.exponentialRampToValueAtTime(60, t + .16);
|
||||
lp.type = 'lowpass'; lp.frequency.value = 420;
|
||||
g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(0.16, t + .012); g.gain.exponentialRampToValueAtTime(0.0001, t + .2);
|
||||
o.connect(lp); lp.connect(g); g.connect(ac.destination); o.start(t); o.stop(t + .22);
|
||||
// 小气泡:很轻的上滑「啵」,晚一点点
|
||||
const b = ac.createOscillator(), bg = ac.createGain(), t2 = t + .05;
|
||||
b.type = 'sine'; b.frequency.setValueAtTime(520, t2); b.frequency.exponentialRampToValueAtTime(900, t2 + .07);
|
||||
bg.gain.setValueAtTime(0.0001, t2); bg.gain.exponentialRampToValueAtTime(0.025, t2 + .01); bg.gain.exponentialRampToValueAtTime(0.0001, t2 + .09);
|
||||
b.connect(bg); bg.connect(ac.destination); b.start(t2); b.stop(t2 + .1);
|
||||
try { if (localStorage.getItem('mb_kick_snd') === '0') return; } catch (e) {} // 「我的 → 隐私与权限 → 宝宝踢腿音效」关了就不响
|
||||
const t = ac.currentTime + delay / 1000, out = ac.createGain();
|
||||
out.gain.value = 0.9; out.connect(ac.destination);
|
||||
// 咚:正弦 420→180Hz 快速下滑(手机喇叭放得出来),带一点二次谐波让它更「实」
|
||||
[[1, .32], [2, .08]].forEach(([m, v]) => {
|
||||
const o = ac.createOscillator(), g = ac.createGain();
|
||||
o.type = 'sine'; o.frequency.setValueAtTime(420 * m, t); o.frequency.exponentialRampToValueAtTime(180 * m, t + .14);
|
||||
g.gain.setValueAtTime(0.0001, t); g.gain.exponentialRampToValueAtTime(v, t + .008); g.gain.exponentialRampToValueAtTime(0.0001, t + .18);
|
||||
o.connect(g); g.connect(out); o.start(t); o.stop(t + .2);
|
||||
});
|
||||
// 闷擦:低通噪声一小下,像隔着肚皮蹬了一脚
|
||||
if (nb) {
|
||||
const n = ac.createBufferSource(), lp = ac.createBiquadFilter(), ng = ac.createGain();
|
||||
n.buffer = nb; lp.type = 'lowpass'; lp.frequency.value = 900;
|
||||
ng.gain.setValueAtTime(0.0001, t); ng.gain.exponentialRampToValueAtTime(0.12, t + .006); ng.gain.exponentialRampToValueAtTime(0.0001, t + .09);
|
||||
n.connect(lp); lp.connect(ng); ng.connect(out); n.start(t); n.stop(t + .1);
|
||||
}
|
||||
}
|
||||
|
||||
// 安排下一次「动一动」
|
||||
|
||||
@@ -44,10 +44,7 @@
|
||||
'.bf-card .bf-go{flex:none;font-size:12.5px;font-weight:700;color:#F4593C;border:1.5px solid #F4593C;border-radius:99px;padding:6px 11px;background:#fff;white-space:nowrap}' +
|
||||
'.bf-card.born{background:linear-gradient(120deg,#E6F5EC,#FBFFFC);border-color:#BFE5CF}' +
|
||||
'.bf-card.born .bf-ic{background:#CFEEDC}.bf-card.born .bf-go{color:#2F8A5E;border-color:#2F8A5E}' +
|
||||
'.bf-me{display:flex;align-items:center;gap:10px;width:100%;margin-top:12px;padding:14px 16px;border:0;border-radius:18px;background:#fff;text-align:left;font-size:15px;color:#2B2320;box-shadow:0 2px 10px rgba(80,40,20,.05)}' +
|
||||
'.bf-me i{font-style:normal}.bf-me .bf-me-ic{flex:none;width:30px;height:30px;border-radius:10px;background:#FFE0D1;display:flex;align-items:center;justify-content:center}' +
|
||||
'.bf-me.born .bf-me-ic{background:#D8EFE1}.bf-me.born .bf-me-v{color:#3A7A52}' +
|
||||
'.bf-me .bf-me-t{flex:1}.bf-me .bf-me-v{font-size:12.5px;color:#9A8E86}.bf-me .bf-me-a{color:#C9BEB6}' +
|
||||
'.bf-me{margin-top:14px}.bf-me .li-ico{background:#FFE0D1}.bf-me.born .li-ico{background:#D8EFE1}.bf-me.born .li-v{color:#3A7A52}' +
|
||||
'.bf-ov{position:fixed;inset:0;z-index:135;display:none;background:rgba(30,20,15,.45);font-family:inherit;color:#2B2320}' +
|
||||
'.bf-ov.on{display:flex;align-items:flex-end}' +
|
||||
'.bf-sheet{width:100%;background:#fff;border-radius:22px 22px 0 0;padding:22px 20px calc(22px + env(safe-area-inset-bottom));animation:bfUp .3s ease}' +
|
||||
@@ -356,9 +353,10 @@
|
||||
var pc = $('#screen-me .preg-card'), me = $('#bfMe');
|
||||
if (me) me.remove();
|
||||
/* 2026-10-22(测试会话 150e0991):产后用户「我的」里原来什么入口都没有 → 换成「宝宝已出生 · 去育儿首页」,走同一个 goBaby() */
|
||||
/* 11-05 用户:「宝宝出生了」字号和图标要跟下面「我的收藏」「兜豆兑换」一致 → 直接用同一套 .list-card > .li(38px 图标块、16.5px 粗体) */
|
||||
if (pc) pc.insertAdjacentHTML('afterend', S.postpartum
|
||||
? '<button class="bf-me born ripple" id="bfMe" data-bf-open="baby"><span class="bf-me-ic">' + BABY('#2F8A5E', 18) + '</span><span class="bf-me-t">宝宝已出生</span><span class="bf-me-v">去育儿首页</span><i class="bf-me-a">›</i></button>'
|
||||
: '<button class="bf-me ripple" id="bfMe" data-bf-open="reg"><span class="bf-me-ic">' + BABY('#F4593C', 18) + '</span><span class="bf-me-t">宝宝出生了?</span><span class="bf-me-v">切换到育儿模式</span><i class="bf-me-a">›</i></button>');
|
||||
? '<div class="list-card bf-me born" id="bfMe"><button class="li ripple" data-bf-open="baby"><span class="li-ico">' + BABY('#2F8A5E', 22) + '</span><span class="li-t">宝宝已出生</span><span class="li-v">去育儿首页</span><i class="chev">›</i></button></div>'
|
||||
: '<div class="list-card bf-me" id="bfMe"><button class="li ripple" data-bf-open="reg"><span class="li-ico">' + BABY('#F4593C', 22) + '</span><span class="li-t">宝宝出生了?</span><span class="li-v">切换到育儿模式</span><i class="chev">›</i></button></div>');
|
||||
}
|
||||
|
||||
function maybeAsk() {
|
||||
|
||||
@@ -244,5 +244,5 @@
|
||||
}
|
||||
/* feed.js 首页默认不加载(index.html 只引了 topics.js),这里按需拉一次 */
|
||||
if (window.GC_FEED) init();
|
||||
else { var fs = document.createElement('script'); fs.src = 'guangchang/feed.js?v=26110445'; fs.onload = fs.onerror = init; document.body.appendChild(fs); }
|
||||
else { var fs = document.createElement('script'); fs.src = 'guangchang/feed.js?v=26110446'; fs.onload = fs.onerror = init; document.body.appendChild(fs); }
|
||||
})();
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
(function () {
|
||||
var sec = document.getElementById('gcHome');
|
||||
if (!sec) return;
|
||||
var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = 'js/gch/v4.css?v=26110445';
|
||||
var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = 'js/gch/v4.css?v=26110446';
|
||||
document.head.appendChild(l);
|
||||
var s = document.createElement('script'); s.src = 'js/gch/v4.js?v=26110445';
|
||||
var s = document.createElement('script'); s.src = 'js/gch/v4.js?v=26110446';
|
||||
s.onload = function () { if (sec.querySelector('.g4-foot')) merge(); else sec.addEventListener('gc4-ready', merge, { once: true }); }; /* v4 要先拉 feed.js 才渲染 */
|
||||
document.body.appendChild(s);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if (/[?&]kit=0(?:&|$)/.test(location.search)) return;
|
||||
var box = document.getElementById('kit'), sec = document.getElementById('kitHome');
|
||||
if (!box || !sec) return;
|
||||
var V = '26110445';
|
||||
var V = '26110446';
|
||||
var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = 'js/kit.css?v=' + V; document.head.appendChild(l);
|
||||
document.documentElement.classList.add('has-kit');
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
postMessage 不是实时投递,微信在分享那一刻才派发,所以每次换内容都要再报一次;子页面没引 jweixin,这里按需加载。 */
|
||||
(function (g) {
|
||||
'use strict';
|
||||
var V = '26110445';
|
||||
var V = '26110446';
|
||||
var isWx = /MicroMessenger/i.test(navigator.userAgent || '');
|
||||
var waiting = [], loading = false;
|
||||
function ready(cb) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
· 别的脚本读 window.__mbUgc(true/false),等结果用 window.__mbUgcReady(Promise),中途变了会发 mb-ugc 事件。
|
||||
上一次拿到的值存本机 mmbox.ugc.v1,先按它渲染、接口回来再校正;接口不通就沿用上一次的值(从没拿到过 = 关)。
|
||||
11-05 首页「孕N周专属福利」开关 giftEnabled(后台同一处,默认开):false → <html>.gift-off 藏 .shelf.gift2,缓存 mmbox.gift.v1。
|
||||
预览站也跟这个开关(预览不跟的只是 UGC);正式版 main 是并进 UGC 那次请求里的,合并时以哪边为准都行、两边行为一致。
|
||||
预览站不跟这个开关、一直显示(11-05 用户:预览放出来,正式先隐藏);正式版 main 是并进 UGC 那次请求里的,合并时以哪边为准都行、两边行为一致。
|
||||
本文件在 <root>/js/ugc.js,必须同步 <script> 引入(要靠 document.currentScript 算首页地址)。 */
|
||||
(function () {
|
||||
var K = 'mmbox.ugc.v1', de = document.documentElement, me = document.currentScript, on = false;
|
||||
@@ -21,8 +21,10 @@
|
||||
'html.gift-off .shelf.gift2{display:none!important}';
|
||||
(document.head || de).appendChild(st);
|
||||
|
||||
try { de.classList.toggle('gift-off', localStorage.getItem('mmbox.gift.v1') === '0'); } catch (e) {}
|
||||
fetch('/api/mp/public/mama-box/config', { cache: 'no-store' })
|
||||
/* 11-05 用户:「预览页面要放出来,正式上线的可以先隐藏」→ 预览站不跟 giftEnabled,一直显示;正式站照开关 */
|
||||
var pvSite = /\/mama-box-preview\//.test(location.pathname);
|
||||
if (!pvSite) try { de.classList.toggle('gift-off', localStorage.getItem('mmbox.gift.v1') === '0'); } catch (e) {}
|
||||
if (!pvSite) fetch('/api/mp/public/mama-box/config', { cache: 'no-store' })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (j) {
|
||||
var g = !(j && j.result && j.result.giftEnabled === false);
|
||||
|
||||
Reference in New Issue
Block a user