From 4fe4d79da03c351536f95937d7add122a82f4059 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 12 Jul 2026 14:39:39 +0800 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20rehydrate=20=E6=A0=B9=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=85=BC=E5=AE=B9=20Element=20=E6=97=A0=20getElementB?= =?UTF-8?q?yId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 评论排序/点赞在 AJAX rehydrate 时 root 为 Element,调用 getElementById 抛 TypeError;改为 Document/Element 安全查找,并补上评论排序委托点击。 --- assets/js/core/article.js | 20 +++++++++++++++-- assets/js/core/comments.js | 46 +++++++++++++++++++++++++++++++++----- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/assets/js/core/article.js b/assets/js/core/article.js index cd5f4bb6..f4e02461 100644 --- a/assets/js/core/article.js +++ b/assets/js/core/article.js @@ -142,10 +142,26 @@ button.classList.toggle("is-loading", !!busy); } + function findInScope(scope, id) { + scope = scope || document; + if (!scope) return null; + if (scope.nodeType === 9) { + return scope.getElementById(id); + } + if (scope.nodeType === 1) { + if (scope.id === id) return scope; + return typeof scope.querySelector === "function" + ? scope.querySelector("#" + id) + : null; + } + return null; + } + function initInteractionBar(root) { var scope = root || document; - var likeBtn = scope.getElementById("action-like"); - var favBtn = scope.getElementById("action-favorite"); + // Element roots (AJAX rehydrate) do not implement getElementById + var likeBtn = findInScope(scope, "action-like"); + var favBtn = findInScope(scope, "action-favorite"); if (likeBtn && likeBtn.dataset.aksrtInteractionBound) return; if (favBtn && favBtn.dataset.aksrtInteractionBound) return; diff --git a/assets/js/core/comments.js b/assets/js/core/comments.js index 1670db93..f4bc019d 100644 --- a/assets/js/core/comments.js +++ b/assets/js/core/comments.js @@ -555,18 +555,33 @@ } /* ====== 评论排序(最新 / 最早) ====== */ + /** + * Locate #id within a rehydrate root. + * Document has getElementById; Element roots (AJAX panels) only have querySelector. + */ + function findInScope(scope, id) { + scope = scope || document; + if (!scope) return null; + if (scope.nodeType === 9) { + return scope.getElementById(id); + } + if (scope.nodeType === 1) { + if (scope.id === id) return scope; + return typeof scope.querySelector === "function" + ? scope.querySelector("#" + id) + : null; + } + return null; + } + function initCommentOrder(root) { var scope = root || document; - var commentsArea = scope.getElementById("comments"); + var commentsArea = findInScope(scope, "comments"); if (!commentsArea) return; + // Event delegation survives filter HTML replacement after AJAX rehydrate. if (commentsArea.dataset.orderInit === "1") return; commentsArea.dataset.orderInit = "1"; - function getPaginationEl(root) { - if (!root) return null; - return root.querySelector(".aksrt-comment-pagination, .comment-navigation"); - } - function renderLoadingState() { var listContainer = commentsArea.querySelector("#comment-list"); if (!listContainer) return; @@ -625,6 +640,25 @@ window.location.href = url.toString(); }); } + + commentsArea.addEventListener("click", function (e) { + var target = e.target; + if (!target || typeof target.closest !== "function") return; + + // 「只看作者」同时带 comment-orderby,需优先于排序按钮判断 + var authorBtn = target.closest(".comment-author-filter"); + if (authorBtn && commentsArea.contains(authorBtn)) { + e.preventDefault(); + applyAuthorFilter(authorBtn.getAttribute("data-author-only") || "0"); + return; + } + + var orderBtn = target.closest(".comment-orderby[data-order]"); + if (orderBtn && commentsArea.contains(orderBtn)) { + e.preventDefault(); + applyCommentOrder(orderBtn.getAttribute("data-order") || "newest"); + } + }); } window.AksrtFrontend.register("aksrt-comment-system", function () { initCommentSystem(); });