Files
web_huangguo2_h5/app/static/js/pages/playComments.js
T
2026-09-29 15:30:33 +07:00

261 lines
7.8 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.
// 播放页评论:只读列表 + 「查看更多评论」追加翻页
(function () {
var commentsRoot = document.querySelector("[data-play-comments]");
if (!commentsRoot) return;
var listEl = document.querySelector("[data-comment-list]");
var totalEl = document.querySelector("[data-comment-total-label]");
var moreBtn = document.querySelector("[data-comment-more]");
var loadingMore = false;
var PAGE_SIZE = 4;
function toast(message, type) {
if (typeof window.showToast === "function") {
window.showToast(message, type);
return;
}
}
function toInt(v, fallback) {
var n = parseInt(v, 10);
return isNaN(n) ? fallback || 0 : n;
}
function escapeHtml(s) {
return String(s == null ? "" : s)
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function getPageSize() {
return Math.max(
1,
toInt(commentsRoot.getAttribute("data-comment-size"), PAGE_SIZE)
);
}
function getPage() {
return Math.max(
1,
toInt(commentsRoot.getAttribute("data-comment-page"), 1)
);
}
function getLoaded() {
if (!listEl) return 0;
return listEl.querySelectorAll(".play-comment:not(.play-comment--empty)").length;
}
function setPagerState(page, loaded, total) {
if (page != null) commentsRoot.setAttribute("data-comment-page", String(page));
if (loaded != null) commentsRoot.setAttribute("data-comment-loaded", String(loaded));
if (total != null) commentsRoot.setAttribute("data-comment-total", String(total));
syncMoreButton(total != null ? total : toInt(commentsRoot.getAttribute("data-comment-total"), 0));
}
function syncMoreButton(total) {
if (!moreBtn) return;
var loaded = getLoaded();
var hasMore = total > loaded;
if (hasMore) {
moreBtn.hidden = false;
moreBtn.removeAttribute("hidden");
} else {
moreBtn.hidden = true;
moreBtn.setAttribute("hidden", "");
}
}
function formatTime(raw) {
var s = String(raw || "").trim();
if (!s) return "刚刚";
var d = new Date(s);
if (isNaN(d.getTime())) return s;
return (
d.getFullYear() +
"/" +
(d.getMonth() + 1) +
"/" +
d.getDate() +
" " +
String(d.getHours()).padStart(2, "0") +
":" +
String(d.getMinutes()).padStart(2, "0")
);
}
function renderCommentItem(item) {
item = item || {};
var avatar = String(item.userAvatar || "").trim();
var name = escapeHtml(item.userName || "匿名用户");
var text = escapeHtml(item.text || "");
var time = escapeHtml(formatTime(item.createdAt));
var like = toInt(item.countLike, 0);
var avatarHtml = avatar
? '<img class="play-comment__avatar lazy" src="/static/images/placeholder.png?v=2" data-src="' +
escapeHtml(avatar) +
'" alt="" loading="lazy" decoding="async">'
: '<img class="play-comment__avatar" src="/static/images/placeholder.png?v=2" data-src="/static/images/profile/avatar.png" alt="" loading="lazy" decoding="async">';
var children = Array.isArray(item.children) ? item.children : [];
var replies = children
.map(function (child) {
var cName = escapeHtml(child.userName || "用户");
var replyTo = child.replyUserName
? " 回复 " + escapeHtml(child.replyUserName)
: "";
return (
'<div class="play-comment__reply">' +
cName +
replyTo +
":" +
escapeHtml(child.text || "") +
"</div>"
);
})
.join("");
var commentId = escapeHtml(item.id || "");
return (
'<li class="play-comment" data-comment-id="' +
commentId +
'">' +
avatarHtml +
'<div class="play-comment__body">' +
'<div class="play-comment__meta">' +
'<span class="play-comment__name">' +
name +
"</span>" +
'<span class="play-comment__time">' +
time +
"</span>" +
"</div>" +
'<p class="play-comment__text">' +
text +
"</p>" +
replies +
'<div class="play-comment__actions">' +
'<span class="play-comment__action">' +
'<img class="icon" src="/static/images/placeholder.png?v=2" data-src="/static/images/heart.svg" alt="" loading="lazy" decoding="async">' +
"<span>" +
escapeHtml(like) +
"</span>" +
"</span>" +
"</div></div></li>"
);
}
function getLoadedIds() {
var ids = Object.create(null);
if (!listEl) return ids;
listEl.querySelectorAll(".play-comment[data-comment-id]").forEach(function (el) {
var id = String(el.getAttribute("data-comment-id") || "").trim();
if (id) ids[id] = true;
});
return ids;
}
function updateTotal(n) {
if (!totalEl) return;
totalEl.textContent = n > 0 ? n + " 条" : "暂无评论";
}
// 下一页追加到现有列表底部,不替换已展示评论。
function appendList(list, totalCount) {
if (!listEl) return;
list = Array.isArray(list) ? list : [];
var total =
typeof totalCount === "number"
? totalCount
: toInt(commentsRoot.getAttribute("data-comment-total"), 0);
if (typeof totalCount === "number") {
updateTotal(totalCount);
}
if (!list.length) {
setPagerState(getPage(), getLoaded(), total);
return;
}
var empty = listEl.querySelector(".play-comment--empty");
if (empty) empty.remove();
var existing = getLoadedIds();
var fresh = list.filter(function (item) {
var id = String((item && item.id) || "").trim();
return id && !existing[id];
});
if (!fresh.length) {
setPagerState(getPage(), getLoaded(), total);
return;
}
var wrap = document.createElement("ul");
wrap.innerHTML = fresh.map(renderCommentItem).join("");
var nodes = [];
while (wrap.firstChild) {
nodes.push(wrap.firstChild);
listEl.appendChild(wrap.firstChild);
}
if (typeof window.initLazyImages === "function") {
nodes.forEach(function (node) {
if (node && node.nodeType === 1) window.initLazyImages(node);
});
window.initLazyImages(listEl);
}
setPagerState(getPage(), getLoaded(), total);
}
function fetchCommentPage(pageNum) {
if (!window.HttpRequest || typeof window.HttpRequest.get !== "function") {
return Promise.reject(new Error("评论服务未就绪"));
}
var objectId = toInt(commentsRoot.getAttribute("data-object-id"), 0);
var objectType = toInt(commentsRoot.getAttribute("data-object-type"), 10);
if (objectId <= 0) return Promise.reject(new Error("缺少评论对象"));
var pageSize = getPageSize();
return window.HttpRequest.get("/api/comment/list", {
params: {
objectId: objectId,
objectType: objectType,
pageNum: pageNum,
pageSize: pageSize,
sortOrder: 1,
},
}).then(function (res) {
if (!res || Number(res.code) !== 200 || !res.data) {
throw new Error((res && (res.tip || res.msg)) || "加载失败");
}
return res.data;
});
}
function loadMoreComments() {
if (loadingMore || !moreBtn) return;
var nextPage = getPage() + 1;
loadingMore = true;
moreBtn.disabled = true;
fetchCommentPage(nextPage)
.then(function (data) {
var list = data.list || [];
var total = toInt(data.totalCount, 0);
commentsRoot.setAttribute("data-comment-page", String(nextPage));
// 只追加,绝不 renderList 整表替换
appendList(list, total);
})
.catch(function (err) {
toast((err && err.message) || "加载失败,请稍后重试", "error");
})
.finally(function () {
loadingMore = false;
if (moreBtn) moreBtn.disabled = false;
});
}
if (moreBtn) {
moreBtn.addEventListener("click", function (event) {
event.preventDefault();
loadMoreComments();
});
}
})();