logo和配置修改

This commit is contained in:
谢宇宁
2026-09-23 16:50:34 +07:00
parent bef9f8b4ed
commit 0db8087765
163 changed files with 393 additions and 20366 deletions
-307
View File
@@ -1,307 +0,0 @@
(function () {
var mask = document.getElementById("coinDialog");
if (!mask) return;
var balanceEls = mask.querySelectorAll("[data-coin-balance]");
var costEls = mask.querySelectorAll("[data-coin-cost]");
var payBtn = mask.querySelector("[data-coin-dialog-pay]");
var loading = false;
var paying = false;
function formatCoins(n) {
var num = Number(n);
if (!Number.isFinite(num) || num < 0) num = 0;
return String(Math.floor(num));
}
function setBalance(n) {
var text = formatCoins(n);
balanceEls.forEach(function (el) {
el.textContent = text;
});
}
function setCost(n) {
var text = formatCoins(n);
costEls.forEach(function (el) {
el.textContent = text;
});
}
function toast(message, type) {
if (typeof window.showToast === "function") {
window.showToast(message, type);
return;
}
window.alert(message);
}
function openLogin() {
var loginOpen = document.querySelector("[data-login-dialog-open]");
if (loginOpen) loginOpen.click();
}
function goToCoinRecharge() {
window.location.href = "/deposit/coin/";
}
function isInsufficientBalance(res) {
if (!res) return false;
if (Number(res.code) === 20004) return true;
var message = String(res.tip || res.msg || "");
return /(?:金币|余额).{0,6}不足|不足.{0,6}(?:金币|余额)/.test(message);
}
function resolvePlayletId(trigger) {
if (trigger) {
var fromTrigger = Number(trigger.getAttribute("data-playlet-id") || 0);
if (fromTrigger > 0) return fromTrigger;
}
var fromMask = Number(mask.getAttribute("data-playlet-id") || 0);
if (fromMask > 0) return fromMask;
var playPage =
document.querySelector("[data-play-page]") ||
document.querySelector(".play-page");
if (playPage) {
var fromPage = Number(playPage.getAttribute("data-playlet-id") || 0);
if (fromPage > 0) return fromPage;
}
var player = document.querySelector("[data-play-player]");
if (player) {
var fromPlayer = Number(player.getAttribute("data-playlet-id") || 0);
if (fromPlayer > 0) return fromPlayer;
}
var likeBtn = document.querySelector("[data-playlet-id]");
if (likeBtn) {
var fromBtn = Number(likeBtn.getAttribute("data-playlet-id") || 0);
if (fromBtn > 0) return fromBtn;
}
return 0;
}
function resolvePlayletSlug(trigger) {
if (trigger) {
var fromTrigger = String(trigger.getAttribute("data-playlet-slug") || "").trim();
if (fromTrigger) return fromTrigger;
}
var fromMask = String(mask.getAttribute("data-playlet-slug") || "").trim();
if (fromMask) return fromMask;
var playPage =
document.querySelector("[data-play-page]") ||
document.querySelector(".play-page");
if (playPage) {
var fromPage = String(playPage.getAttribute("data-playlet-slug") || "").trim();
if (fromPage) return fromPage;
}
return "";
}
function buildPlayHref(playletId, chapterId) {
if (!playletId || !chapterId) return "";
var slug = resolvePlayletSlug(null);
var key = slug || String(playletId);
return "/play/" + encodeURIComponent(key) + "/" + chapterId + "/";
}
function isOnPlayPage() {
return !!(
document.querySelector("[data-play-page]") ||
document.querySelector(".play-page")
);
}
function afterUnlockSuccess(playletId, chapterId, data) {
var detail = {
playletId: playletId,
chapterId: chapterId,
balance: data && typeof data.balance === "number" ? data.balance : null,
canWatch: !!(data && data.canWatch),
unlocked: !!(data && data.unlocked),
};
window.dispatchEvent(
new CustomEvent("play:chapter-unlocked", { detail: detail })
);
if (
isOnPlayPage() &&
typeof window.playAfterChapterUnlock === "function"
) {
window.playAfterChapterUnlock(detail);
return;
}
var href = buildPlayHref(playletId, chapterId);
if (href) {
window.location.href = href;
}
}
function setPaying(on) {
paying = !!on;
if (!payBtn) return;
payBtn.disabled = paying;
payBtn.classList.toggle("is-loading", paying);
payBtn.setAttribute("aria-busy", paying ? "true" : "false");
}
function fetchBalance() {
if (!window.HttpRequest) {
setBalance(0);
return Promise.resolve(0);
}
return window.HttpRequest.get("/api/auth/getInfo")
.then(function (res) {
if (!res || res.code !== 200 || !res.data) {
if (res && res.code === 401) {
openLogin();
}
throw new Error((res && (res.tip || res.msg)) || "获取余额失败");
}
var recharge = res.data.recharge;
setBalance(recharge);
if (window.CookieUtil && CookieUtil.setAuthSession) {
CookieUtil.setAuthSession(res.data);
}
return Number(recharge) || 0;
})
.catch(function (err) {
setBalance(0);
toast((err && err.message) || "获取余额失败", "error");
return 0;
});
}
function unlockAndPlay() {
if (paying) return;
if (!window.HttpRequest) {
toast("网络模块未就绪", "error");
return;
}
var chapterId = Number(mask.getAttribute("data-chapter-id") || 0);
var playletId = Number(mask.getAttribute("data-playlet-id") || 0);
var cost = Number(mask.getAttribute("data-single-coins") || 0);
var balance = Number(
(balanceEls[0] && balanceEls[0].textContent) || 0
);
if (!chapterId || !playletId) {
toast("缺少剧集信息,请刷新后重试", "error");
return;
}
if (Number.isFinite(balance) && Number.isFinite(cost) && balance < cost) {
goToCoinRecharge();
return;
}
setPaying(true);
window.HttpRequest.post("/api/playlet/chapter/unlock", {
chapterId: chapterId,
playletId: playletId,
})
.then(function (res) {
if (!res || res.code !== 200) {
if (res && res.code === 401) {
closeDialog();
openLogin();
return;
}
if (isInsufficientBalance(res)) {
goToCoinRecharge();
return;
}
throw new Error((res && (res.tip || res.msg)) || "解锁失败");
}
var data = res.data || {};
if (typeof data.balance === "number") {
setBalance(data.balance);
if (window.CookieUtil && CookieUtil.setAuthSession) {
CookieUtil.setAuthSession({ recharge: data.balance });
}
}
toast((res && res.tip) || "解锁成功", "success");
closeDialog();
afterUnlockSuccess(
Number(data.playletId) || playletId,
Number(data.chapterId) || chapterId,
data
);
})
.catch(function (err) {
toast((err && err.message) || "解锁失败,请稍后重试", "error");
})
.finally(function () {
setPaying(false);
});
}
function openDialog(event) {
if (event) event.preventDefault();
var trigger =
event && event.target && event.target.closest
? event.target.closest("[data-coin-dialog-open]")
: null;
var singleCoins = trigger
? Number(trigger.getAttribute("data-single-coins") || 0)
: 0;
setCost(singleCoins);
if (trigger) {
mask.setAttribute(
"data-chapter-id",
trigger.getAttribute("data-chapter-id") || ""
);
mask.setAttribute("data-single-coins", String(singleCoins || 0));
mask.setAttribute(
"data-playlet-id",
String(resolvePlayletId(trigger) || "")
);
mask.setAttribute("data-playlet-slug", resolvePlayletSlug(trigger));
} else if (!mask.getAttribute("data-playlet-id")) {
mask.setAttribute("data-playlet-id", String(resolvePlayletId(null) || ""));
}
mask.classList.add("is-open");
document.body.style.overflow = "hidden";
if (loading) return;
loading = true;
fetchBalance().finally(function () {
loading = false;
});
}
function closeDialog() {
mask.classList.remove("is-open");
document.body.style.overflow = "";
}
document.addEventListener("click", function (event) {
if (event.target.closest("[data-coin-dialog-open]")) {
openDialog(event);
return;
}
if (event.target.closest("[data-coin-dialog-close]")) {
closeDialog();
return;
}
if (event.target.closest("[data-coin-dialog-pay]")) {
event.preventDefault();
unlockAndPlay();
return;
}
if (event.target === mask) {
closeDialog();
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && mask.classList.contains("is-open")) {
closeDialog();
}
});
window.openCoinDialog = openDialog;
window.closeCoinDialog = closeDialog;
})();
-481
View File
@@ -1,481 +0,0 @@
/**
* 充值页:套餐 / 支付方式互斥选择,按套餐 payMethods 刷新;提交走 VIP/金币下单。
* VIP: POST /api/vip/pay 金币: POST /api/coin/buy
* 支付方式严格使用接口返回的 payMethods,不造假默认渠道。
*/
(function () {
var submitting = false;
var confirmMask = document.querySelector("[data-deposit-confirm]");
var confirmMethods = document.querySelector("[data-deposit-confirm-methods]");
var confirmSubmit = document.querySelector("[data-deposit-confirm-submit]");
var bodyOverflowBeforeConfirm = "";
function toast(message, type) {
if (window.AuthAPI && typeof AuthAPI.toast === "function") {
AuthAPI.toast(message, type || "info");
return;
}
if (typeof showToast === "function") showToast(message, type || "info");
}
function bindExclusive(root, selector, activeClass) {
var scope = root || document;
var nodes = scope.querySelectorAll(selector);
if (!nodes.length) return;
nodes.forEach(function (node) {
node.addEventListener("click", function () {
nodes.forEach(function (item) {
item.classList.remove(activeClass);
});
node.classList.add(activeClass);
syncPayTypeAcross(node.getAttribute("data-pay-type") || "");
});
});
}
function syncPayTypeAcross(payType) {
if (!payType) return;
document.querySelectorAll("[data-pay-type]").forEach(function (el) {
var match = String(el.getAttribute("data-pay-type") || "") === String(payType);
if (el.classList.contains("deposit-pay-btn")) {
el.classList.toggle("deposit-pay-btn--active", match);
}
if (el.classList.contains("deposit-mobile-pay")) {
el.classList.toggle("deposit-mobile-pay--active", match);
}
if (el.classList.contains("deposit-confirm-method")) {
el.classList.toggle("is-active", match);
}
});
}
function parsePayMethods(raw) {
if (!raw) return [];
try {
var list = JSON.parse(raw);
if (!Array.isArray(list)) return [];
return list
.map(function (item) {
return {
type: String((item && item.type) || "").trim(),
typeName: String((item && (item.typeName || item.type)) || "").trim(),
};
})
.filter(function (item) {
return item.type || item.typeName;
});
} catch (e) {
return [];
}
}
function currentPayType() {
var active =
document.querySelector(".deposit-confirm-method.is-active[data-pay-type]") ||
document.querySelector(".deposit-pay-btn--active[data-pay-type]") ||
document.querySelector(".deposit-mobile-pay--active[data-pay-type]");
return active ? String(active.getAttribute("data-pay-type") || "") : "";
}
function currentPackage() {
return (
document.querySelector(".deposit-mobile-pkg--active[data-package-id]") ||
document.querySelector(".deposit-package--active[data-package-id]")
);
}
function renderPayButtons(container, className, activeClass, methods, preferType) {
if (!container) return;
var list = Array.isArray(methods) ? methods : [];
if (!list.length) {
container.innerHTML = '<div class="deposit-package-empty">暂无可用支付方式</div>';
return;
}
var prefer = preferType || "";
var activeType = prefer;
if (!list.some(function (item) { return item.type === prefer; })) {
activeType = list[0] ? list[0].type : "";
}
container.innerHTML = list
.map(function (item) {
var isActive = item.type === activeType;
return (
'<button class="' +
className +
(isActive ? " " + activeClass : "") +
'" type="button" data-pay-type="' +
escapeAttr(item.type) +
'">' +
escapeHtml(item.typeName || item.type) +
"</button>"
);
})
.join("");
bindExclusive(container, "." + className.split(" ").join("."), activeClass);
}
function escapeHtml(text) {
return String(text || "")
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function escapeAttr(text) {
return escapeHtml(text).replace(/'/g, "&#39;");
}
function payMethodVisual(item) {
var value = String((item && (item.typeName || item.type)) || "").toLowerCase();
if (/支付宝|alipay/.test(value)) {
return { kind: "alipay", icon: "/static/images/figma-dialogs/alipay.svg" };
}
if (/微信|wechat|weixin|wxpay/.test(value)) {
return { kind: "wechat", icon: "/static/images/figma-dialogs/wechat.svg" };
}
if (/usdt|tether/.test(value)) {
return { kind: "usdt", icon: "/static/images/figma-dialogs/usdt.svg" };
}
return { kind: "other", icon: "" };
}
function renderConfirmMethods(methods, preferType) {
if (!confirmMethods) return "";
var list = Array.isArray(methods) ? methods : [];
var activeType = preferType || (list[0] && list[0].type) || "";
if (!list.some(function (item) { return item.type === activeType; })) {
activeType = (list[0] && list[0].type) || "";
}
confirmMethods.innerHTML = list.map(function (item) {
var visual = payMethodVisual(item);
var icon = visual.icon
? '<img src="' + visual.icon + '" alt="" />'
: '<span aria-hidden="true">¥</span>';
return '<button class="deposit-confirm-method' +
(item.type === activeType ? ' is-active' : '') +
'" type="button" data-pay-type="' + escapeAttr(item.type) + '">' +
'<span class="deposit-confirm-method-copy"><span class="deposit-confirm-method-icon deposit-confirm-method-icon--' + visual.kind + '">' + icon + '</span>' +
'<span class="deposit-confirm-method-name">' + escapeHtml(item.typeName || item.type) + '</span></span>' +
'<span class="deposit-confirm-method-check" aria-hidden="true">✓</span></button>';
}).join("");
confirmMethods.querySelectorAll(".deposit-confirm-method").forEach(function (button) {
button.addEventListener("click", function () {
syncPayTypeAcross(button.getAttribute("data-pay-type") || "");
});
});
syncPayTypeAcross(activeType);
return activeType;
}
function hasPayMethods(el) {
var target = el || currentPackage();
if (!target) return false;
return parsePayMethods(target.getAttribute("data-pay-methods")).length > 0;
}
function syncPayMethods(el) {
var methods = parsePayMethods(el.getAttribute("data-pay-methods"));
var prefer = currentPayType();
renderPayButtons(
document.querySelector("[data-deposit-pay-pc]"),
"deposit-pay-btn",
"deposit-pay-btn--active",
methods,
prefer
);
renderPayButtons(
document.querySelector("[data-deposit-pay-mobile]"),
"deposit-mobile-pay",
"deposit-mobile-pay--active",
methods,
prefer
);
}
function syncPackageActive(kind, packageId) {
document.querySelectorAll(".deposit-package, .deposit-mobile-pkg").forEach(function (el) {
var match =
String(el.getAttribute("data-package-id") || "") === String(packageId) &&
String(el.getAttribute("data-package-kind") || "") === String(kind);
el.classList.toggle("deposit-package--active", match && el.classList.contains("deposit-package"));
el.classList.toggle(
"deposit-mobile-pkg--active",
match && el.classList.contains("deposit-mobile-pkg")
);
});
}
function updateSubmitButtons(price, loading) {
var canPay = hasPayMethods(currentPackage());
var disabled = !!loading || !canPay;
var pkg = currentPackage();
var packageName = pkg ? String(pkg.getAttribute("data-package-name") || "").trim() : "";
var text;
if (loading) {
text = "支付中...";
} else if (!canPay) {
text = "暂无支付方式";
} else {
text = "立即支付 ¥" + (price || "0");
}
document.querySelectorAll("[data-deposit-submit]").forEach(function (btn) {
btn.disabled = disabled;
btn.classList.toggle("is-loading", !!loading);
btn.classList.toggle("is-disabled", !canPay && !loading);
if (btn.classList.contains("deposit-pc-submit")) {
btn.textContent = loading ? "支付中..." : canPay ? "立即支付 ¥" + (price || "0") : "暂无支付方式";
} else {
btn.textContent = loading ? "支付中..." : canPay ? "支付 ¥" + (price || "0") + " 充值金币" : text;
}
});
document.querySelectorAll("[data-deposit-selected-note]").forEach(function (node) {
node.textContent = packageName
? "已选择 " + packageName + " · 点击后选择支付方式"
: "请选择金币套餐";
});
}
function onPackageClick(el) {
var kind = el.getAttribute("data-package-kind") || "";
var id = el.getAttribute("data-package-id") || "";
var price = el.getAttribute("data-price") || "0";
syncPackageActive(kind, id);
syncPayMethods(el);
updateSubmitButtons(price, false);
}
function openPayUrl(data) {
var url = data && data.payUrl ? String(data.payUrl).trim() : "";
if (!url) {
toast("未获取到支付链接", "error");
return;
}
var mode = String((data && data.payUrlMode) || "").toLowerCase();
var openNew =
!!(data && data.isOpenNewBrowser) ||
mode === "new" ||
mode === "blank" ||
mode === "external";
if (openNew) {
var win = window.open(url, "_blank");
if (!win) {
window.location.href = url;
}
return;
}
window.location.href = url;
}
function ensureLoggedIn() {
if (window.CookieUtil && CookieUtil.isLoggedIn()) return true;
toast("请先登录后再支付", "error");
var loginURL = "/login/return/deposit/";
if (typeof window.openLoginDialog === "function") {
var opened = window.openLoginDialog();
if (opened && typeof opened.then === "function") {
opened.catch(function () {
window.location.href = loginURL;
});
}
} else {
window.location.href = loginURL;
}
return false;
}
function closePayConfirm() {
if (!confirmMask) return;
confirmMask.classList.remove("is-open");
confirmMask.setAttribute("aria-hidden", "true");
document.body.style.overflow = bodyOverflowBeforeConfirm;
}
function openPayConfirm() {
if (submitting || !confirmMask) return;
if (!ensureLoggedIn()) return;
var pkg = currentPackage();
if (!pkg) {
toast("请选择套餐", "error");
return;
}
var methods = parsePayMethods(pkg.getAttribute("data-pay-methods"));
if (!methods.length) {
toast("当前套餐暂无可用支付方式", "error");
return;
}
var packageName = String(pkg.getAttribute("data-package-name") || "金币套餐").trim();
var price = String(pkg.getAttribute("data-price") || "0").trim();
var nameEl = confirmMask.querySelector("[data-deposit-confirm-name]");
var priceEl = confirmMask.querySelector("[data-deposit-confirm-price]");
if (nameEl) nameEl.textContent = packageName;
if (priceEl) priceEl.textContent = price;
renderConfirmMethods(methods, currentPayType());
bodyOverflowBeforeConfirm = document.body.style.overflow;
document.body.style.overflow = "hidden";
confirmMask.classList.add("is-open");
confirmMask.setAttribute("aria-hidden", "false");
}
function submitPay() {
if (submitting) return;
if (!window.HttpRequest) {
toast("请求组件未加载", "error");
return;
}
if (!ensureLoggedIn()) return;
var pkg = currentPackage();
if (!pkg) {
toast("请选择套餐", "error");
return;
}
var packageId = Number(pkg.getAttribute("data-package-id") || 0);
var kind = String(pkg.getAttribute("data-package-kind") || "");
var price = pkg.getAttribute("data-price") || "0";
var payMode = currentPayType();
if (!packageId || (kind !== "vip" && kind !== "coin")) {
toast("套餐无效,请重新选择", "error");
return;
}
if (!payMode) {
toast("请选择支付方式", "error");
return;
}
if (!hasPayMethods(pkg)) {
toast("当前套餐暂无可用支付方式", "error");
return;
}
var api = kind === "coin" ? "/api/coin/buy" : "/api/vip/pay";
submitting = true;
updateSubmitButtons(price, true);
if (confirmSubmit) {
confirmSubmit.disabled = true;
confirmSubmit.textContent = "支付中...";
}
HttpRequest.post(api, { packageId: packageId, payMode: payMode })
.then(function (res) {
if (!res || res.code !== 200 || !res.data) {
var err = new Error((res && (res.tip || res.msg)) || "发起支付失败");
err.code = res && res.code;
throw err;
}
openPayUrl(res.data);
})
.catch(function (err) {
if (err && err.code === 401) {
toast("请先登录后再支付", "error");
if (typeof window.openLoginDialog === "function") {
var opened = window.openLoginDialog();
if (opened && typeof opened.then === "function") {
opened.catch(function () {
window.location.href = "/login/return/deposit/";
});
}
}
return;
}
toast((err && err.message) || "发起支付失败", "error");
})
.finally(function () {
submitting = false;
updateSubmitButtons(price, false);
if (confirmSubmit) {
confirmSubmit.disabled = false;
confirmSubmit.textContent = "去支付";
}
});
}
bindExclusive(document, ".deposit-pay-btn", "deposit-pay-btn--active");
bindExclusive(document, ".deposit-mobile-pay", "deposit-mobile-pay--active");
document.querySelectorAll(".deposit-package[data-package-id]").forEach(function (node) {
node.addEventListener("click", function () {
onPackageClick(node);
});
});
document.querySelectorAll(".deposit-mobile-pkg[data-package-id]").forEach(function (node) {
node.addEventListener("click", function () {
onPackageClick(node);
});
});
document.querySelectorAll("[data-deposit-submit]").forEach(function (btn) {
btn.addEventListener("click", openPayConfirm);
});
if (confirmSubmit) confirmSubmit.addEventListener("click", submitPay);
document.querySelectorAll("[data-deposit-confirm-close]").forEach(function (button) {
button.addEventListener("click", closePayConfirm);
});
if (confirmMask) {
confirmMask.addEventListener("click", function (event) {
if (event.target === confirmMask) closePayConfirm();
});
}
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && confirmMask && confirmMask.classList.contains("is-open")) {
closePayConfirm();
}
});
var active =
document.querySelector(".deposit-mobile-pkg--active[data-price]") ||
document.querySelector(".deposit-package--active[data-price]");
if (active) {
syncPayMethods(active);
updateSubmitButtons(active.getAttribute("data-price") || "0", false);
} else {
updateSubmitButtons("0", false);
}
// /deposit/coin 时滚动到金币充值区域(套餐默认选中由 SSR 完成)
(function scrollPreferCoin() {
if (!/\/deposit\/coin\/?$/i.test(window.location.pathname || "")) return;
var isMobile = window.matchMedia("(max-width: 767px)").matches;
var target = isMobile
? document.getElementById("depositCoinMobileTitle")
: document.getElementById("depositCoinGroup");
if (!target) return;
setTimeout(function () {
target.scrollIntoView({ behavior: "smooth", block: "start" });
}, 80);
})();
function formatRecharge(value) {
var n = Number(value);
if (!isFinite(n) || n < 0) n = 0;
return String(Math.floor(n)).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function syncDepositRecharge(value) {
var text = formatRecharge(value);
document.querySelectorAll("[data-deposit-recharge]").forEach(function (el) {
el.textContent = text;
});
}
function refreshDepositWallet() {
if (!window.CookieUtil || !CookieUtil.isLoggedIn() || !window.HttpRequest) {
return;
}
var session = CookieUtil.getAuthSession();
if (session && session.recharge != null && session.recharge !== "") {
syncDepositRecharge(session.recharge);
}
HttpRequest.get("/api/auth/getInfo")
.then(function (res) {
if (!res || res.code !== 200 || !res.data) return;
if (CookieUtil.setAuthSession) CookieUtil.setAuthSession(res.data);
syncDepositRecharge(res.data.recharge);
})
.catch(function () {});
}
refreshDepositWallet();
})();
+24 -704
View File
@@ -120,239 +120,18 @@
})();
(function () {
// detail.js 同步执行早于 defer 的 request.js,需等 HttpRequest 就绪后再绑定
function toast(message, type) {
if (typeof window.showToast === "function") {
window.showToast(message, type);
return;
}
window.alert(message);
}
// 付费剧集:不再站内解锁,统一引导下载 APP
var lockedEpisodes = document.querySelectorAll("[data-episode-locked]");
if (!lockedEpisodes.length) return;
function bindLikeActions() {
var likeBtns = document.querySelectorAll("[data-detail-like]");
if (!likeBtns.length) return;
if (!window.HttpRequest || typeof window.HttpRequest.post !== "function") {
if (!bindLikeActions._retried) {
bindLikeActions._retried = true;
window.addEventListener("load", bindLikeActions, { once: true });
lockedEpisodes.forEach(function (el) {
el.addEventListener("click", function (e) {
e.preventDefault();
if (typeof window.openDownloadApp === "function") {
window.openDownloadApp();
}
return;
}
if (bindLikeActions._bound) return;
bindLikeActions._bound = true;
function applyLikeUI(isLike, countLike) {
var liked = Number(isLike) === 1;
likeBtns.forEach(function (btn) {
btn.classList.toggle("detail-action--active", liked);
btn.classList.toggle("detail-h5-top-btn--active", liked);
btn.classList.toggle("detail-h5-like--active", liked);
btn.classList.toggle("play-h5-side-item--active", liked);
btn.setAttribute("data-liked", liked ? "1" : "2");
btn.setAttribute("aria-pressed", liked ? "true" : "false");
if (countLike != null) {
btn.setAttribute("data-count-like", String(countLike));
}
var label = btn.querySelector("[data-detail-like-label]");
if (label) {
if (btn.getAttribute("data-like-label-mode") === "state") {
label.textContent = liked ? "已点赞" : "点赞";
} else {
var n = countLike != null ? countLike : btn.getAttribute("data-count-like");
label.textContent = String(n == null || n === "" ? 0 : n);
}
}
var h5Icon = btn.querySelector("[data-h5-like-icon]");
if (h5Icon) {
h5Icon.src = liked
? "/static/images/h5_liked.svg"
: "/static/images/like.svg";
}
});
}
likeBtns.forEach(function (btn) {
btn.addEventListener("click", function () {
if (btn.getAttribute("data-liking") === "1") return;
var playletId = Number(btn.getAttribute("data-playlet-id") || 0);
if (!playletId) return;
var likedNow = Number(btn.getAttribute("data-liked") || 2) === 1;
var countNow = Number(btn.getAttribute("data-count-like") || 0);
if (Number.isNaN(countNow)) countNow = 0;
var nextLike = !likedNow;
var nextCount = Math.max(0, countNow + (nextLike ? 1 : -1));
likeBtns.forEach(function (item) {
item.setAttribute("data-liking", "1");
item.disabled = true;
});
applyLikeUI(nextLike ? 1 : 2, nextCount);
window.HttpRequest.post("/api/playlet/like/set", {
id: playletId,
isLike: nextLike,
})
.then(function (res) {
if (!res || res.code !== 200) {
if (res && res.code === 401) {
var loginOpen = document.querySelector(
"[data-login-dialog-open]"
);
if (loginOpen) loginOpen.click();
}
throw new Error((res && (res.tip || res.msg)) || "操作失败");
}
var data = res.data || {};
applyLikeUI(
data.isLike != null ? data.isLike : nextLike ? 1 : 2,
data.countLike != null ? data.countLike : nextCount
);
})
.catch(function (err) {
applyLikeUI(likedNow ? 1 : 2, countNow);
toast((err && err.message) || "操作失败,请稍后重试", "error");
})
.finally(function () {
likeBtns.forEach(function (item) {
item.removeAttribute("data-liking");
item.disabled = false;
});
});
});
});
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", bindLikeActions, { once: true });
} else {
bindLikeActions();
}
})();
(function () {
function toast(message, type) {
if (typeof window.showToast === "function") {
window.showToast(message, type);
return;
}
window.alert(message);
}
function bindCollectActions() {
var collectBtns = document.querySelectorAll("[data-detail-collect]");
if (!collectBtns.length) return;
if (!window.HttpRequest || typeof window.HttpRequest.post !== "function") {
if (!bindCollectActions._retried) {
bindCollectActions._retried = true;
window.addEventListener("load", bindCollectActions, { once: true });
}
return;
}
if (bindCollectActions._bound) return;
bindCollectActions._bound = true;
function applyCollectUI(isCollect, countCollect) {
var collected = Number(isCollect) === 1;
collectBtns.forEach(function (btn) {
btn.classList.toggle("detail-action--active", collected);
btn.classList.toggle("detail-h5-collect--active", collected);
btn.classList.toggle("detail-h5-top-btn--active", collected);
btn.classList.toggle("play-h5-side-item--active", collected);
btn.classList.toggle("is-collected", collected);
btn.setAttribute("data-collected", collected ? "1" : "2");
btn.setAttribute("aria-pressed", collected ? "true" : "false");
if (countCollect != null) {
btn.setAttribute("data-count-collect", String(countCollect));
}
var label = btn.querySelector("[data-detail-collect-label]");
if (label) {
if (btn.classList.contains("detail-h5-collect")) {
var n = countCollect != null
? countCollect
: btn.getAttribute("data-count-collect");
label.textContent = String(n == null || n === "" ? 0 : n);
} else {
label.textContent = collected ? "已收藏" : "收藏";
}
}
var h5Icon = btn.querySelector("[data-h5-collect-icon]");
if (h5Icon) {
if (btn.classList.contains("detail-h5-top-btn")) {
h5Icon.src = collected
? "/static/images/h5_collected.svg?v=2"
: "/static/images/collect.svg";
} else if (btn.classList.contains("play-h5-side-item")) {
h5Icon.src = collected
? "/static/images/h5_collected.svg?v=2"
: "/static/images/collect.svg";
} else {
h5Icon.src = collected
? "/static/images/h5_detail_collected.svg"
: "/static/images/h5_detail_collect.svg";
}
}
});
}
collectBtns.forEach(function (btn) {
btn.addEventListener("click", function () {
if (btn.getAttribute("data-collecting") === "1") return;
var playletId = Number(btn.getAttribute("data-playlet-id") || 0);
if (!playletId) return;
var collectedNow = Number(btn.getAttribute("data-collected") || 2) === 1;
var countNow = Number(btn.getAttribute("data-count-collect") || 0);
if (Number.isNaN(countNow)) countNow = 0;
var nextCollect = !collectedNow;
var nextCount = Math.max(0, countNow + (nextCollect ? 1 : -1));
collectBtns.forEach(function (item) {
item.setAttribute("data-collecting", "1");
item.disabled = true;
});
applyCollectUI(nextCollect ? 1 : 2, nextCount);
window.HttpRequest.post("/api/playlet/collect/set", {
id: playletId,
isCollect: nextCollect,
})
.then(function (res) {
if (!res || res.code !== 200) {
if (res && res.code === 401) {
var loginOpen = document.querySelector(
"[data-login-dialog-open]"
);
if (loginOpen) loginOpen.click();
}
throw new Error((res && (res.tip || res.msg)) || "操作失败");
}
var data = res.data || {};
applyCollectUI(
data.isCollect != null ? data.isCollect : nextCollect ? 1 : 2,
data.countCollect != null ? data.countCollect : nextCount
);
})
.catch(function (err) {
applyCollectUI(collectedNow ? 1 : 2, countNow);
toast((err && err.message) || "操作失败,请稍后重试", "error");
})
.finally(function () {
collectBtns.forEach(function (item) {
item.removeAttribute("data-collecting");
item.disabled = false;
});
});
});
});
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", bindCollectActions, { once: true });
} else {
bindCollectActions();
}
});
})();
(function () {
@@ -593,15 +372,6 @@
return formatCommentTime(raw);
}
function formatCompactCount(n) {
n = Number(n);
if (!n || n < 0 || Number.isNaN(n)) return "0";
if (n < 10000) return String(n);
var v = n / 10000;
if (v >= 10) return Math.floor(v) + "w";
return (Math.round(v * 10) / 10) + "w";
}
function avatarURL(url) {
url = String(url || "").trim();
return url || DEFAULT_AVATAR;
@@ -614,10 +384,7 @@
}
function renderDetailComment(item, playPcMode) {
var liked = Number(item.isLike) === 1;
var avatar = avatarURL(item.userAvatar);
var commentId = item.id;
var parentsId = Number(item.parentsId || 0) || Number(commentId);
var avatarHtml = item.userAvatar
? '<img class="detail-comment-avatar lazy" src="' +
PLACEHOLDER +
@@ -627,9 +394,6 @@
escapeHtml((item.userName || "匿名用户") + "的头像") +
'" />'
: '<img class="detail-comment-avatar" src="' + DEFAULT_AVATAR + '" alt="匿名用户头像" />';
var likeIcon = liked
? "/static/images/like_solid.svg"
: "/static/images/like_hollow.svg";
var textHtml = escapeHtml(item.text || "");
if (item.replyUserName) {
textHtml =
@@ -691,11 +455,7 @@
}
return (
'<div class="detail-comment" data-comment-id="' +
escapeHtml(commentId) +
'" data-parents-id="' +
escapeHtml(parentsId) +
'" data-user-name="' +
escapeHtml(item.userName || "匿名用户") +
escapeHtml(item.id) +
'">' +
avatarHtml +
'<div class="detail-comment-body">' +
@@ -709,27 +469,6 @@
'<span class="detail-comment-time">' +
escapeHtml(formatCommentTime(item.createdAt)) +
"</span>" +
'<button class="detail-comment-like' +
(liked ? " detail-comment-like--active" : "") +
'" type="button" aria-label="点赞" data-comment-like="' +
escapeHtml(commentId) +
'" data-liked="' +
(liked ? "1" : "2") +
'">' +
'<img src="' +
likeIcon +
'" alt="点赞" />' +
'<span data-like-count>' +
escapeHtml(item.countLike == null ? 0 : item.countLike) +
"</span>" +
"</button>" +
'<button class="detail-comment-reply-label" type="button" data-comment-reply="' +
escapeHtml(commentId) +
'" data-parents-id="' +
escapeHtml(parentsId) +
'" data-reply-name="' +
escapeHtml(item.userName || "匿名用户") +
'">回复</button>' +
"</div>" +
repliesHtml +
"</div></div>"
@@ -737,10 +476,8 @@
}
function renderPlayComment(item) {
var liked = Number(item.isLike) === 1;
var avatar = avatarURL(item.userAvatar);
var commentId = item.id;
var parentsId = Number(item.parentsId || 0) || Number(commentId);
var children = Array.isArray(item.children) ? item.children : [];
var replyCount = Number(item.commentCount || children.length || 0);
var avatarHtml = item.userAvatar
@@ -752,9 +489,6 @@
escapeHtml((item.userName || "匿名用户") + "的头像") +
'" />'
: '<img class="play-comment-avatar" src="' + DEFAULT_AVATAR + '" alt="匿名用户头像" />';
var likeIcon = liked
? "/static/images/h5_liked.svg"
: "/static/images/like_hollow.svg";
var textHtml = escapeHtml(item.text || "");
if (item.replyUserName) {
textHtml =
@@ -807,10 +541,6 @@
return (
'<div class="play-comment-item" data-comment-id="' +
escapeHtml(commentId) +
'" data-parents-id="' +
escapeHtml(parentsId) +
'" data-user-name="' +
escapeHtml(item.userName || "匿名用户") +
'">' +
avatarHtml +
'<div class="play-comment-body">' +
@@ -825,30 +555,7 @@
'<span class="play-comment-time">' +
escapeHtml(formatRelativeTime(item.createdAt)) +
"</span>" +
'<button class="play-comment-reply-action" type="button" data-comment-reply="' +
escapeHtml(commentId) +
'" data-parents-id="' +
escapeHtml(parentsId) +
'" data-reply-name="' +
escapeHtml(item.userName || "匿名用户") +
'">回复</button>' +
"</div>" +
'<button class="play-comment-like' +
(liked ? " play-comment-like--active" : "") +
'" type="button" aria-label="点赞" data-comment-like="' +
escapeHtml(commentId) +
'" data-liked="' +
(liked ? "1" : "2") +
'" data-like-raw="' +
escapeHtml(item.countLike == null ? 0 : item.countLike) +
'">' +
'<img src="' +
likeIcon +
'" alt="点赞" />' +
'<span data-like-count>' +
escapeHtml(formatCompactCount(item.countLike)) +
"</span>" +
"</button>" +
"</div>" +
repliesHtml +
"</div></div>"
@@ -887,18 +594,12 @@
var scope = sheetRoot || section;
var listEl = section.querySelector("[data-comment-list]");
var moreBtn = section.querySelector("[data-comment-more]");
var composerInput =
scope.querySelector(".play-comment-composer-input") ||
scope.querySelector(".detail-comment-composer-input");
var composerCount = scope.querySelector(".detail-comment-composer-count");
var titleEl = section.querySelector("[data-comment-title]");
var sendBtn = scope.querySelector("[data-comment-send]");
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]");
var iconSend = !!(sendBtn && sendBtn.classList.contains("play-comment-composer-emoji"));
if (section.getAttribute("data-comment-inited") === "1") return;
section.setAttribute("data-comment-inited", "1");
@@ -910,169 +611,11 @@
var page = 0;
var total = 0;
var loading = false;
var sending = false;
var replyTarget = null; // { parentsId, replyCommentId, replyName }
var inlineSending = false;
function getObjectId() {
return Number(section.getAttribute("data-comment-object-id") || 0);
}
function clearReplyTarget() {
replyTarget = null;
if (!scope) return;
var boxes = scope.querySelectorAll("[data-comment-inline-composer]");
Array.prototype.forEach.call(boxes, function (el) {
el.remove();
});
}
function setReplyTarget(parentsId, replyCommentId, replyName, anchorEl) {
parentsId = Number(parentsId || 0);
replyCommentId = Number(replyCommentId || 0);
if (!parentsId || !replyCommentId || !anchorEl) return;
var root =
anchorEl.closest(commentItemSelector()) ||
anchorEl.closest("[data-comment-id]");
if (!root || !scope.contains(root)) return;
// 再次点击同一条:关闭内联输入框
var existingOnRoot = root.querySelector("[data-comment-inline-composer]");
if (
existingOnRoot &&
replyTarget &&
replyTarget.replyCommentId === replyCommentId
) {
clearReplyTarget();
return;
}
clearReplyTarget();
replyTarget = {
parentsId: parentsId,
replyCommentId: replyCommentId,
replyName: replyName || "用户",
};
var meta =
root.querySelector(".detail-comment-meta") ||
root.querySelector(".play-comment-meta");
var body =
root.querySelector(".detail-comment-body") ||
root.querySelector(".play-comment-body") ||
root;
var box = document.createElement("div");
box.className = sheetMode
? "play-comment-inline-composer"
: "detail-comment-inline-composer";
box.setAttribute("data-comment-inline-composer", "");
var placeholder = "回复 @" + replyTarget.replyName + "…";
if (sheetMode) {
box.innerHTML =
'<div class="play-comment-reply-hint" data-comment-reply-hint>' +
"<span>回复 @" +
escapeHtml(replyTarget.replyName) +
"</span>" +
'<button type="button" data-comment-reply-cancel>取消</button>' +
"</div>" +
'<div class="play-comment-inline-row">' +
'<input class="play-comment-inline-input" type="text" maxlength="200" placeholder="' +
escapeHtml(placeholder) +
'" data-comment-inline-input autocomplete="off" />' +
'<button class="play-comment-inline-send" type="button" data-comment-inline-send>发送</button>' +
"</div>";
} else {
box.innerHTML =
'<div class="detail-comment-reply-hint" data-comment-reply-hint>' +
"<span>回复 @" +
escapeHtml(replyTarget.replyName) +
"</span>" +
'<button type="button" data-comment-reply-cancel>取消</button>' +
"</div>" +
'<textarea class="detail-comment-inline-input" maxlength="200" rows="2" placeholder="' +
escapeHtml(placeholder) +
'" data-comment-inline-input></textarea>' +
'<div class="detail-comment-inline-footer">' +
'<button class="detail-comment-inline-send" type="button" data-comment-inline-send>发表回复</button>' +
"</div>";
}
if (meta && meta.parentNode === body) {
if (meta.nextSibling) {
body.insertBefore(box, meta.nextSibling);
} else {
body.appendChild(box);
}
} else {
body.appendChild(box);
}
var inlineInput = box.querySelector("[data-comment-inline-input]");
if (inlineInput) {
inlineInput.focus();
}
}
function sendInlineReply(box) {
if (!box || inlineSending || !replyTarget) return;
var objectId = getObjectId();
if (!objectId) return;
var input = box.querySelector("[data-comment-inline-input]");
var btn = box.querySelector("[data-comment-inline-send]");
if (!input) return;
var text = String(input.value || "").trim();
if (!text) {
toast("请输入评论内容", "error");
return;
}
if (Array.from(text).length > 200) {
toast("评论最多 200 字", "error");
return;
}
inlineSending = true;
if (btn) {
btn.disabled = true;
btn.classList.add("is-loading");
}
input.disabled = true;
var payload = {
objectId: objectId,
objectType: objectType,
text: text,
parentsId: replyTarget.parentsId,
replyCommentId:
replyTarget.replyCommentId > 0
? replyTarget.replyCommentId
: replyTarget.parentsId,
};
window.HttpRequest.post("/api/comment/send", payload)
.then(function (res) {
if (!res || res.code !== 200) {
if (res && res.code === 401) {
var loginOpen = document.querySelector(
"[data-login-dialog-open]"
);
if (loginOpen) loginOpen.click();
}
throw new Error((res && (res.tip || res.msg)) || "发表失败");
}
clearReplyTarget();
toast("发布成功,评论审核后才会展示", "success");
})
.catch(function (err) {
toast((err && err.message) || "发表失败,请稍后重试", "error");
})
.finally(function () {
inlineSending = false;
if (btn) {
btn.disabled = false;
btn.classList.remove("is-loading");
}
if (input) input.disabled = false;
});
}
function commentItemSelector() {
return sheetMode ? ".play-comment-item" : ".detail-comment";
}
@@ -1089,32 +632,6 @@
}
}
function applyLikeUI(btn, isLike, countLike) {
var liked = Number(isLike) === 1;
btn.classList.toggle("detail-comment-like--active", liked);
btn.classList.toggle("play-comment-like--active", liked);
btn.setAttribute("data-liked", liked ? "1" : "2");
var img = btn.querySelector("img");
if (img) {
if (sheetMode) {
img.src = liked
? "/static/images/h5_liked.svg"
: "/static/images/like_hollow.svg";
} else {
img.src = liked
? "/static/images/like_solid.svg"
: "/static/images/like_hollow.svg";
}
}
var countEl = btn.querySelector("[data-like-count]");
if (countEl && countLike != null) {
btn.setAttribute("data-like-raw", String(countLike));
countEl.textContent = sheetMode
? formatCompactCount(countLike)
: String(countLike);
}
}
function syncSortActive() {
sortBtns.forEach(function (item) {
var active = Number(item.getAttribute("data-comment-sort")) === sortOrder;
@@ -1140,7 +657,6 @@
var emptyClass = sheetMode
? "section-empty play-comment-empty"
: "section-empty";
clearReplyTarget();
listEl.innerHTML =
'<div class="' +
emptyClass +
@@ -1179,7 +695,6 @@
updateTitleCount();
if (replace) {
clearReplyTarget();
if (!rows.length) {
showEmpty("暂无评论");
return;
@@ -1225,15 +740,6 @@
});
}
if (composerInput && composerCount) {
var syncCount = function () {
composerCount.textContent =
Array.from(composerInput.value).length + " / 200";
};
composerInput.addEventListener("input", syncCount);
syncCount();
}
syncSortActive();
sortBtns.forEach(function (btn) {
@@ -1251,149 +757,27 @@
});
});
if (sendBtn && composerInput) {
var sendBtnDefaultText = sendBtn.textContent || "发表评论";
sendBtn.addEventListener("click", function () {
var objectId = getObjectId();
if (sending || !objectId) return;
var text = String(composerInput.value || "").trim();
if (!text) {
toast("请输入评论内容", "error");
return;
}
if (Array.from(text).length > 200) {
toast("评论最多 200 字", "error");
return;
}
sending = true;
sendBtn.disabled = true;
sendBtn.classList.add("is-loading");
if (!iconSend) sendBtn.textContent = "发表中";
composerInput.disabled = true;
var payload = {
objectId: objectId,
objectType: objectType,
text: text,
parentsId: 0,
replyCommentId: 0,
};
window.HttpRequest.post("/api/comment/send", payload)
.then(function (res) {
if (!res || res.code !== 200) {
if (res && res.code === 401) {
var loginOpen = document.querySelector(
"[data-login-dialog-open]"
);
if (loginOpen) loginOpen.click();
}
throw new Error((res && (res.tip || res.msg)) || "发表失败");
}
composerInput.value = "";
if (composerCount) composerCount.textContent = "0 / 200";
toast("发布成功,评论审核后才会展示", "success");
// 与 PC 一致:发表后不强制刷新列表(审核后才可见)
})
.catch(function (err) {
toast((err && err.message) || "发表失败,请稍后重试", "error");
})
.finally(function () {
sending = false;
sendBtn.disabled = false;
sendBtn.classList.remove("is-loading");
if (!iconSend) sendBtn.textContent = sendBtnDefaultText;
composerInput.disabled = false;
});
});
if (sheetMode) {
composerInput.addEventListener("keydown", function (e) {
if (e.key === "Enter") {
e.preventDefault();
sendBtn.click();
}
});
}
}
if (scope) {
scope.addEventListener("click", function (e) {
var cancel =
e.target && e.target.closest
? e.target.closest("[data-comment-reply-cancel]")
: null;
if (cancel) {
e.preventDefault();
clearReplyTarget();
return;
}
var inlineSend =
e.target && e.target.closest
? e.target.closest("[data-comment-inline-send]")
: null;
if (inlineSend && scope.contains(inlineSend)) {
e.preventDefault();
var box = inlineSend.closest("[data-comment-inline-composer]");
sendInlineReply(box);
return;
}
var repliesToggle =
e.target && e.target.closest
? e.target.closest("[data-comment-replies-toggle]")
: null;
if (repliesToggle && scope.contains(repliesToggle)) {
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;
});
return;
}
var replyBtn =
e.target && e.target.closest
? e.target.closest("[data-comment-reply]")
: null;
if (!replyBtn || !scope.contains(replyBtn)) return;
if (!repliesToggle || !scope.contains(repliesToggle)) return;
e.preventDefault();
var replyCommentId = Number(replyBtn.getAttribute("data-comment-reply") || 0);
var parentsId = Number(replyBtn.getAttribute("data-parents-id") || 0);
var replyName = replyBtn.getAttribute("data-reply-name") || "用户";
if (!parentsId) {
var root =
replyBtn.closest("[data-parents-id]") ||
replyBtn.closest("[data-comment-id]");
if (root) {
parentsId = Number(
root.getAttribute("data-parents-id") ||
root.getAttribute("data-comment-id") ||
0
);
}
}
if (!replyCommentId) return;
if (!parentsId) parentsId = replyCommentId;
setReplyTarget(parentsId, replyCommentId, replyName, replyBtn);
});
scope.addEventListener("keydown", function (e) {
if (e.key !== "Enter") return;
var input =
e.target && e.target.closest
? e.target.closest("[data-comment-inline-input]")
: null;
if (!input || !scope.contains(input)) return;
if (input.tagName === "TEXTAREA" && !e.ctrlKey && !e.metaKey) return;
e.preventDefault();
var box = input.closest("[data-comment-inline-composer]");
sendInlineReply(box);
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;
});
});
}
@@ -1403,70 +787,6 @@
});
}
if (listEl) {
listEl.addEventListener("click", function (e) {
var btn =
e.target && e.target.closest
? e.target.closest("[data-comment-like]")
: null;
if (!btn || !listEl.contains(btn)) return;
var commentId = Number(btn.getAttribute("data-comment-like") || 0);
if (!commentId) return;
if (btn.getAttribute("data-liking") === "1") return;
var likedNow = Number(btn.getAttribute("data-liked") || 2) === 1;
var nextLike = !likedNow;
var rawAttr = btn.getAttribute("data-like-raw");
var countEl = btn.querySelector("[data-like-count]");
var prevCount = Number(
rawAttr != null
? rawAttr
: countEl && countEl.textContent
? countEl.textContent
: 0
);
if (Number.isNaN(prevCount)) prevCount = 0;
btn.setAttribute("data-liking", "1");
btn.disabled = true;
applyLikeUI(
btn,
nextLike ? 1 : 2,
Math.max(0, prevCount + (nextLike ? 1 : -1))
);
window.HttpRequest.post("/api/comment/like/set", {
commentId: commentId,
isLike: nextLike,
})
.then(function (res) {
if (!res || res.code !== 200) {
if (res && res.code === 401) {
var loginOpen = document.querySelector(
"[data-login-dialog-open]"
);
if (loginOpen) loginOpen.click();
}
throw new Error((res && (res.tip || res.msg)) || "操作失败");
}
var data = res.data || {};
applyLikeUI(
btn,
data.isLike != null ? data.isLike : nextLike ? 1 : 2,
data.countLike != null ? data.countLike : null
);
})
.catch(function (err) {
applyLikeUI(btn, likedNow ? 1 : 2, prevCount);
toast((err && err.message) || "操作失败,请稍后重试", "error");
})
.finally(function () {
btn.removeAttribute("data-liking");
btn.disabled = false;
});
});
}
if (!listEl || !getObjectId()) {
if (listEl) showEmpty("暂无评论");
return;
+14 -62
View File
@@ -7,20 +7,6 @@
js: "/static/js/pages/downloadAppDialog.js?v=4",
open: "openDownloadAppDialog",
},
login: {
endpoint: "/ui/dialog/login",
elementId: "loginDialog",
css: "/static/css/loginDialog.css?v=2",
js: "/static/js/pages/loginDialog.js?v=3",
open: "openLoginDialog",
},
register: {
endpoint: "/ui/dialog/register",
elementId: "registerDialog",
css: "/static/css/registerDialog.css?v=2",
js: "/static/js/pages/registerDialog.js?v=2",
open: "openRegisterDialog",
},
};
var pending = Object.create(null);
var stubOpeners = Object.create(null);
@@ -141,26 +127,6 @@
return pending[name];
}
function loginFallbackURL() {
var redirect = "";
try {
redirect = global.location.pathname || "/";
} catch (e) {
redirect = "/";
}
var url = "/login/";
if (
typeof redirect === "string" &&
redirect.charAt(0) === "/" &&
redirect.charAt(1) !== "/" &&
redirect !== "/" &&
redirect.indexOf("/?auth=") !== 0
) {
url = "/login/return" + redirect;
}
return url;
}
function openDialog(name, value) {
return ensureDialog(name)
.then(function () {
@@ -171,15 +137,6 @@
return opener(value);
})
.catch(function (error) {
if (name === "login") {
try {
var params = new URLSearchParams(global.location.search || "");
// 已在登录入口仍失败时避免死循环跳转
if (params.get("auth") !== "login") {
global.location.href = loginFallbackURL();
}
} catch (e) {}
}
throw error;
});
}
@@ -196,12 +153,6 @@
function triggerName(target) {
if (!target || !target.closest) return "";
if (target.closest("[data-download-app-open]")) return "download";
if (target.closest("[data-register-dialog-open], a[href=\"#register\"], a[href=\"/register/\"]")) {
return "register";
}
if (target.closest("[data-login-dialog-open], a[href=\"#login\"], a[href=\"/login/\"]")) {
return "login";
}
return "";
}
@@ -222,22 +173,23 @@
openDialog(name).catch(function () {});
}, true);
function openFromLocation() {
var params = new URLSearchParams(global.location.search || "");
var auth = params.get("auth");
if (auth === "login" || auth === "register") {
openDialog(auth).catch(function () {});
return;
}
if (global.location.hash === "#login") openDialog("login").catch(function () {});
if (global.location.hash === "#register") openDialog("register").catch(function () {});
function appDownloadURL() {
var el = document.querySelector("[data-app-download-url]");
var url = el ? (el.getAttribute("data-app-download-url") || "").trim() : "";
return url || "/download-app/";
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", openFromLocation, { once: true });
} else {
openFromLocation();
// 付费内容统一入口:移动端直接跳下载地址,PC 弹下载二维码。
function openDownloadApp() {
if (isMobileViewport()) {
global.location.href = appDownloadURL();
return Promise.resolve();
}
return openDialog("download").catch(function () {
global.location.href = appDownloadURL();
});
}
global.ensureDialog = ensureDialog;
global.openDownloadApp = openDownloadApp;
})(window);
-139
View File
@@ -1,139 +0,0 @@
/**
* 修改密码:POST /api/auth/profile { oldPassword, newPassword }
*/
(function () {
var form = document.querySelector("[data-edit-password-form]");
if (!form) return;
var currentInput = form.querySelector("[data-edit-password-current]");
var newInput = form.querySelector("[data-edit-password-new]");
var confirmInput = form.querySelector("[data-edit-password-confirm]");
var submitBtn = form.querySelector("[data-edit-password-submit]");
document.querySelectorAll("[data-password-toggle]").forEach(function (btn) {
btn.addEventListener("click", function () {
var id = btn.getAttribute("data-password-toggle");
var input = id ? document.getElementById(id) : null;
if (!input) return;
var show = input.type === "password";
input.type = show ? "text" : "password";
btn.textContent = show ? "隐藏" : "显示";
});
});
function getField(name) {
return form.querySelector('[data-edit-password-field="' + name + '"]');
}
function setFieldError(name, message) {
var field = getField(name);
if (!field) return;
var error = field.querySelector("[data-edit-password-error]");
field.classList.toggle("is-error", !!message);
if (error) {
if (message) {
error.hidden = false;
error.textContent = message;
} else {
error.hidden = true;
}
}
}
function clearErrors() {
setFieldError("current", "");
setFieldError("new", "");
setFieldError("confirm", "");
}
function isValidLength(value) {
return value.length >= 4 && value.length <= 16;
}
function toast(message, type) {
if (window.AuthAPI) AuthAPI.toast(message, type);
else if (typeof showToast === "function") showToast(message, type);
}
function validate() {
clearErrors();
var current = (currentInput && currentInput.value) || "";
var next = (newInput && newInput.value) || "";
var confirm = (confirmInput && confirmInput.value) || "";
var ok = true;
if (!current) {
setFieldError("current", "请输入当前密码");
ok = false;
} else if (!isValidLength(current)) {
setFieldError("current", "当前密码需为 4–16 个字符");
ok = false;
}
if (!next) {
setFieldError("new", "请输入新密码");
ok = false;
} else if (!isValidLength(next)) {
setFieldError("new", "新密码需为 4–16 个字符");
ok = false;
} else if (next === current) {
setFieldError("new", "新密码不能与当前密码相同");
ok = false;
}
if (!confirm) {
setFieldError("confirm", "请再次输入新密码");
ok = false;
} else if (confirm !== next) {
setFieldError("confirm", "两次输入的新密码不一致");
ok = false;
}
if (!ok) return null;
return { oldPassword: current, newPassword: next };
}
[currentInput, newInput, confirmInput].forEach(function (input) {
if (!input) return;
input.addEventListener("input", function () {
var field = input.closest("[data-edit-password-field]");
if (!field) return;
var name = field.getAttribute("data-edit-password-field");
setFieldError(name, "");
});
});
form.addEventListener("submit", function (event) {
event.preventDefault();
var payload = validate();
if (!payload) return;
if (!window.AuthAPI || !window.HttpRequest) {
return;
}
if (submitBtn) submitBtn.disabled = true;
AuthAPI.updateProfile(payload)
.then(function () {
toast("密码修改成功", "success");
setTimeout(function () {
window.location.href = "/setting/";
}, 400);
})
.catch(function (err) {
var tip = (err && err.message) || "修改失败,请稍后重试";
if (/旧|当前|原密码|old/i.test(tip)) {
setFieldError("current", tip);
return;
}
if (/新密码|new/i.test(tip)) {
setFieldError("new", tip);
return;
}
toast(tip, "error");
})
.finally(function () {
if (submitBtn) submitBtn.disabled = false;
});
});
})();
-68
View File
@@ -1,68 +0,0 @@
(function () {
var form = document.querySelector("[data-edit-profile-form]");
var nickInput = document.querySelector("[data-edit-profile-nickname]");
var bioInput = document.querySelector("[data-edit-profile-bio]");
var submitBtn = document.querySelector("[data-edit-profile-submit]");
if (!form) return;
var originalNick = nickInput ? String(nickInput.value || "").trim() : "";
var originalBio = bioInput ? String(bioInput.value || "").trim() : "";
function toast(message, type) {
if (window.AuthAPI) AuthAPI.toast(message, type);
else if (typeof showToast === "function") showToast(message, type);
}
form.addEventListener("submit", function (event) {
event.preventDefault();
if (!window.AuthAPI || !window.HttpRequest) {
return;
}
var nick = nickInput ? String(nickInput.value || "").trim() : "";
var bio = bioInput ? String(bioInput.value || "").trim() : "";
if (!nick) {
toast("请输入昵称", "error");
return;
}
if (nick.length > 20) {
toast("昵称最多 20 个字符", "error");
return;
}
if (bio.length > 120) {
toast("个人简介最多 120 个字符", "error");
return;
}
var nickChanged = nick !== originalNick;
var bioChanged = bio !== originalBio;
if (!nickChanged && !bioChanged) {
toast("暂无修改", "info");
return;
}
var payload = {};
if (nickChanged) payload.nickName = nick;
if (bioChanged) payload.introduction = bio;
if (!payload.nickName && !payload.introduction) {
toast(bioChanged ? "请填写个人简介或修改昵称" : "暂无修改", "error");
return;
}
if (submitBtn) submitBtn.disabled = true;
AuthAPI.updateProfile(payload)
.then(function () {
toast("保存成功", "success");
setTimeout(function () {
window.location.href = "/setting/";
}, 400);
})
.catch(function (err) {
toast((err && err.message) || "保存失败", "error");
})
.finally(function () {
if (submitBtn) submitBtn.disabled = false;
});
});
})();
-30
View File
@@ -495,23 +495,6 @@
});
}
function requireLogin() {
if (window.CookieUtil && CookieUtil.isLoggedIn()) return true;
toast("请先登录后再提交反馈", "error");
var loginURL = "/login/return/feedback/";
if (typeof window.openLoginDialog === "function") {
var opened = window.openLoginDialog();
if (opened && typeof opened.then === "function") {
opened.catch(function () {
window.location.href = loginURL;
});
}
} else {
window.location.href = loginURL;
}
return false;
}
function uploadAllImages() {
if (!selectedFiles.length) return Promise.resolve([]);
if (!window.AuthAPI || typeof AuthAPI.uploadImage !== "function") {
@@ -548,7 +531,6 @@
return;
}
if (submitBtn && submitBtn.classList.contains("is-loading")) return;
if (!requireLogin()) return;
var activeTypeChip = document.querySelector("[data-feedback-type-option].is-active");
var type = parseInt(
@@ -647,18 +629,6 @@
clearFiles();
})
.catch(function (err) {
if (err && err.code === 401) {
toast("请先登录后再提交反馈", "error");
if (typeof window.openLoginDialog === "function") {
var opened = window.openLoginDialog();
if (opened && typeof opened.then === "function") {
opened.catch(function () {
window.location.href = "/login/return/feedback/";
});
}
}
return;
}
toast((err && err.message) || "提交失败", "error");
})
.finally(function () {
-130
View File
@@ -93,142 +93,12 @@
});
}
var DEFAULT_AVATAR = "/static/images/avatar.png";
var PLACEHOLDER = "/static/images/placeholder.png?v=2";
function usableAvatar(url) {
var u = String(url || "").trim();
if (!u) return "";
if (/^https?:\/\//i.test(u) || u.indexOf("/static/") === 0) return u;
return "";
}
function setAvatarImg(img, url) {
if (!img) return;
var src = usableAvatar(url);
img.removeAttribute("data-decrypted");
if (src && typeof shouldDecryptImage === "function" && shouldDecryptImage(src)) {
img.classList.add("lazy");
img.src = PLACEHOLDER;
img.setAttribute("data-src", src);
} else {
img.classList.remove("lazy");
img.removeAttribute("data-src");
img.src = src || DEFAULT_AVATAR;
}
}
function refreshDecrypt(root) {
if (typeof window.initLazyImages === "function") {
window.initLazyImages(root || document);
}
}
/** 用 cookie 登录态同步 header-account */
function parseExpireTime(value) {
if (value == null || value === "") return NaN;
if (typeof value === "number") {
return value < 1e12 ? value * 1000 : value;
}
var text = String(value).trim();
if (!text) return NaN;
if (/^\d+$/.test(text)) {
var num = Number(text);
return num < 1e12 ? num * 1000 : num;
}
return Date.parse(text);
}
// vipType≠0 且 currentVipExpire 未过期(与 91ly 一致)
function isVipActive(user) {
if (!user) return false;
var type = Number(user.vipType);
if (!type || type === 0) return false;
var expireMs = parseExpireTime(user.currentVipExpire);
if (!isFinite(expireMs) || expireMs <= 0) return false;
return expireMs > Date.now();
}
function syncHeaderVip(session) {
var active = isVipActive(session);
document.querySelectorAll("[data-header-vip], [data-header-vip-sep]").forEach(function (el) {
el.hidden = !active;
});
}
function syncHeaderAccount() {
var account = document.querySelector("[data-header-account]");
if (!account || !window.CookieUtil) return;
// 有 token 即展示个人信息(含游客)
var loggedIn = CookieUtil.isLoggedIn();
var session = loggedIn ? CookieUtil.getAuthSession() : null;
var nameEl = account.querySelector("[data-header-username]");
if (loggedIn && session) {
var displayName =
session.nickName || session.accountNo || session.email || "用户";
var avatar = usableAvatar(session.avatar);
account.href = "/user-center/";
account.removeAttribute("data-login-dialog-open");
var guest = account.querySelector("[data-header-guest-avatar]");
if (guest) guest.remove();
var photo = account.querySelector("[data-header-avatar]");
if (!photo) {
photo = document.createElement("img");
photo.className = "account-avatar-photo";
photo.setAttribute("data-header-avatar", "");
photo.alt = displayName + "的头像";
account.insertBefore(photo, nameEl || account.firstChild);
}
setAvatarImg(photo, avatar);
if (nameEl) {
nameEl.textContent = displayName;
nameEl.classList.add("account-label--logged");
}
refreshDecrypt(account.parentElement || document);
syncHeaderVip(session);
return;
}
account.href = "#login";
account.setAttribute("data-login-dialog-open", "");
var loggedPhoto = account.querySelector("[data-header-avatar]");
if (loggedPhoto) loggedPhoto.remove();
if (!account.querySelector("[data-header-guest-avatar]")) {
var wrap = document.createElement("div");
wrap.className = "account-avatar";
wrap.setAttribute("data-header-guest-avatar", "");
wrap.innerHTML =
'<img class="account-avatar-ring" src="' +
DEFAULT_AVATAR +
'" alt="未登录用户头像" />' +
'<div class="account-avatar-body"></div>' +
'<div class="account-avatar-head"></div>';
account.insertBefore(wrap, nameEl || account.firstChild);
}
if (nameEl) {
nameEl.textContent = "未登录";
nameEl.classList.remove("account-label--logged");
}
syncHeaderVip(null);
}
syncHeaderAccount();
window.syncHeaderAccount = syncHeaderAccount;
document.addEventListener("auth:login", function () {
syncHeaderAccount();
});
document.addEventListener("auth:logout", function () {
syncHeaderAccount();
});
document.addEventListener(
"click",
-85
View File
@@ -1,85 +0,0 @@
/**
* 观看历史页:清空记录
*/
(function () {
var clearBtns = document.querySelectorAll("[data-history-clear]");
var confirmMask = document.querySelector("[data-history-confirm]");
var confirmCancelBtns = document.querySelectorAll(
"[data-history-confirm-cancel]"
);
var confirmOkBtn = document.querySelector("[data-history-confirm-ok]");
var clearing = false;
function toast(message, type) {
if (window.AuthAPI && typeof window.AuthAPI.toast === "function") {
window.AuthAPI.toast(message, type);
}
}
function openClearConfirm() {
if (!confirmMask) return;
confirmMask.hidden = false;
confirmMask.removeAttribute("hidden");
confirmMask.classList.add("is-open");
document.body.style.overflow = "hidden";
}
function closeClearConfirm() {
if (!confirmMask) return;
confirmMask.classList.remove("is-open");
confirmMask.hidden = true;
confirmMask.setAttribute("hidden", "");
document.body.style.overflow = "";
}
function clearHistory() {
if (clearing) return;
if (!window.HttpRequest) {
toast("清空失败,请稍后重试", "error");
return;
}
clearing = true;
window.HttpRequest.post("/api/playlet/history/clear")
.then(function (res) {
if (!res || res.code !== 200) {
throw new Error((res && (res.tip || res.msg)) || "清空失败");
}
window.location.reload();
})
.catch(function (err) {
clearing = false;
toast((err && err.message) || "清空失败,请稍后重试", "error");
});
}
clearBtns.forEach(function (btn) {
btn.addEventListener("click", function () {
openClearConfirm();
});
});
confirmCancelBtns.forEach(function (btn) {
btn.addEventListener("click", function () {
closeClearConfirm();
});
});
if (confirmMask) {
confirmMask.addEventListener("click", function (e) {
if (e.target === confirmMask) closeClearConfirm();
});
}
if (confirmOkBtn) {
confirmOkBtn.addEventListener("click", function () {
closeClearConfirm();
clearHistory();
});
}
document.addEventListener("keydown", function (e) {
if (e.key !== "Escape") return;
if (!confirmMask || !confirmMask.classList.contains("is-open")) return;
closeClearConfirm();
});
})();
-236
View File
@@ -1,236 +0,0 @@
(function () {
var mask = document.getElementById("loginDialog");
if (!mask) return;
var form = mask.querySelector("[data-login-dialog-form]");
var accountInput = mask.querySelector("[data-login-account]");
var passwordInput = mask.querySelector("[data-login-password]");
var submitBtn = mask.querySelector("[data-login-submit]");
var defaultSubmitText = (submitBtn && submitBtn.textContent) || "登录";
function setSubmitting(loading) {
if (!submitBtn) return;
submitBtn.disabled = !!loading;
submitBtn.classList.toggle("is-loading", !!loading);
submitBtn.setAttribute("aria-busy", loading ? "true" : "false");
submitBtn.textContent = loading ? "登录中..." : defaultSubmitText;
}
function getField(name) {
return mask.querySelector('[data-login-field="' + name + '"]');
}
function setFieldError(name, message) {
var field = getField(name);
if (!field) return;
var control = field.querySelector("[data-login-control]");
var error = field.querySelector("[data-login-error]");
if (control) control.classList.add("is-error");
if (error) {
error.textContent = message;
error.hidden = false;
}
}
function clearFieldError(name) {
var field = getField(name);
if (!field) return;
var control = field.querySelector("[data-login-control]");
var error = field.querySelector("[data-login-error]");
if (control) control.classList.remove("is-error");
if (error) error.hidden = true;
}
function clearAllErrors() {
clearFieldError("account");
clearFieldError("password");
}
function isValidLength(value) {
return value.length >= 4 && value.length <= 16;
}
function validateForm() {
var account = (accountInput && accountInput.value.trim()) || "";
var password = (passwordInput && passwordInput.value) || "";
var valid = true;
clearAllErrors();
if (!account) {
setFieldError("account", "账号格式不正确,请输入有效账号");
valid = false;
} else if (!window.AuthAPI || !AuthAPI.isValidLoginAccount(account)) {
setFieldError("account", "账号格式不正确,请输入有效账号");
valid = false;
}
if (!password) {
setFieldError("password", "密码错误,请检查后重新输入");
valid = false;
} else if (!isValidLength(password)) {
setFieldError("password", "密码错误,请检查后重新输入");
valid = false;
}
if (!valid) return null;
return { account: account, password: password };
}
function mapServerError(err) {
var tip = (err && err.message) || "登录失败,请稍后重试";
if (/密码|password/i.test(tip)) {
setFieldError("password", tip);
return;
}
if (/账号|账户|用户|邮箱|account|email|不存在|错误/i.test(tip)) {
setFieldError("account", tip);
return;
}
if (window.AuthAPI) AuthAPI.toast(tip, "error");
else if (typeof showToast === "function") showToast(tip, "error");
}
function openDialog(event) {
if (event) event.preventDefault();
if (typeof window.closeRegisterDialog === "function") {
window.closeRegisterDialog();
}
clearAllErrors();
mask.classList.add("is-open");
document.body.style.overflow = "hidden";
return true;
}
function closeDialog() {
mask.classList.remove("is-open");
clearAllErrors();
if (!document.getElementById("registerDialog") || !document.getElementById("registerDialog").classList.contains("is-open")) {
document.body.style.overflow = "";
}
}
function setLoginErrors(errors) {
clearAllErrors();
if (!errors) return;
if (errors.account) setFieldError("account", errors.account);
if (errors.password) setFieldError("password", errors.password);
}
if (form) {
form.addEventListener("submit", function (event) {
event.preventDefault();
if (submitBtn && submitBtn.classList.contains("is-loading")) return;
var payload = validateForm();
if (!payload) return;
if (!window.AuthAPI || !window.HttpRequest) {
return;
}
setSubmitting(true);
AuthAPI.login(payload)
.then(function () {
AuthAPI.toast("登录成功", "success");
closeDialog();
setTimeout(function () {
goAfterAuth();
}, 400);
})
.catch(function (err) {
setSubmitting(false);
mapServerError(err);
});
});
}
function isSafeRedirect(path) {
return typeof path === "string" && path.charAt(0) === "/" && path.charAt(1) !== "/";
}
function goAfterAuth() {
var bodyRedirect = document.body && document.body.getAttribute("data-auth-redirect");
if (isSafeRedirect(bodyRedirect)) {
window.location.href = bodyRedirect;
return;
}
var params = new URLSearchParams(window.location.search);
var redirect = params.get("redirect");
if (isSafeRedirect(redirect)) {
window.location.href = redirect;
return;
}
window.location.reload();
}
function consumeAuthQuery(kind) {
var params = new URLSearchParams(window.location.search);
if (params.get("auth") !== kind) return false;
params.delete("auth");
var qs = params.toString();
var next = window.location.pathname + (qs ? "?" + qs : "") + window.location.hash;
window.history.replaceState(null, "", next);
return true;
}
if (accountInput) {
accountInput.addEventListener("input", function () {
clearFieldError("account");
});
}
if (passwordInput) {
passwordInput.addEventListener("input", function () {
clearFieldError("password");
});
}
document.addEventListener("click", function (event) {
var openEl = event.target.closest("[data-login-dialog-open]");
if (openEl) {
openDialog(event);
return;
}
var loginLink = event.target.closest('a[href="/login/"], a[href="#login"]');
if (loginLink) {
openDialog(event);
return;
}
if (event.target.closest("[data-login-dialog-close]")) {
closeDialog();
return;
}
if (event.target.closest("[data-login-dialog-eye]")) {
var btn = event.target.closest("[data-login-dialog-eye]");
var input = document.getElementById("loginDialogPassword");
var img = btn.querySelector("img");
if (!input || !img) return;
var show = input.type === "password";
input.type = show ? "text" : "password";
img.src = show ? "/static/images/eye_open.svg" : "/static/images/eye_close.svg";
btn.setAttribute("aria-label", show ? "隐藏密码" : "显示密码");
return;
}
if (event.target === mask) {
closeDialog();
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && mask.classList.contains("is-open")) {
closeDialog();
}
});
window.openLoginDialog = openDialog;
window.closeLoginDialog = closeDialog;
window.setLoginDialogErrors = setLoginErrors;
if ((document.body && document.body.getAttribute("data-auth-mode") === "login") || consumeAuthQuery("login")) {
openDialog();
}
})();
+43 -255
View File
@@ -437,46 +437,6 @@
applyPlaySpeed(dp, currentPlaySpeed());
}
// 复用同一 meta 对象:bindVideoEvents 只绑一次,切集时就地更新字段即可生效。
var playTrackerMeta = {
media_id: "",
video_id: "",
video_title: "",
video_type_id: "playlet",
video_type_name: "短剧",
video_content_type: "playlet",
recommend_trace_id: "",
video_tag_key: "",
video_tag_name: "",
};
var playViewTracked = false;
function syncPlayTrackerMeta() {
var root = document.querySelector("[data-play-page]");
var ds = (root && root.dataset) || {};
var player = document.querySelector("[data-play-player]");
var pds = (player && player.dataset) || {};
var episode = ds.playEpisode || "";
playTrackerMeta.media_id = ds.playletId || "";
playTrackerMeta.video_id = ds.playletId || "";
playTrackerMeta.video_title = ds.playTitle || "";
playTrackerMeta.video_type_id = "playlet";
playTrackerMeta.video_type_name = ds.playTag || "短剧";
playTrackerMeta.video_content_type = "playlet";
playTrackerMeta.recommend_trace_id = "";
playTrackerMeta.video_tag_key = pds.chapterId || "";
playTrackerMeta.video_tag_name = episode ? "第" + episode + "集" : "";
return playTrackerMeta;
}
function bindPlayTracker(dp) {
if (!dp || !window.tracker || typeof window.tracker.bindVideoEvents !== "function") {
return;
}
syncPlayTrackerMeta();
window.tracker.bindVideoEvents(dp, playTrackerMeta);
}
function nextEpisodeElement() {
var active = document.querySelector(".play-ep-grid .play-ep--active");
if (!active) return null;
@@ -607,7 +567,6 @@
var player = container.closest(".play-player");
bindPlayerPoster(playDp, player);
bindH265Fallback(playDp, source);
bindPlayTracker(playDp);
setupDesktopPlayerControls(playDp);
return playDp;
} catch (e) {
@@ -681,7 +640,7 @@
if (id > 0 && next.getAttribute("data-play-switch") != null) {
return id;
}
// 付费/VIP 锁定集:返回 id 以便弹窗
// 付费锁定集:返回 id 以便引导下载 APP
if (id > 0) return id;
}
next = next.nextElementSibling;
@@ -721,14 +680,17 @@
if (dp && typeof dp.on === "function") {
dp.on("timeupdate", updateNextCountdown);
dp.on("ended", function () {
markCurrentEpisodeWatched();
var chapterId = findNextChapterId();
setNextCountdownVisible(false, 3);
if (chapterId) switchToChapter(chapterId, { autoplay: true });
if (!chapterId) return;
if (isLockedEpisode(chapterId)) {
openDownloadApp();
return;
}
switchToChapter(chapterId, { autoplay: true });
});
dp.on("play", function () {
applyPlaySpeed(dp, currentPlaySpeed());
markCurrentEpisodeWatched();
updateNextCountdown();
});
dp.on("seeked", updateNextCountdown);
@@ -770,26 +732,6 @@
(playPage && playPage.getAttribute("data-play-episode")) || 0
);
var switchingChapter = false;
var lastWatchReportKey = "";
function reportChapterWatch() {
if (!currentChapterId || !window.HttpRequest) return;
if (window.CookieUtil && !window.CookieUtil.isLoggedIn()) return;
var key = String(playletId || 0) + ":" + currentChapterId;
if (key === lastWatchReportKey) return;
lastWatchReportKey = key;
var body = { chapterId: currentChapterId };
if (playletId) body.playletId = playletId;
window.HttpRequest.post("/api/playlet/chapter/watch/report", body).catch(
function () {
/* 静默失败:未登录/网络错误不打断播放 */
}
);
}
function markCurrentEpisodeWatched() {
reportChapterWatch();
}
function padEpisode(n) {
var num = Number(n) || 0;
@@ -802,92 +744,42 @@
return "/play/" + encodeURIComponent(key) + "/" + chapterId + "/";
}
function resolvePayGate(chapter, el) {
if (chapter) {
if (chapter.canWatch || chapter.isUnlocked) return 0;
if (chapter.needUnlock) return 1;
if (chapter.needVip) return 2;
var payType = Number(chapter.payType || 0);
if (payType === 1 || payType === 2) return payType;
return 0;
}
if (el) {
if (el.getAttribute("data-can-watch") === "1") return 0;
if (el.getAttribute("data-need-unlock") === "1") return 1;
if (el.getAttribute("data-need-vip") === "1") return 2;
if (el.getAttribute("data-coin-dialog-open") != null) return 1;
if (el.getAttribute("data-vip-dialog-open") != null) return 2;
return Number(el.getAttribute("data-pay-type") || 0);
}
return 0;
function isChapterLocked(chapter) {
if (!chapter) return false;
if (chapter.canWatch || chapter.isUnlocked) return false;
if (chapter.needUnlock || chapter.needVip) return true;
// 与服务端 PlayletChapterData.AllowWatch 保持一致:仅免费集可直接播放。
return Number(chapter.payType || 0) !== 0;
}
function resolveUnlockCost(chapter, el) {
if (chapter) {
if (Number(chapter.costCoins) > 0) return Number(chapter.costCoins);
if (Number(chapter.singleCoins) > 0) return Number(chapter.singleCoins);
}
if (el) return Number(el.getAttribute("data-single-coins") || 0);
return 0;
function isLockedEpisode(chapterId) {
chapterId = Number(chapterId) || 0;
if (!chapterId) return false;
return !!document.querySelector(
'[data-play-locked][data-chapter-id="' + chapterId + '"]'
);
}
function openPayForChapter(el, chapter) {
var payGate = resolvePayGate(chapter, el);
if (payGate === 1) {
if (typeof window.openCoinDialog === "function") {
var coinTrigger = document.createElement("button");
coinTrigger.setAttribute("data-coin-dialog-open", "");
coinTrigger.setAttribute(
"data-chapter-id",
String((chapter && chapter.id) || (el && el.getAttribute("data-chapter-id")) || "")
);
coinTrigger.setAttribute(
"data-playlet-id",
String(
(chapter && chapter.playletId) ||
playletId ||
(el && el.getAttribute("data-playlet-id")) ||
""
)
);
coinTrigger.setAttribute(
"data-single-coins",
String(resolveUnlockCost(chapter, el))
);
coinTrigger.style.display = "none";
document.body.appendChild(coinTrigger);
coinTrigger.click();
coinTrigger.remove();
}
return true;
// 付费剧集统一引导下载 APP(移动端跳转下载地址,PC 弹出下载二维码)。
function openDownloadApp() {
if (typeof window.openDownloadApp === "function") {
return window.openDownloadApp();
}
if (payGate === 2) {
var vipBtn = document.querySelector("[data-vip-dialog-open]");
if (vipBtn) vipBtn.click();
else if (typeof window.openVipDialog === "function") {
window.openVipDialog();
}
return true;
}
return false;
return Promise.resolve();
}
function updateEpisodeActive(chapterId) {
document.querySelectorAll(".play-ep").forEach(function (el) {
var isActive = Number(el.getAttribute("data-chapter-id") || 0) === chapterId;
el.classList.toggle("play-ep--active", isActive);
var coin = el.querySelector(".play-ep-coin");
var lock = el.querySelector(".play-ep-lock");
if (coin) coin.style.display = isActive ? "none" : "";
if (lock) lock.style.display = isActive ? "none" : "";
});
document.querySelectorAll(".play-ep-sheet-item").forEach(function (el) {
var isActive =
Number(el.getAttribute("data-chapter-id") || 0) === chapterId;
el.classList.toggle("play-ep-sheet-item--active", isActive);
var coin = el.querySelector(".play-ep-sheet-coin");
var lock = el.querySelector(".play-ep-sheet-lock");
if (coin) coin.hidden = isActive;
if (lock) lock.hidden = isActive;
});
syncDesktopNextControl();
@@ -897,7 +789,6 @@
var ep = Number(chapter.currentEpisode) || 0;
currentEpisode = ep;
currentChapterId = Number(chapter.id) || currentChapterId;
lastWatchReportKey = "";
if (playPage) {
playPage.setAttribute("data-play-episode", String(ep));
}
@@ -922,10 +813,6 @@
player.setAttribute("data-chapter-id", String(chapter.id || ""));
player.setAttribute("data-playlet-id", String(playletId || chapter.playletId || ""));
player.setAttribute("data-pay-type", String(chapter.payType || 0));
player.setAttribute(
"data-single-coins",
String(resolveUnlockCost(chapter, null))
);
player.setAttribute(
"data-can-watch",
chapter.canWatch || chapter.isUnlocked ? "1" : "0"
@@ -935,10 +822,6 @@
chapter.needUnlock ? "1" : "0"
);
player.setAttribute("data-need-vip", chapter.needVip ? "1" : "0");
player.setAttribute(
"data-is-unlocked",
chapter.isUnlocked ? "1" : "0"
);
}
var commentCount = document.querySelector("[data-play-comment-count]");
@@ -976,6 +859,8 @@
container.setAttribute("data-url", videoUrl || "");
if (playCover) container.setAttribute("data-cover", playCover);
player.insertBefore(container, player.firstChild);
var lockedCta = player.querySelector("[data-play-locked-cta]");
if (lockedCta) lockedCta.remove();
var playBtn = player.querySelector("[data-play-poster-play]");
if (!playBtn) {
playBtn = document.createElement("button");
@@ -1016,24 +901,18 @@
throw new Error((res && (res.tip || res.msg)) || "加载失败");
}
var chapter = res.data;
var payGate = resolvePayGate(chapter, null);
if (payGate !== 0 && !options.skipPayCheck) {
openPayForChapter(null, chapter);
if (isChapterLocked(chapter)) {
openDownloadApp();
return;
}
var videoUrl = resolvePlayUrl(chapter.videoUrl || "");
if (!videoUrl) {
if (payGate !== 0) {
openPayForChapter(null, chapter);
return;
}
throw new Error("暂无播放地址");
}
currentChapterId = Number(chapter.id) || chapterId;
updateEpisodeActive(currentChapterId);
updateChapterMeta(chapter);
markCurrentEpisodeWatched();
if (!options.skipHistory) {
var href = buildPlayHref(currentChapterId);
@@ -1049,8 +928,6 @@
if (playDp && typeof playDp.switchVideo === "function") {
switchPlayerVideo(playDp, videoOption);
syncPlayTrackerMeta();
bindPlayTracker(playDp);
} else {
ensurePlayerContainer(chapter.videoUrl || "");
playDp = initDPlayer();
@@ -1078,69 +955,6 @@
});
}
function markEpisodeUnlocked(chapterId) {
chapterId = Number(chapterId) || 0;
if (!chapterId) return;
var href = buildPlayHref(chapterId);
document
.querySelectorAll(
'.play-ep[data-chapter-id="' +
chapterId +
'"], .play-ep-sheet-item[data-chapter-id="' +
chapterId +
'"]'
)
.forEach(function (el) {
el.removeAttribute("data-coin-dialog-open");
el.removeAttribute("data-vip-dialog-open");
el.removeAttribute("data-single-coins");
el.setAttribute("data-play-switch", "");
el.setAttribute("href", href || "javascript:;");
var coin = el.querySelector(
".play-ep-coin, .play-ep-sheet-coin"
);
if (coin) coin.remove();
var lock = el.querySelector(
".play-ep-lock, .play-ep-sheet-lock"
);
if (lock) lock.remove();
});
var player = document.querySelector("[data-play-player]");
if (
player &&
Number(player.getAttribute("data-chapter-id") || 0) === chapterId
) {
player.setAttribute("data-pay-type", "0");
player.setAttribute("data-can-watch", "1");
player.setAttribute("data-need-unlock", "0");
player.setAttribute("data-need-vip", "0");
player.setAttribute("data-is-unlocked", "1");
player.removeAttribute("data-single-coins");
}
}
function playAfterChapterUnlock(detail) {
detail = detail || {};
var chapterId = Number(detail.chapterId) || 0;
if (!chapterId) return;
if (detail.playletId) {
playletId = Number(detail.playletId) || playletId;
if (playPage) {
playPage.setAttribute("data-playlet-id", String(playletId));
}
}
markEpisodeUnlocked(chapterId);
switchToChapter(chapterId, {
force: true,
skipPayCheck: true,
autoplay: true,
replace: true,
});
}
window.playAfterChapterUnlock = playAfterChapterUnlock;
function bindEpisodeSwitch() {
document.addEventListener("click", function (e) {
var el =
@@ -1154,12 +968,27 @@
switchToChapter(chapterId, { autoplay: true });
});
document.addEventListener("click", function (e) {
var el =
e.target && e.target.closest
? e.target.closest("[data-play-locked], [data-play-download-app]")
: null;
if (!el) return;
e.preventDefault();
openDownloadApp();
});
window.addEventListener("popstate", function (e) {
var match = String(window.location.pathname || "").match(/\/play\/[^/]+\/(\d+)\/?$/);
var chapterId =
(e.state && e.state.chapterId) ||
Number((match && match[1]) || 0);
if (!chapterId) return;
if (isLockedEpisode(chapterId)) {
// 回退到付费集:交给服务端渲染下载 APP 引导,避免自动跳转。
window.location.reload();
return;
}
switchToChapter(chapterId, {
autoplay: true,
skipHistory: true,
@@ -1176,14 +1005,6 @@
}
}
function maybeOpenPayDialog() {
var player = document.querySelector("[data-play-player]");
if (!player) return;
var hasVideo = !!player.querySelector(".dplayer-video[data-url]");
if (hasVideo) return;
openPayForChapter(player, null);
}
function bindSidebarRanges() {
var ranges = document.querySelectorAll("[data-play-ep-ranges] .play-ep-range");
var episodes = document.querySelectorAll("[data-play-ep-grid] .play-ep");
@@ -1349,44 +1170,11 @@
window.alert(message);
}
function trackPlayView() {
if (playViewTracked || !window.tracker || typeof window.tracker.videoEvent !== "function") return;
var meta = syncPlayTrackerMeta();
if (!meta.video_id) return;
playViewTracked = true;
window.tracker.videoEvent({
media_id: meta.media_id,
video_id: meta.video_id,
video_title: meta.video_title,
video_type_id: meta.video_type_id,
video_type_name: meta.video_type_name,
video_content_type: meta.video_content_type,
recommend_trace_id: meta.recommend_trace_id,
video_tag_key: meta.video_tag_key,
video_tag_name: meta.video_tag_name,
video_behavior_key: "video_view",
video_behavior_name: "视频展示",
});
}
function bindTrackingWhenReady(dp) {
function activateTracking() {
bindPlayTracker(dp || playDp);
trackPlayView();
}
activateTracking();
if (!window.__trackerReady) {
window.addEventListener("tracker:ready", activateTracking, { once: true });
}
}
function boot() {
var dp = initDPlayer();
bindH5PlayerUI(dp);
bindSidebarRanges();
bindEpisodeSwitch();
maybeOpenPayDialog();
bindTrackingWhenReady(dp);
if (typeof window.initLazyImages === "function") {
window.initLazyImages(document.querySelector(".play-page") || document);
}
-213
View File
@@ -1,213 +0,0 @@
(function () {
var mask = document.getElementById("registerDialog");
if (!mask) return;
var form = mask.querySelector("[data-register-dialog-form]");
var accountInput = mask.querySelector("[data-register-account]");
var passwordInput = mask.querySelector("[data-register-password]");
var confirmInput = mask.querySelector("[data-register-password-confirm]");
var submitBtn = mask.querySelector("[data-register-submit]");
var defaultSubmitText = (submitBtn && submitBtn.textContent) || "立即注册";
function setSubmitting(loading) {
if (!submitBtn) return;
submitBtn.disabled = !!loading;
submitBtn.classList.toggle("is-loading", !!loading);
submitBtn.setAttribute("aria-busy", loading ? "true" : "false");
submitBtn.textContent = loading ? "注册中..." : defaultSubmitText;
}
function getField(name) {
return mask.querySelector('[data-register-field="' + name + '"]');
}
function setFieldError(name, message) {
var field = getField(name);
if (!field) return;
var control = field.querySelector("[data-register-control]");
var error = field.querySelector("[data-register-error]");
if (control) control.classList.add("is-error");
if (error) {
error.textContent = message;
error.hidden = false;
}
}
function clearFieldError(name) {
var field = getField(name);
if (!field) return;
var control = field.querySelector("[data-register-control]");
var error = field.querySelector("[data-register-error]");
if (control) control.classList.remove("is-error");
if (error) error.hidden = true;
}
function clearAllErrors() {
clearFieldError("account");
clearFieldError("password");
clearFieldError("password_confirm");
}
function isValidLength(value) {
return value.length >= 4 && value.length <= 16;
}
function validateForm() {
var account = (accountInput && accountInput.value.trim()) || "";
var password = (passwordInput && passwordInput.value) || "";
var confirm = (confirmInput && confirmInput.value) || "";
var valid = true;
clearAllErrors();
if (!account) {
setFieldError("account", "请输入账号");
valid = false;
} else if (!isValidLength(account)) {
setFieldError("account", "账号需为 4–16 个字符");
valid = false;
}
if (!password) {
setFieldError("password", "请输入密码");
valid = false;
} else if (!isValidLength(password)) {
setFieldError("password", "密码需为 4–16 个字符");
valid = false;
}
if (!confirm) {
setFieldError("password_confirm", "请再次输入密码");
valid = false;
} else if (confirm !== password) {
setFieldError("password_confirm", "两次输入的密码不一致");
valid = false;
}
if (!valid) return null;
return { accountNo: account, password: password };
}
function mapServerError(err) {
var tip = (err && err.message) || "注册失败,请稍后重试";
var code = err && err.code;
if (code === 5005 || /已存在|重复|占用/.test(tip)) {
setFieldError("account", tip);
return;
}
if (/密码|password/i.test(tip)) {
setFieldError("password", tip);
return;
}
if (window.AuthAPI) AuthAPI.toast(tip, "error");
else if (typeof showToast === "function") showToast(tip, "error");
}
function openDialog(event) {
if (event) event.preventDefault();
if (typeof window.closeLoginDialog === "function") {
window.closeLoginDialog();
}
clearAllErrors();
mask.classList.add("is-open");
document.body.style.overflow = "hidden";
return true;
}
function closeDialog() {
mask.classList.remove("is-open");
clearAllErrors();
if (!document.getElementById("loginDialog") || !document.getElementById("loginDialog").classList.contains("is-open")) {
document.body.style.overflow = "";
}
}
if (form) {
form.addEventListener("submit", function (event) {
event.preventDefault();
if (submitBtn && submitBtn.classList.contains("is-loading")) return;
var payload = validateForm();
if (!payload) return;
if (!window.AuthAPI || !window.HttpRequest) {
return;
}
setSubmitting(true);
AuthAPI.register(payload)
.then(function () {
AuthAPI.toast("注册成功", "success");
closeDialog();
setTimeout(function () {
window.location.reload();
}, 400);
})
.catch(function (err) {
setSubmitting(false);
mapServerError(err);
});
});
}
function consumeAuthQuery(kind) {
var params = new URLSearchParams(window.location.search);
if (params.get("auth") !== kind) return false;
params.delete("auth");
var qs = params.toString();
var next = window.location.pathname + (qs ? "?" + qs : "") + window.location.hash;
window.history.replaceState(null, "", next);
return true;
}
if (accountInput) {
accountInput.addEventListener("input", function () {
clearFieldError("account");
});
}
if (passwordInput) {
passwordInput.addEventListener("input", function () {
clearFieldError("password");
});
}
if (confirmInput) {
confirmInput.addEventListener("input", function () {
clearFieldError("password_confirm");
});
}
document.addEventListener("click", function (event) {
var openEl = event.target.closest("[data-register-dialog-open]");
if (openEl) {
openDialog(event);
return;
}
var registerLink = event.target.closest('a[href="/register/"], a[href="#register"]');
if (registerLink) {
openDialog(event);
return;
}
if (event.target.closest("[data-register-dialog-close]")) {
closeDialog();
return;
}
if (event.target === mask) {
closeDialog();
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && mask.classList.contains("is-open")) {
closeDialog();
}
});
window.openRegisterDialog = openDialog;
window.closeRegisterDialog = closeDialog;
if ((document.body && document.body.getAttribute("data-auth-mode") === "register") || consumeAuthQuery("register")) {
openDialog();
}
})();
-34
View File
@@ -1,34 +0,0 @@
(function () {
document.querySelectorAll(".setting-switch").forEach(function (btn) {
btn.addEventListener("click", function () {
var on = btn.classList.toggle("setting-switch--on");
btn.setAttribute("aria-pressed", on ? "true" : "false");
});
});
var logoutBtn = document.querySelector("[data-auth-logout]");
if (logoutBtn) {
logoutBtn.addEventListener("click", function () {
function done() {
if (window.AuthAPI && typeof AuthAPI.markGuestLogout === "function") {
AuthAPI.markGuestLogout();
}
if (window.CookieUtil && typeof CookieUtil.clearAuth === "function") {
CookieUtil.clearAuth();
}
try {
document.dispatchEvent(new CustomEvent("auth:logout"));
} catch (e) {}
window.location.href = "/";
}
if (window.HttpRequest) {
HttpRequest.post("/api/auth/logout", {})
.catch(function () {})
.then(done);
} else {
done();
}
});
}
})();
-161
View File
@@ -1,161 +0,0 @@
(function () {
function parseExpireTime(value) {
if (value == null || value === "") return NaN;
if (typeof value === "number") {
return value < 1e12 ? value * 1000 : value;
}
var text = String(value).trim();
if (!text) return NaN;
if (/^\d+$/.test(text)) {
var num = Number(text);
return num < 1e12 ? num * 1000 : num;
}
return Date.parse(text);
}
function isVipActive(user) {
if (!user) return false;
var type = Number(user.vipType);
if (!type || type === 0) return false;
var expireMs = parseExpireTime(user.currentVipExpire);
if (!isFinite(expireMs) || expireMs <= 0) return false;
return expireMs > Date.now();
}
function vipTypeLabel(vipType) {
var type = Number(vipType);
if (type === 1) return "月卡会员";
if (type === 2) return "年卡会员";
return "普通会员";
}
function vipDisplayLabel(user) {
var name = user && String(user.showCardName || "").trim();
if (name) return name;
return vipTypeLabel(user && user.vipType);
}
function vipExpireText(raw) {
var ms = parseExpireTime(raw);
if (!isFinite(ms) || ms <= 0) return "";
var d = new Date(ms);
var y = d.getFullYear();
var m = String(d.getMonth() + 1).padStart(2, "0");
var day = String(d.getDate()).padStart(2, "0");
return "有效期至 " + y + "/" + m + "/" + day;
}
function formatRecharge(value) {
var n = Number(value);
if (!isFinite(n) || n < 0) n = 0;
return String(Math.floor(n)).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
function syncUserCenterRecharge(value) {
var text = formatRecharge(
value != null
? value
: CookieUtil.getAuthSession() && CookieUtil.getAuthSession().recharge,
);
var pc = document.querySelector("[data-user-center-recharge]");
if (pc) pc.textContent = text;
var hint = document.querySelector("[data-user-center-recharge-hint]");
if (hint) hint.textContent = text + "金币";
}
function syncUserCenterID(value) {
var id = String(value == null ? "" : value).trim();
if (!id) return;
document.querySelectorAll("[data-user-center-id]").forEach(function (el) {
el.textContent = el.getAttribute("data-id-layout") === "pc"
? "ID:" + id
: "ID " + id;
});
}
function refreshUserCenterWallet() {
if (!window.CookieUtil || !CookieUtil.isLoggedIn()) return;
syncUserCenterRecharge();
if (!window.HttpRequest) return;
HttpRequest.get("/api/auth/getInfo")
.then(function (res) {
if (!res || res.code !== 200 || !res.data) return;
if (CookieUtil.setAuthSession) CookieUtil.setAuthSession(res.data);
syncUserCenterID(res.data.userId);
syncUserCenterRecharge(res.data.recharge);
syncUserCenterVip();
})
.catch(function () {});
}
function syncUserCenterVip() {
if (!window.CookieUtil || !CookieUtil.isLoggedIn()) return;
var session = CookieUtil.getAuthSession();
var active = isVipActive(session);
var label = active ? vipDisplayLabel(session) : "";
var expire = active
? vipExpireText(session && session.currentVipExpire)
: "";
var pc = document.querySelector("[data-user-center-vip]");
if (pc) {
pc.classList.toggle("user-center-vip-card--active", active);
var status = pc.querySelector("[data-vip-status]");
var expireEl = pc.querySelector("[data-vip-expire]");
var action = pc.querySelector("[data-vip-action]");
if (status) {
status.textContent = active ? "尊享 VIP 会员" : "尚未开通会员";
}
if (expireEl) {
if (active && expire) {
expireEl.hidden = false;
expireEl.style.display = "";
expireEl.textContent = expire;
} else {
expireEl.hidden = true;
expireEl.style.display = "none";
expireEl.textContent = "";
}
}
if (action) {
if (active) {
action.hidden = true;
action.style.display = "none";
} else {
action.hidden = false;
action.style.display = "";
action.textContent = "立即开通 →";
}
}
}
var mobile = document.querySelector("[data-user-center-mobile-vip]");
if (mobile) {
mobile.classList.toggle("user-center-mobile-vip--active", active);
var title = mobile.querySelector("[data-mobile-vip-title]");
var desc = mobile.querySelector("[data-mobile-vip-desc]");
var btn = mobile.querySelector("[data-mobile-vip-btn]");
if (title) title.textContent = active ? label : "开通黄果短剧会员";
if (desc) {
desc.textContent = active
? expire || "全场免费看 · 热门短剧抢先看"
: "全场免费看 · 热门短剧抢先看";
}
if (btn) {
btn.hidden = false;
btn.style.display = "";
if (active) {
btn.textContent = "续费会员";
} else {
btn.textContent = "立即开通";
}
}
}
}
syncUserCenterVip();
refreshUserCenterWallet();
window.syncUserCenterVip = syncUserCenterVip;
window.syncUserCenterID = syncUserCenterID;
window.syncUserCenterRecharge = syncUserCenterRecharge;
})();
-52
View File
@@ -1,52 +0,0 @@
(function () {
var mask = document.getElementById("vipDialog");
if (!mask) return;
function openDialog(event) {
if (event) event.preventDefault();
mask.classList.add("is-open");
document.body.style.overflow = "hidden";
}
function closeDialog() {
mask.classList.remove("is-open");
document.body.style.overflow = "";
}
function isVipLockedEpisode(target) {
var episode = target.closest(
".detail-episode, .play-ep, .play-ep-sheet-item, .detail-h5-ep-item"
);
if (!episode) return false;
// 金币解锁走 coinDialog,不在此打开 VIP 弹窗
if (episode.hasAttribute("data-coin-dialog-open")) return false;
return !!episode.querySelector(
".detail-episode-lock[src*='vip'], .detail-episode-vip, .play-ep-lock[src*='vip'], .play-ep-sheet-lock[src*='vip'], .detail-h5-ep-lock[src*='vip']"
);
}
document.addEventListener("click", function (event) {
if (event.target.closest("[data-vip-dialog-open]") || isVipLockedEpisode(event.target)) {
openDialog(event);
return;
}
if (event.target.closest("[data-vip-dialog-close]")) {
closeDialog();
return;
}
if (event.target === mask) {
closeDialog();
}
});
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && mask.classList.contains("is-open")) {
closeDialog();
}
});
window.openVipDialog = openDialog;
window.closeVipDialog = closeDialog;
})();