From 41be920f59439af57aa4ced4c4d38951a2079455 Mon Sep 17 00:00:00 2001 From: ddrwode <34234@3来 34> Date: Tue, 10 Feb 2026 18:34:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=93=88=E5=93=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/js/forum-post-detail.js | 113 +++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 static/js/forum-post-detail.js diff --git a/static/js/forum-post-detail.js b/static/js/forum-post-detail.js new file mode 100644 index 0000000..63b93e1 --- /dev/null +++ b/static/js/forum-post-detail.js @@ -0,0 +1,113 @@ +// Forum post detail interactions: +// - Track CTA/related/recommendation interactions +// - Track comment submissions +// - Smooth-scroll for in-page comment jump links +(function () { + 'use strict'; + + var TRACK_ENDPOINT = '/api/event/track'; + var bodyEl = document.body; + if (!bodyEl) { + return; + } + + var rawPostId = bodyEl.getAttribute('data-post-id'); + var parsedPostId = Number(rawPostId); + var postId = Number.isFinite(parsedPostId) ? parsedPostId : null; + + function normalizeLabel(value) { + return String(value || '') + .trim() + .replace(/\s+/g, ' ') + .slice(0, 120); + } + + function sendTrack(eventName, label) { + var normalizedName = String(eventName || '').trim().toLowerCase(); + if (!normalizedName) { + return; + } + + var payload = { + event_name: normalizedName, + label: normalizeLabel(label), + post_id: postId, + page_path: (window.location && window.location.pathname) || '' + }; + var payloadText = JSON.stringify(payload); + + if (navigator.sendBeacon) { + try { + var ok = navigator.sendBeacon( + TRACK_ENDPOINT, + new Blob([payloadText], { type: 'application/json' }) + ); + if (ok) { + return; + } + } catch (err) { + // Fallback to fetch below. + } + } + + fetch(TRACK_ENDPOINT, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'same-origin', + keepalive: true, + body: payloadText + }).catch(function () { + // Silent failure: tracking should never block UX. + }); + } + + function resolveTrackNode(target) { + if (!target || typeof target.closest !== 'function') { + return null; + } + return target.closest('[data-track-event]'); + } + + document.addEventListener('click', function (evt) { + var node = resolveTrackNode(evt.target); + if (!node) { + return; + } + var eventName = node.getAttribute('data-track-event'); + var label = node.getAttribute('data-track-label') || node.textContent || ''; + sendTrack(eventName, label); + }); + + var commentForm = document.querySelector('form.comment-form'); + if (commentForm) { + commentForm.addEventListener('submit', function () { + sendTrack('post_detail_comment_submit', 'comment_form'); + }); + } + + var reducedMotionQuery = null; + if (typeof window.matchMedia === 'function') { + reducedMotionQuery = window.matchMedia('(prefers-reduced-motion: reduce)'); + } + var enableSmoothScroll = !(reducedMotionQuery && reducedMotionQuery.matches); + if (!enableSmoothScroll) { + return; + } + + var jumpLinks = document.querySelectorAll('a[href="#comments-panel"]'); + if (!jumpLinks.length) { + return; + } + + jumpLinks.forEach(function (link) { + link.addEventListener('click', function () { + var panel = document.getElementById('comments-panel'); + if (!panel) { + return; + } + window.setTimeout(function () { + panel.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, 0); + }); + }); +})();