feat(widget): 优化访客在线轨迹、GeoIP与多站点渠道
CI / Frontend (typecheck + lint + build) (push) Successful in 2m5s
CI / Backend (go vet + test) (push) Failing after 5m20s

This commit is contained in:
yml2213
2026-11-06 18:21:30 +08:00
parent 24fac1bcf1
commit 38d6fc1684
37 changed files with 1071 additions and 123 deletions
+31 -2
View File
@@ -34,6 +34,7 @@
var lastSentKey = '';
var lastSentAt = 0;
var routeTimer = null;
var presenceTimer = null;
var btn = document.createElement('button');
btn.type = 'button';
@@ -104,7 +105,7 @@
* 避免轨迹标题永远慢一页(URL 已是新页、title 仍是上一页)。
*/
function schedulePostPage(force) {
if (!open && !force) return;
if (!iframe && !force) return;
if (routeTimer) clearTimeout(routeTimer);
routeTimer = setTimeout(function () {
routeTimer = null;
@@ -123,8 +124,20 @@
iframe.src = buildEmbedURL();
iframe.addEventListener('load', function () {
schedulePostPage(true);
postHostVisibility();
});
panel.appendChild(iframe);
if (presenceTimer == null) {
presenceTimer = window.setInterval(function () {
if (!iframe || !iframe.contentWindow) return;
try {
iframe.contentWindow.postMessage({
type: 'kefu-host-tick',
visible: document.visibilityState === 'visible',
}, '*');
} catch (e) { /* ignore */ }
}, 15000);
}
}
function setOpen(next) {
@@ -140,6 +153,16 @@
}
}
function postHostVisibility() {
if (!iframe || !iframe.contentWindow) return;
try {
iframe.contentWindow.postMessage({
type: 'kefu-host-visibility',
visible: document.visibilityState === 'visible',
}, '*');
} catch (e) { /* ignore */ }
}
function shouldAutoOpenOnce() {
var key = 'kefu_widget_auto_opened_' + channelKey;
try {
@@ -158,13 +181,14 @@
}
// iframe 就绪后可再次同步宿主页
if (event.data.type === 'kefu-widget-ready') {
postHostVisibility();
schedulePostPage(true);
}
});
// —— SPA / 浏览器导航监听 ——
function onRouteMaybeChanged() {
if (!open) return;
if (!iframe) return;
schedulePostPage(false);
}
@@ -185,6 +209,11 @@
window.addEventListener('popstate', onRouteMaybeChanged);
window.addEventListener('hashchange', onRouteMaybeChanged);
document.addEventListener('visibilitychange', function () {
postHostVisibility();
if (document.visibilityState === 'visible') schedulePostPage(true);
});
window.addEventListener('pagehide', postHostVisibility);
// 标题可能异步更新
try {
var titleEl = document.querySelector('title');