896 lines
34 KiB
JavaScript
896 lines
34 KiB
JavaScript
(function () {
|
||
var section = document.querySelector(".detail-episodes");
|
||
if (!section) return;
|
||
|
||
var ranges = section.querySelectorAll(".detail-episode-range");
|
||
var episodes = section.querySelectorAll(".detail-episode-list .detail-episode");
|
||
if (!episodes.length) return;
|
||
if (!ranges.length) return;
|
||
|
||
function applyRange(start, end) {
|
||
episodes.forEach(function (el) {
|
||
var n = Number(el.getAttribute("data-ep"));
|
||
var inRange = !Number.isNaN(n) && n >= start && n <= end;
|
||
el.classList.toggle("is-range-hidden", !inRange);
|
||
});
|
||
}
|
||
|
||
function activate(btn) {
|
||
ranges.forEach(function (item) {
|
||
item.classList.toggle("detail-episode-range--active", item === btn);
|
||
});
|
||
applyRange(Number(btn.dataset.rangeStart), Number(btn.dataset.rangeEnd));
|
||
}
|
||
|
||
ranges.forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
activate(btn);
|
||
});
|
||
});
|
||
|
||
var active = section.querySelector(".detail-episode-range--active") || ranges[0];
|
||
activate(active);
|
||
})();
|
||
|
||
(function () {
|
||
var shareBtns = document.querySelectorAll("[data-detail-share]");
|
||
if (!shareBtns.length) return;
|
||
|
||
function toast(message, type) {
|
||
if (typeof window.showToast === "function") {
|
||
window.showToast(message, type);
|
||
return;
|
||
}
|
||
window.alert(message);
|
||
}
|
||
|
||
function resolvePlayletId(btn) {
|
||
var id = Number(btn.getAttribute("data-playlet-id") || 0);
|
||
if (id > 0) return id;
|
||
var host =
|
||
btn.closest("[data-playlet-id]") ||
|
||
document.querySelector("[data-play-player][data-playlet-id]") ||
|
||
document.querySelector("[data-playlet-id]");
|
||
if (host) {
|
||
id = Number(host.getAttribute("data-playlet-id") || 0);
|
||
}
|
||
return id > 0 ? id : 0;
|
||
}
|
||
|
||
function reportForwardHeat(playletId) {
|
||
if (!playletId || !window.HttpRequest) return;
|
||
window.HttpRequest.post("/api/playlet/forward/heat", { id: playletId }).catch(
|
||
function () {
|
||
/* 加热失败不影响分享体验 */
|
||
}
|
||
);
|
||
}
|
||
|
||
function fallbackCopy(text) {
|
||
var area = document.createElement("textarea");
|
||
area.value = text;
|
||
area.setAttribute("readonly", "");
|
||
area.style.cssText = "position:fixed;left:-9999px;top:0;opacity:0;";
|
||
document.body.appendChild(area);
|
||
area.focus();
|
||
area.select();
|
||
area.setSelectionRange(0, area.value.length);
|
||
var ok = false;
|
||
try {
|
||
ok = document.execCommand("copy");
|
||
} catch (e) {
|
||
ok = false;
|
||
}
|
||
document.body.removeChild(area);
|
||
return ok;
|
||
}
|
||
|
||
function copyPageUrl() {
|
||
var url = window.location.href;
|
||
if (navigator.clipboard && navigator.clipboard.writeText && window.isSecureContext) {
|
||
return navigator.clipboard.writeText(url).then(
|
||
function () {
|
||
return true;
|
||
},
|
||
function () {
|
||
return fallbackCopy(url);
|
||
}
|
||
);
|
||
}
|
||
return Promise.resolve(fallbackCopy(url));
|
||
}
|
||
|
||
shareBtns.forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
var playletId = resolvePlayletId(btn);
|
||
copyPageUrl()
|
||
.then(function (ok) {
|
||
if (ok) {
|
||
toast("链接已复制", "success");
|
||
reportForwardHeat(playletId);
|
||
} else {
|
||
toast("复制失败,请手动复制链接", "error");
|
||
}
|
||
})
|
||
.catch(function () {
|
||
toast("复制失败,请手动复制链接", "error");
|
||
});
|
||
});
|
||
});
|
||
})();
|
||
|
||
(function () {
|
||
// 付费剧集:不再站内解锁,统一引导下载 APP
|
||
var lockedEpisodes = document.querySelectorAll("[data-episode-locked]");
|
||
if (!lockedEpisodes.length) return;
|
||
|
||
lockedEpisodes.forEach(function (el) {
|
||
el.addEventListener("click", function (e) {
|
||
e.preventDefault();
|
||
if (typeof window.openDownloadApp === "function") {
|
||
window.openDownloadApp();
|
||
}
|
||
});
|
||
});
|
||
})();
|
||
|
||
(function () {
|
||
var grid = document.querySelector("[data-related-grid]");
|
||
var btn = document.querySelector("[data-related-refresh]");
|
||
if (!grid || !btn) return;
|
||
|
||
var section = document.querySelector("[data-related-section]");
|
||
var mobileMedia = window.matchMedia && window.matchMedia("(max-width: 767px)");
|
||
var isMobileDetail =
|
||
document.body.classList.contains("is-detail-page") &&
|
||
mobileMedia &&
|
||
mobileMedia.matches;
|
||
|
||
if (isMobileDetail) {
|
||
var PLACEHOLDER = "/static/images/placeholder.png?v=2";
|
||
var guessLikeData = [];
|
||
var guessOffset = 0;
|
||
var pageSize = 4;
|
||
|
||
grid.textContent = "";
|
||
btn.hidden = true;
|
||
if (section) section.hidden = true;
|
||
|
||
function detailHref(item) {
|
||
var slug = String((item && item.slug) || "").trim();
|
||
var id = Number(item && item.id);
|
||
var key = slug || (id > 0 ? String(id) : "");
|
||
return key ? "/detail/" + encodeURIComponent(key) + "/" : "#";
|
||
}
|
||
|
||
function firstCardTag(item) {
|
||
var tags = item && Array.isArray(item.tagNames) ? item.tagNames : [];
|
||
var themes = item && Array.isArray(item.themeNames) ? item.themeNames : [];
|
||
return String(tags[0] || themes[0] || "热门").trim();
|
||
}
|
||
|
||
function setCardCover(image, rawURL, title) {
|
||
var cover = String(rawURL || "").trim();
|
||
image.className = "poster-cover-img";
|
||
image.alt = title;
|
||
image.title = title;
|
||
image.addEventListener("error", function () {
|
||
image.classList.remove("lazy");
|
||
image.removeAttribute("data-src");
|
||
image.src = PLACEHOLDER;
|
||
}, { once: true });
|
||
if (
|
||
cover &&
|
||
typeof window.shouldDecryptImage === "function" &&
|
||
window.shouldDecryptImage(cover)
|
||
) {
|
||
image.classList.add("lazy");
|
||
image.src = PLACEHOLDER;
|
||
image.setAttribute("data-src", cover);
|
||
return;
|
||
}
|
||
image.src = cover || PLACEHOLDER;
|
||
}
|
||
|
||
function createGuessCard(item) {
|
||
var card = document.createElement("a");
|
||
var cover = document.createElement("div");
|
||
var image = document.createElement("img");
|
||
var episode = document.createElement("div");
|
||
var episodeText = document.createElement("div");
|
||
var body = document.createElement("div");
|
||
var title = document.createElement("div");
|
||
var subtitle = document.createElement("div");
|
||
var meta = document.createElement("div");
|
||
var tag = document.createElement("span");
|
||
var titleText = String((item && item.title) || "精彩短剧");
|
||
var totalEpisode = Math.max(0, Number(item && item.totalEpisode) || 0);
|
||
|
||
card.className = "poster-card";
|
||
card.href = detailHref(item);
|
||
card.setAttribute("aria-label", titleText);
|
||
cover.className = "poster-cover";
|
||
episode.className = "episode-badge";
|
||
episodeText.className = "text-white-xs";
|
||
body.className = "poster-card-body";
|
||
title.className = "poster-card-title";
|
||
subtitle.className = "poster-card-subtitle";
|
||
meta.className = "poster-card-meta";
|
||
tag.className = "poster-card-tag";
|
||
|
||
setCardCover(image, (item && (item.cover || item.banner)) || "", titleText);
|
||
episodeText.textContent = totalEpisode ? totalEpisode + "集" : "更新中";
|
||
title.textContent = titleText;
|
||
subtitle.textContent = String((item && item.desc) || "精彩内容等你来看");
|
||
tag.textContent = firstCardTag(item);
|
||
|
||
episode.appendChild(episodeText);
|
||
cover.appendChild(image);
|
||
cover.appendChild(episode);
|
||
meta.appendChild(tag);
|
||
body.appendChild(title);
|
||
body.appendChild(subtitle);
|
||
body.appendChild(meta);
|
||
card.appendChild(cover);
|
||
card.appendChild(body);
|
||
return card;
|
||
}
|
||
|
||
function renderMobileGuessLike() {
|
||
var count = Math.min(pageSize, guessLikeData.length);
|
||
grid.textContent = "";
|
||
if (section) section.hidden = count === 0;
|
||
btn.hidden = guessLikeData.length <= pageSize;
|
||
for (var index = 0; index < count; index += 1) {
|
||
grid.appendChild(
|
||
createGuessCard(guessLikeData[(guessOffset + index) % guessLikeData.length])
|
||
);
|
||
}
|
||
if (count && typeof window.initLazyImages === "function") {
|
||
window.initLazyImages(grid);
|
||
}
|
||
}
|
||
|
||
btn.addEventListener("click", function () {
|
||
if (guessLikeData.length > pageSize) {
|
||
guessOffset = (guessOffset + pageSize) % guessLikeData.length;
|
||
}
|
||
renderMobileGuessLike();
|
||
});
|
||
|
||
function loadMobileGuessLike() {
|
||
if (!window.HttpRequest || typeof window.HttpRequest.get !== "function") {
|
||
renderMobileGuessLike();
|
||
return;
|
||
}
|
||
window.HttpRequest.get("/api/playlet/hot-like")
|
||
.then(function (response) {
|
||
var source = response && response.data && response.data.guessLike;
|
||
guessLikeData = Array.isArray(source)
|
||
? source.filter(function (item) {
|
||
return item && (item.id || item.slug);
|
||
})
|
||
: [];
|
||
guessOffset = 0;
|
||
renderMobileGuessLike();
|
||
})
|
||
.catch(function () {
|
||
guessLikeData = [];
|
||
renderMobileGuessLike();
|
||
});
|
||
}
|
||
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", loadMobileGuessLike, { once: true });
|
||
} else {
|
||
loadMobileGuessLike();
|
||
}
|
||
return;
|
||
}
|
||
|
||
var cards = Array.prototype.slice.call(grid.querySelectorAll(".poster-card"));
|
||
if (cards.length <= 6) {
|
||
btn.hidden = true;
|
||
return;
|
||
}
|
||
var pageSize = 6;
|
||
var page = 0;
|
||
|
||
function render() {
|
||
var start = (page * pageSize) % cards.length;
|
||
cards.forEach(function (card) {
|
||
card.style.display = "none";
|
||
});
|
||
for (var i = 0; i < pageSize; i++) {
|
||
var card = cards[(start + i) % cards.length];
|
||
card.style.display = "";
|
||
grid.appendChild(card);
|
||
}
|
||
}
|
||
|
||
render();
|
||
btn.addEventListener("click", function () {
|
||
page += 1;
|
||
render();
|
||
});
|
||
})();
|
||
|
||
(function () {
|
||
// 注意:本文件在页面底部同步加载,早于 header 中 defer 的 request.js。
|
||
// 不能在此用 `if (!HttpRequest) return`,否则评论初始化会整段跳过。
|
||
// 实际请求在 DOMContentLoaded(HttpRequest 已就绪)后再发起。
|
||
|
||
var DEFAULT_AVATAR = "/static/images/avatar.png";
|
||
var PLACEHOLDER = "/static/images/placeholder.png?v=2";
|
||
|
||
function toast(message, type) {
|
||
if (typeof window.showToast === "function") {
|
||
window.showToast(message, type);
|
||
return;
|
||
}
|
||
window.alert(message);
|
||
}
|
||
|
||
function escapeHtml(s) {
|
||
return String(s == null ? "" : s)
|
||
.replace(/&/g, "&")
|
||
.replace(/</g, "<")
|
||
.replace(/>/g, ">")
|
||
.replace(/"/g, """);
|
||
}
|
||
|
||
function formatCommentTime(raw) {
|
||
if (!raw) return "";
|
||
var d = new Date(raw);
|
||
if (Number.isNaN(d.getTime())) return String(raw);
|
||
return (
|
||
d.getFullYear() +
|
||
"/" +
|
||
(d.getMonth() + 1) +
|
||
"/" +
|
||
d.getDate() +
|
||
" " +
|
||
String(d.getHours()).padStart(2, "0") +
|
||
":" +
|
||
String(d.getMinutes()).padStart(2, "0")
|
||
);
|
||
}
|
||
|
||
function formatRelativeTime(raw) {
|
||
if (!raw) return "";
|
||
var d = new Date(raw);
|
||
if (Number.isNaN(d.getTime())) return String(raw);
|
||
var diff = Date.now() - d.getTime();
|
||
if (diff < 0) diff = 0;
|
||
var minutes = Math.floor(diff / 60000);
|
||
if (minutes < 1) return "刚刚";
|
||
if (minutes < 60) return minutes + "分钟前";
|
||
var hours = Math.floor(minutes / 60);
|
||
if (hours < 24) return hours + "小时前";
|
||
var days = Math.floor(hours / 24);
|
||
if (days < 30) return days + "天前";
|
||
return formatCommentTime(raw);
|
||
}
|
||
|
||
function avatarURL(url) {
|
||
url = String(url || "").trim();
|
||
return url || DEFAULT_AVATAR;
|
||
}
|
||
|
||
function replyToggleLabel(expanded, count) {
|
||
count = Number(count || 0);
|
||
if (expanded) return "收起回复";
|
||
return "查看全部 " + count + " 条回复 ›";
|
||
}
|
||
|
||
function renderDetailComment(item, playPcMode) {
|
||
var avatar = avatarURL(item.userAvatar);
|
||
var avatarHtml = item.userAvatar
|
||
? '<img class="detail-comment-avatar lazy" src="' +
|
||
PLACEHOLDER +
|
||
'" data-src="' +
|
||
escapeHtml(avatar) +
|
||
'" alt="' +
|
||
escapeHtml((item.userName || "匿名用户") + "的头像") +
|
||
'" />'
|
||
: '<img class="detail-comment-avatar" src="' + DEFAULT_AVATAR + '" alt="匿名用户头像" />';
|
||
var textHtml = escapeHtml(item.text || "");
|
||
if (item.replyUserName) {
|
||
textHtml =
|
||
'<span class="detail-comment-reply-to">回复 @' +
|
||
escapeHtml(item.replyUserName) +
|
||
"</span> " +
|
||
textHtml;
|
||
}
|
||
var children = Array.isArray(item.children) ? item.children : [];
|
||
var replyCount = Number(item.commentCount || children.length || 0);
|
||
var repliesHtml = "";
|
||
if (children.length) {
|
||
var collapsed = children.length > 1;
|
||
repliesHtml =
|
||
'<div class="detail-comment-replies">' +
|
||
children
|
||
.map(function (child, index) {
|
||
var childText = escapeHtml(child.text || "");
|
||
if (child.replyUserName) {
|
||
childText =
|
||
'<span class="detail-comment-reply-to">@' +
|
||
escapeHtml(child.replyUserName) +
|
||
"</span> " +
|
||
childText;
|
||
}
|
||
return (
|
||
'<div class="detail-comment-reply-item" data-comment-id="' +
|
||
escapeHtml(child.id) +
|
||
'"' +
|
||
(collapsed && index > 0
|
||
? ' data-reply-collapsed-item hidden'
|
||
: "") +
|
||
">" +
|
||
'<span class="detail-comment-reply-name">' +
|
||
escapeHtml(child.userName || "匿名用户") +
|
||
":</span>" +
|
||
'<span class="detail-comment-reply-text">' +
|
||
childText +
|
||
"</span>" +
|
||
"</div>"
|
||
);
|
||
})
|
||
.join("") +
|
||
(replyCount > 1
|
||
? '<button class="detail-comment-replies-toggle" type="button" data-comment-replies-toggle data-reply-count="' +
|
||
escapeHtml(replyCount) +
|
||
'" aria-expanded="false">' +
|
||
replyToggleLabel(false, replyCount) +
|
||
"</button>"
|
||
: "") +
|
||
"</div>";
|
||
} else if (playPcMode && replyCount > 1) {
|
||
repliesHtml =
|
||
'<div class="detail-comment-replies"><button class="detail-comment-replies-toggle" type="button" data-comment-replies-toggle data-reply-count="' +
|
||
escapeHtml(replyCount) +
|
||
'" aria-expanded="false">' +
|
||
replyToggleLabel(false, replyCount) +
|
||
"</button></div>";
|
||
}
|
||
return (
|
||
'<div class="detail-comment" data-comment-id="' +
|
||
escapeHtml(item.id) +
|
||
'">' +
|
||
avatarHtml +
|
||
'<div class="detail-comment-body">' +
|
||
'<div class="detail-comment-name">' +
|
||
escapeHtml(item.userName || "匿名用户") +
|
||
"</div>" +
|
||
'<div class="detail-comment-text">' +
|
||
textHtml +
|
||
"</div>" +
|
||
'<div class="detail-comment-meta">' +
|
||
'<span class="detail-comment-time">' +
|
||
escapeHtml(formatCommentTime(item.createdAt)) +
|
||
"</span>" +
|
||
"</div>" +
|
||
repliesHtml +
|
||
"</div></div>"
|
||
);
|
||
}
|
||
|
||
function renderPlayComment(item) {
|
||
var avatar = avatarURL(item.userAvatar);
|
||
var commentId = item.id;
|
||
var children = Array.isArray(item.children) ? item.children : [];
|
||
var replyCount = Number(item.commentCount || children.length || 0);
|
||
var avatarHtml = item.userAvatar
|
||
? '<img class="play-comment-avatar lazy" src="' +
|
||
PLACEHOLDER +
|
||
'" data-src="' +
|
||
escapeHtml(avatar) +
|
||
'" alt="' +
|
||
escapeHtml((item.userName || "匿名用户") + "的头像") +
|
||
'" />'
|
||
: '<img class="play-comment-avatar" src="' + DEFAULT_AVATAR + '" alt="匿名用户头像" />';
|
||
var textHtml = escapeHtml(item.text || "");
|
||
if (item.replyUserName) {
|
||
textHtml =
|
||
'<span class="play-comment-reply-to">回复 @' +
|
||
escapeHtml(item.replyUserName) +
|
||
"</span> " +
|
||
textHtml;
|
||
}
|
||
var repliesHtml = "";
|
||
if (children.length) {
|
||
repliesHtml =
|
||
'<div class="play-comment-replies">' +
|
||
children
|
||
.map(function (child) {
|
||
return (
|
||
'<div class="play-comment-reply-line" data-comment-id="' +
|
||
escapeHtml(child.id) +
|
||
'">' +
|
||
'<span class="play-comment-reply-name">' +
|
||
escapeHtml(child.userName || "匿名用户") +
|
||
"</span>" +
|
||
(child.replyUserName
|
||
? '<span class="play-comment-reply-badge">回复</span><span class="play-comment-reply-name">' +
|
||
escapeHtml(child.replyUserName) +
|
||
"</span>"
|
||
: "") +
|
||
'<span class="play-comment-reply-text">' +
|
||
escapeHtml(child.text || "") +
|
||
"</span>" +
|
||
"</div>"
|
||
);
|
||
})
|
||
.join("") +
|
||
(replyCount > children.length
|
||
? '<button class="play-comment-replies-all" type="button" data-comment-replies="' +
|
||
escapeHtml(commentId) +
|
||
'">全部' +
|
||
escapeHtml(replyCount) +
|
||
"条评论</button>"
|
||
: "") +
|
||
"</div>";
|
||
} else if (replyCount > 0) {
|
||
repliesHtml =
|
||
'<button class="play-comment-more-replies" type="button" data-comment-replies="' +
|
||
escapeHtml(commentId) +
|
||
'">全部' +
|
||
escapeHtml(replyCount) +
|
||
'条评论<img src="/static/images/arrow_right.svg" alt="查看回复" /></button>';
|
||
}
|
||
return (
|
||
'<div class="play-comment-item" data-comment-id="' +
|
||
escapeHtml(commentId) +
|
||
'">' +
|
||
avatarHtml +
|
||
'<div class="play-comment-body">' +
|
||
'<div class="play-comment-name">' +
|
||
escapeHtml(item.userName || "匿名用户") +
|
||
"</div>" +
|
||
'<div class="play-comment-text">' +
|
||
textHtml +
|
||
"</div>" +
|
||
'<div class="play-comment-meta">' +
|
||
'<div class="play-comment-meta-left">' +
|
||
'<span class="play-comment-time">' +
|
||
escapeHtml(formatRelativeTime(item.createdAt)) +
|
||
"</span>" +
|
||
"</div>" +
|
||
"</div>" +
|
||
repliesHtml +
|
||
"</div></div>"
|
||
);
|
||
}
|
||
|
||
function renderComment(item, sheetMode, playPcMode) {
|
||
return sheetMode
|
||
? renderPlayComment(item)
|
||
: renderDetailComment(item, playPcMode);
|
||
}
|
||
|
||
function triggerLazy(root) {
|
||
if (typeof window.initLazyImages === "function") {
|
||
window.initLazyImages(root || document);
|
||
return;
|
||
}
|
||
if (typeof window.__lazyLoadImages === "function") {
|
||
window.__lazyLoadImages();
|
||
return;
|
||
}
|
||
if (window.LazyLoad && typeof window.LazyLoad.update === "function") {
|
||
window.LazyLoad.update();
|
||
}
|
||
}
|
||
|
||
function initCommentSection(section) {
|
||
// PC 播放页评论区仅桌面初始化;H5 sheet 始终初始化(避免宽屏加载后缩到手机仍卡在「加载中」)
|
||
if (section.classList.contains("play-comments")) {
|
||
if (window.matchMedia("(max-width: 767px)").matches) return;
|
||
}
|
||
|
||
var sheetRoot = section.closest("[data-play-comment-sheet]");
|
||
var sheetMode = !!sheetRoot || section.classList.contains("play-comment-sheet-body");
|
||
var playPcMode = section.classList.contains("play-comments");
|
||
var scope = sheetRoot || section;
|
||
var listEl = section.querySelector("[data-comment-list]");
|
||
var moreBtn = section.querySelector("[data-comment-more]");
|
||
var titleEl = section.querySelector("[data-comment-title]");
|
||
var sortBtns = scope.querySelectorAll("[data-comment-sort]");
|
||
var sheetTitle = sheetRoot
|
||
? sheetRoot.querySelector("[data-play-comment-title]")
|
||
: document.querySelector("[data-play-comment-title]");
|
||
var sideCount = document.querySelector("[data-play-comment-count]");
|
||
|
||
if (section.getAttribute("data-comment-inited") === "1") return;
|
||
section.setAttribute("data-comment-inited", "1");
|
||
|
||
var objectType = Number(section.getAttribute("data-comment-object-type") || 10);
|
||
var pageSize = Number(section.getAttribute("data-comment-size") || 10);
|
||
var sortDefault = Number(section.getAttribute("data-comment-sort-default") || 0);
|
||
var sortOrder = sortDefault === 2 || sortDefault === 1 ? sortDefault : sheetMode ? 2 : 1;
|
||
var page = 0;
|
||
var total = 0;
|
||
var loading = false;
|
||
|
||
function getObjectId() {
|
||
return Number(section.getAttribute("data-comment-object-id") || 0);
|
||
}
|
||
|
||
function commentItemSelector() {
|
||
return sheetMode ? ".play-comment-item" : ".detail-comment";
|
||
}
|
||
|
||
function updateTitleCount() {
|
||
if (titleEl) {
|
||
titleEl.textContent = total > 0 ? "评论 (" + total + ")" : "评论";
|
||
}
|
||
if (sheetTitle) {
|
||
sheetTitle.textContent = total > 0 ? total + "条评论" : "评论";
|
||
}
|
||
if (sideCount) {
|
||
sideCount.textContent = String(total);
|
||
}
|
||
}
|
||
|
||
function syncSortActive() {
|
||
sortBtns.forEach(function (item) {
|
||
var active = Number(item.getAttribute("data-comment-sort")) === sortOrder;
|
||
item.classList.toggle("detail-sort-btn--active", active);
|
||
item.classList.toggle("play-comment-sort-btn--active", active);
|
||
});
|
||
}
|
||
|
||
function setMoreVisible(show) {
|
||
if (!moreBtn) return;
|
||
if (show) {
|
||
moreBtn.hidden = false;
|
||
moreBtn.removeAttribute("hidden");
|
||
moreBtn.disabled = false;
|
||
} else {
|
||
moreBtn.hidden = true;
|
||
moreBtn.setAttribute("hidden", "");
|
||
moreBtn.disabled = false;
|
||
}
|
||
}
|
||
|
||
function showEmpty(text) {
|
||
var emptyClass = sheetMode
|
||
? "section-empty play-comment-empty"
|
||
: "section-empty";
|
||
listEl.innerHTML =
|
||
'<div class="' +
|
||
emptyClass +
|
||
'" data-comment-empty>' +
|
||
escapeHtml(text || "暂无评论") +
|
||
"</div>";
|
||
setMoreVisible(false);
|
||
}
|
||
|
||
function fetchPage(nextPage, replace) {
|
||
var objectId = getObjectId();
|
||
if (!objectId || loading) return Promise.resolve();
|
||
// detail.js 若早于 defer 的 request.js 执行,直接 get 会同步抛错且 loading 无法复位
|
||
if (!window.HttpRequest || typeof window.HttpRequest.get !== "function") {
|
||
if (replace) showEmpty("加载失败,请稍后重试");
|
||
return Promise.resolve();
|
||
}
|
||
loading = true;
|
||
if (moreBtn) moreBtn.disabled = true;
|
||
return window.HttpRequest.get("/api/comment/list", {
|
||
params: {
|
||
objectId: objectId,
|
||
objectType: objectType,
|
||
pageNum: nextPage,
|
||
pageSize: pageSize,
|
||
sortOrder: sortOrder,
|
||
},
|
||
})
|
||
.then(function (res) {
|
||
if (!res || res.code !== 200 || !res.data) {
|
||
throw new Error((res && (res.tip || res.msg)) || "加载失败");
|
||
}
|
||
var rows = res.data.list || [];
|
||
total = Number(res.data.totalCount != null ? res.data.totalCount : total);
|
||
page = Number(res.data.pageNum || nextPage);
|
||
updateTitleCount();
|
||
|
||
if (replace) {
|
||
if (!rows.length) {
|
||
showEmpty("暂无评论");
|
||
return;
|
||
}
|
||
listEl.innerHTML = rows
|
||
.map(function (row) {
|
||
return renderComment(row, sheetMode, playPcMode);
|
||
})
|
||
.join("");
|
||
} else if (rows.length) {
|
||
var empty = listEl.querySelector(
|
||
"[data-comment-empty],[data-comment-loading]"
|
||
);
|
||
if (empty) empty.remove();
|
||
listEl.insertAdjacentHTML(
|
||
"beforeend",
|
||
rows
|
||
.map(function (row) {
|
||
return renderComment(row, sheetMode, playPcMode);
|
||
})
|
||
.join("")
|
||
);
|
||
}
|
||
|
||
triggerLazy(listEl);
|
||
var loaded = listEl.querySelectorAll(commentItemSelector()).length;
|
||
var hasMore =
|
||
rows.length > 0 &&
|
||
rows.length >= pageSize &&
|
||
(total <= 0 || loaded < total);
|
||
setMoreVisible(hasMore);
|
||
})
|
||
.catch(function (err) {
|
||
if (replace || !listEl.querySelector(commentItemSelector())) {
|
||
showEmpty((err && err.message) || "加载失败,请稍后重试");
|
||
} else {
|
||
toast((err && err.message) || "加载失败,请稍后重试", "error");
|
||
if (moreBtn) moreBtn.disabled = false;
|
||
}
|
||
})
|
||
.finally(function () {
|
||
loading = false;
|
||
});
|
||
}
|
||
|
||
syncSortActive();
|
||
|
||
sortBtns.forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
var next = Number(btn.getAttribute("data-comment-sort") || 1);
|
||
if (next === sortOrder || loading) return;
|
||
sortOrder = next;
|
||
syncSortActive();
|
||
listEl.innerHTML =
|
||
'<div class="section-empty' +
|
||
(sheetMode ? " play-comment-empty" : "") +
|
||
'" data-comment-loading>评论加载中…</div>';
|
||
setMoreVisible(false);
|
||
fetchPage(1, true);
|
||
});
|
||
});
|
||
|
||
if (scope) {
|
||
scope.addEventListener("click", function (e) {
|
||
var repliesToggle =
|
||
e.target && e.target.closest
|
||
? e.target.closest("[data-comment-replies-toggle]")
|
||
: null;
|
||
if (!repliesToggle || !scope.contains(repliesToggle)) return;
|
||
e.preventDefault();
|
||
var repliesBox = repliesToggle.closest(".detail-comment-replies");
|
||
if (!repliesBox) return;
|
||
var expanded = repliesToggle.getAttribute("aria-expanded") === "true";
|
||
expanded = !expanded;
|
||
repliesToggle.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||
repliesToggle.textContent = replyToggleLabel(
|
||
expanded,
|
||
repliesToggle.getAttribute("data-reply-count")
|
||
);
|
||
var hiddenItems = repliesBox.querySelectorAll("[data-reply-collapsed-item]");
|
||
Array.prototype.forEach.call(hiddenItems, function (el) {
|
||
el.hidden = !expanded;
|
||
});
|
||
});
|
||
}
|
||
|
||
if (moreBtn) {
|
||
moreBtn.addEventListener("click", function () {
|
||
fetchPage(page + 1, false);
|
||
});
|
||
}
|
||
|
||
if (!listEl || !getObjectId()) {
|
||
if (listEl) showEmpty("暂无评论");
|
||
return;
|
||
}
|
||
|
||
section.addEventListener("play:reload-comments", function () {
|
||
listEl.innerHTML =
|
||
'<div class="section-empty' +
|
||
(sheetMode ? " play-comment-empty" : "") +
|
||
'" data-comment-loading>评论加载中…</div>';
|
||
setMoreVisible(false);
|
||
fetchPage(1, true);
|
||
});
|
||
|
||
fetchPage(1, true);
|
||
}
|
||
|
||
// 等 DOMContentLoaded:保证 header 中 defer 的 request.js 已执行
|
||
function bootCommentSections() {
|
||
if (!window.HttpRequest || typeof window.HttpRequest.get !== "function") {
|
||
// 极端情况:再等 window.load 一次
|
||
if (!bootCommentSections._retried) {
|
||
bootCommentSections._retried = true;
|
||
window.addEventListener("load", bootCommentSections, { once: true });
|
||
}
|
||
return;
|
||
}
|
||
document.querySelectorAll(".detail-comments").forEach(initCommentSection);
|
||
}
|
||
if (document.readyState === "loading") {
|
||
document.addEventListener("DOMContentLoaded", bootCommentSections, { once: true });
|
||
} else {
|
||
bootCommentSections();
|
||
}
|
||
})();
|
||
|
||
/** H5 返回:避免 play ↔ detail 互相压栈导致死循环 */
|
||
(function () {
|
||
var nodes = document.querySelectorAll("[data-nav-back], .play-h5-back, .detail-h5-back");
|
||
if (!nodes.length) return;
|
||
|
||
function pathOf(url) {
|
||
try {
|
||
return new URL(url, window.location.origin).pathname || "";
|
||
} catch (e) {
|
||
return "";
|
||
}
|
||
}
|
||
|
||
function isPlayPath(pathname) {
|
||
return pathname === "/play";
|
||
}
|
||
|
||
function isDetailPath(pathname) {
|
||
return pathname === "/detail";
|
||
}
|
||
|
||
function resolveFallback(el) {
|
||
var fallback = el.getAttribute("data-nav-fallback") || "";
|
||
if (fallback) return fallback;
|
||
var href = el.getAttribute("href") || "";
|
||
if (href && href.indexOf("javascript:") !== 0) return href;
|
||
return "/";
|
||
}
|
||
|
||
nodes.forEach(function (el) {
|
||
el.addEventListener("click", function (e) {
|
||
var fallback = resolveFallback(el);
|
||
var ref = document.referrer || "";
|
||
var sameOrigin = !!ref && ref.indexOf(window.location.origin) === 0;
|
||
var refPath = sameOrigin ? pathOf(ref) : "";
|
||
var here = window.location.pathname || "";
|
||
|
||
// 详情页若上一页是播放页,history.back 会回到播放页形成循环
|
||
if (isDetailPath(here) && isPlayPath(refPath)) {
|
||
e.preventDefault();
|
||
window.location.href = fallback || "/";
|
||
return;
|
||
}
|
||
|
||
// 播放页:有同站来源时回退历史(通常回到详情),否则走详情/首页兜底
|
||
if (isPlayPath(here)) {
|
||
e.preventDefault();
|
||
if (sameOrigin && refPath && ref !== window.location.href) {
|
||
window.history.back();
|
||
return;
|
||
}
|
||
window.location.href = fallback || "/";
|
||
return;
|
||
}
|
||
|
||
// 其它带 data-nav-back 的页面
|
||
if (sameOrigin && refPath && ref !== window.location.href) {
|
||
e.preventDefault();
|
||
window.history.back();
|
||
return;
|
||
}
|
||
|
||
var href = el.getAttribute("href") || "";
|
||
if (!href || href.indexOf("javascript:") === 0) {
|
||
e.preventDefault();
|
||
window.location.href = fallback || "/";
|
||
}
|
||
});
|
||
});
|
||
})();
|