Files
mama-box/js/pv.js

138 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 兜爸心选 · 页面访问记录(2026-11-07)
推送效果看板要看「推送打开后用户看了哪些页面」,用户同意做。后端 box_app:POST /api/mp/public/mama-box/pv(公开上报),
看板走 POST /api/mp/public/mama-box/pageviews/query(X-Api-Key)。说明见 box_app services/mama_box_pageview_serv.py。
一次「看一页」= 一个 visitId:进来 0.8 秒后报一条(停留 0),之后每 15 秒、切到后台、离开时报一次停留时长(只算页面在前台的时间)。
同一页里换内容也算新的一页:广场切笔记 / 话题 / 分类(pushState)、首页开关星空页(replaceState ?wh=1)—— 这里接管 history 自动识别,页面不用改。
首页 + 孕妈广场 + 测一测 + 专题页 / 计算器都引本文件(和 js/last-sub.js 放一起);新子页面记得加 script。
预览站 / 正式站由后端按路径分(/mama-box-preview/ → preview),这里不管。 */
(function () {
'use strict';
if (window.__mbPV) return;
window.__mbPV = 1;
var API = '/api/mp/public/mama-box/pv';
var BEAT = 15000;
var CAT_NAME = { family: '家庭婚姻', work: '职场方向', baby: '孕育经验' };
function param(k) {
var m = ((location.hash || '') + '&' + (location.search || '')).match(new RegExp('[#?&]' + k + '=([^&]*)'));
try { return m ? decodeURIComponent(m[1]).split('?')[0] : ''; } catch (e) { return ''; }
}
function who() {
if (window.mbGate && window.mbGate.out) return { openid: '', unionid: '' }; /* 11-07 退出登录 = 访客 */
var o = param('openid'), u = param('unionid');
if (!o) {
try {
var c = JSON.parse(sessionStorage.getItem('mmbox.identity') || 'null');
if (c && c.openid && (!c.at || Date.now() - c.at < 432e5)) { o = c.openid; u = u || c.unionid || ''; }
} catch (e) {}
}
return { openid: o, unionid: u };
}
/* 当前地址 → 是哪一页。base = 站点根(/mama-box-v2/ 或 /mama-box-preview/),rel = 之后的部分 */
function where() {
var p = location.pathname.replace(/index\.html$/, '');
var m = p.match(/^(\/[^/]+\/)(.*)$/) || [0, '/', ''];
var rel = m[2], q = new URLSearchParams(location.search), r = { group: 'other', page: rel || 'home', title: document.title || '' };
var T = function (v) { return String(v || '').replace(/\s*·\s*(测一测|孕妈广场)$/, ''); };
if (!rel) {
if (q.get('wh') === '1') { r.group = 'whisper'; r.page = 'whisper'; r.title = '孕妈悄悄话·星空页'; }
else { r.group = 'home'; r.page = 'home'; r.title = '妈妈盒子首页'; }
} else if (rel === 'guangchang/ceshi/') {
var id = q.get('id') || '', t = (window.GC_TESTS || []).filter(function (x) { return x.id === id; })[0];
r.group = 'ceshi'; r.page = id ? 'ceshi/test' : 'ceshi/list'; r.testId = id;
r.testTitle = t ? t.title : (id ? T(document.title) : '');
r.title = id ? '测一测·' + (r.testTitle || id) : '测一测·列表';
} else if (rel === 'guangchang/mine/') {
r.group = 'plaza'; r.page = 'plaza/mine'; r.title = '孕妈广场·我的投稿';
} else if (rel === 'guangchang/') {
var n = q.get('n') || '', tp = q.get('t') || '', c = q.get('c') || '';
var tid = tp || (n ? n.replace(/-\d+$/, '') : '');
var topic = (window.GC_TOPICS || []).filter(function (x) { return x.id === tid; })[0];
r.group = 'plaza';
if (tid) { r.topicId = tid; r.topicTitle = topic ? topic.name : ''; }
if (n) {
var d = window.GC_DATA && GC_DATA[tid], i = +(n.match(/-(\d+)$/) || [0, 0])[1];
r.page = 'plaza/note'; r.noteId = n; r.noteTitle = d && d.notes && d.notes[i - 1] ? d.notes[i - 1].title : '';
r.title = '孕妈广场·笔记详情';
} else if (tp) { r.page = 'plaza/topic'; r.title = '孕妈广场·话题'; }
else if (c === 'ceshi') { r.group = 'ceshi'; r.page = 'ceshi/list'; r.title = '测一测·列表'; }
else if (c) { r.page = 'plaza/cat'; r.title = '孕妈广场·' + (CAT_NAME[c] || c); }
else if (q.get('write') === '1') { r.page = 'plaza/write'; r.title = '孕妈广场·写笔记'; }
else if (q.get('fav') === '1') { r.page = 'plaza/fav'; r.title = '孕妈广场·我的收藏'; }
else if (q.get('mine') === '1') { r.page = 'plaza/mine'; r.title = '孕妈广场·我的投稿'; }
else { r.page = 'plaza/home'; r.title = '孕妈广场'; }
} else if (/^topic\/[a-z0-9_-]+\/$/.test(rel)) {
r.group = 'topic'; r.page = rel.replace(/\/$/, ''); r.title = T(document.title) || r.page;
}
r.key = r.page + '|' + (r.noteId || '') + '|' + (r.topicId || '') + '|' + (r.testId || '');
/* 净地址:不带身份(openid/unionid 在 hash,不记) */
r.path = location.pathname + (location.search || '').replace(/([?&])(openid|unionid)=[^&]*/g, '$1').replace(/[?&]+$/, '');
return r;
}
function send(o) {
var s = JSON.stringify(o);
try { if (navigator.sendBeacon && navigator.sendBeacon(API, new Blob([s], { type: 'text/plain' }))) return; } catch (e) {}
try { fetch(API, { method: 'POST', body: s, keepalive: true, headers: { 'Content-Type': 'text/plain' } }).catch(function () {}); } catch (e) {}
}
function vid() { return Date.now().toString(36) + Math.random().toString(36).slice(2, 10) + Math.random().toString(36).slice(2, 6); }
var cur = null, timer = 0;
function dur() {
if (!cur) return 0;
return cur.acc + (cur.shownAt ? Date.now() - cur.shownAt : 0);
}
function beat() {
if (!cur || !cur.sent) return;
var d = dur();
if (d - cur.lastDur < 1000) return;
cur.lastDur = d;
var w = who();
send({ visitId: cur.id, durationMs: d, openid: w.openid, unionid: w.unionid });
}
function first(c) {
if (c !== cur || c.sent) return;
var r = where(); /* 晚 0.8 秒再取:专题页 / 测试页的标题、广场数据那时才就绪 */
if (r.key !== c.r.key) r = c.r;
var w = who();
c.sent = true;
send({
visitId: c.id, openid: w.openid, unionid: w.unionid, page: r.page, pageGroup: r.group, pageTitle: r.title,
noteId: r.noteId || '', noteTitle: r.noteTitle || '', topicId: r.topicId || '', topicTitle: r.topicTitle || '',
testId: r.testId || '', testTitle: r.testTitle || '', path: c.r.path, enteredAt: c.at, durationMs: dur()
});
}
function close() {
if (!cur) return;
if (cur.sent) beat(); else if (dur() >= 800) first(cur);
cur = null;
}
function open() {
var r = where();
if (cur && cur.r.key === r.key) return;
close();
var c = cur = { id: vid(), r: r, at: Date.now(), acc: 0, shownAt: document.hidden ? 0 : Date.now(), sent: false, lastDur: 0 };
setTimeout(function () { first(c); }, 800);
}
['pushState', 'replaceState'].forEach(function (k) {
var f = history[k];
if (typeof f !== 'function') return;
history[k] = function () { var x = f.apply(this, arguments); try { setTimeout(open, 0); } catch (e) {} return x; };
});
window.addEventListener('popstate', function () { setTimeout(open, 0); });
document.addEventListener('visibilitychange', function () {
if (!cur) return;
if (document.hidden) { if (cur.shownAt) { cur.acc += Date.now() - cur.shownAt; cur.shownAt = 0; } beat(); }
else if (!cur.shownAt) cur.shownAt = Date.now();
});
window.addEventListener('pagehide', close);
window.addEventListener('pageshow', function (e) { if (e.persisted) open(); }); /* 从后退缓存回来 = 又看一次 */
timer = setInterval(function () { if (!document.hidden) beat(); }, BEAT);
open();
})();