Files
web_huangguo2_h5/app/static/js/recharge-modal.js
T
谢宇宁andClaude Opus 5.5 0fbdba5ccf Initial commit
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:47:47 +07:00

247 lines
8.4 KiB
JavaScript

(function () {
var root = document.querySelector("[data-recharge-modal]");
if (!root) return;
var panel = root.querySelector(".recharge-modal__panel");
var openers = document.querySelectorAll("[data-recharge-open]");
var closers = root.querySelectorAll("[data-recharge-close]");
var packagesRoot = root.querySelector("[data-recharge-packages]");
var methodsRoot = root.querySelector("[data-recharge-methods]");
var amount = root.querySelector("[data-recharge-amount]");
var pay = root.querySelector("[data-recharge-pay]");
var status = root.querySelector("[data-recharge-status]");
var previousOverflow = "";
var returnFocus = null;
var paying = false;
function packages() {
return root.querySelectorAll("[data-recharge-package]");
}
function methods() {
return root.querySelectorAll("[data-recharge-method]");
}
function showStatus(message, ok) {
if (!status) return;
status.textContent = message || "";
status.hidden = !message;
status.classList.toggle("is-ok", !!ok);
}
function open(trigger) {
if (!root.hidden) return;
var oldDialog = document.querySelector("[data-play-coin].is-open");
if (oldDialog) {
var oldClose = oldDialog.querySelector("button[data-play-coin-close]");
if (oldClose) oldClose.click();
}
returnFocus = trigger && oldDialog ? document.querySelector("[data-play-coin-open]") : trigger;
previousOverflow = document.body.style.overflow;
showStatus("");
root.hidden = false;
document.body.style.overflow = "hidden";
if (panel) panel.focus();
}
function close() {
if (root.hidden) return;
root.hidden = true;
document.body.style.overflow = previousOverflow;
if (returnFocus && typeof returnFocus.focus === "function") returnFocus.focus();
}
function parsePayMethods(raw) {
try {
var list = JSON.parse(raw || "[]");
return Array.isArray(list) ? list : [];
} catch (e) {
return [];
}
}
function renderMethods(list) {
if (!methodsRoot) return;
methodsRoot.replaceChildren();
if (!list.length) {
var empty = document.createElement("p");
empty.className = "recharge-modal__empty";
empty.textContent = "该套餐暂无可用支付方式";
methodsRoot.appendChild(empty);
return;
}
list.forEach(function (item, index) {
var type = String((item && item.type) || "").trim();
var name = String((item && item.typeName) || type || "支付").trim();
if (!type) return;
var btn = document.createElement("button");
btn.className = "recharge-modal__method" + (index === 0 ? " is-selected" : "");
btn.type = "button";
btn.setAttribute("data-recharge-method", type);
btn.setAttribute("aria-pressed", index === 0 ? "true" : "false");
btn.innerHTML =
'<span class="recharge-modal__method-check" aria-hidden="true"><img src="/static/images/placeholder.png?v=2" data-src="/static/images/recharge/check.svg" alt="" loading="lazy" decoding="async"></span>' +
'<span class="recharge-modal__method-copy"><span></span><small>即时到账</small></span>';
btn.querySelector(".recharge-modal__method-copy span").textContent = name;
methodsRoot.appendChild(btn);
});
if (typeof window.initLazyImages === "function") {
window.initLazyImages(methodsRoot);
}
}
function selectPackage(button) {
Array.prototype.forEach.call(packages(), function (item) {
var selected = item === button;
item.classList.toggle("is-selected", selected);
item.setAttribute("aria-pressed", String(selected));
});
if (amount) amount.textContent = "¥" + (button.getAttribute("data-price") || "0");
renderMethods(parsePayMethods(button.getAttribute("data-pay-methods")));
showStatus("");
}
function bindMethodClicks() {
if (!methodsRoot) return;
methodsRoot.addEventListener("click", function (event) {
var button = event.target.closest("[data-recharge-method]");
if (!button || !methodsRoot.contains(button)) return;
Array.prototype.forEach.call(methods(), function (item) {
var selected = item === button;
item.classList.toggle("is-selected", selected);
item.setAttribute("aria-pressed", String(selected));
});
showStatus("");
});
}
Array.prototype.forEach.call(openers, function (button) {
button.addEventListener("click", function (event) {
event.preventDefault();
open(button);
});
});
Array.prototype.forEach.call(closers, function (element) {
element.addEventListener("click", close);
});
if (packagesRoot) {
packagesRoot.addEventListener("click", function (event) {
var button = event.target.closest("[data-recharge-package]");
if (!button || !packagesRoot.contains(button)) return;
selectPackage(button);
});
}
bindMethodClicks();
if (pay) {
pay.addEventListener("click", function () {
if (paying) return;
var selectedPackage = root.querySelector("[data-recharge-package].is-selected");
var selectedMethod = root.querySelector("[data-recharge-method].is-selected");
var packageId = selectedPackage ? Number(selectedPackage.getAttribute("data-package-id") || 0) : 0;
var payMode = selectedMethod ? selectedMethod.getAttribute("data-recharge-method") : "";
if (!packageId) {
showStatus("请选择充值套餐");
return;
}
if (!payMode) {
showStatus("请选择支付方式");
return;
}
paying = true;
pay.disabled = true;
showStatus("正在创建支付订单…");
var payload = { packageId: packageId, payMode: payMode };
var req =
window.HttpRequest && typeof window.HttpRequest.post === "function"
? window.HttpRequest.post("/api/coin/buy", payload)
: fetch("/api/coin/buy", {
method: "POST",
credentials: "same-origin",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
}).then(function (r) {
return r.json().then(function (body) {
return body;
});
});
req
.then(function (result) {
if (!result || Number(result.code) !== 200 || !result.data || !result.data.payUrl) {
throw new Error((result && (result.tip || result.msg)) || "创建支付订单失败");
}
showStatus("订单创建成功,正在前往支付…", true);
openPayInNewWindow(result.data.payUrl);
paying = false;
pay.disabled = false;
})
.catch(function (error) {
showStatus((error && error.message) || "创建支付订单失败,请稍后重试");
paying = false;
pay.disabled = false;
});
});
}
function openPayInNewWindow(url) {
url = String(url || "").trim();
if (!url) return;
var opened = null;
try {
opened = window.open(url, "_blank", "noopener,noreferrer");
} catch (e) {
opened = null;
}
if (opened) {
try {
opened.opener = null;
} catch (e2) {}
showStatus("已在新窗口打开支付页面,请完成支付后返回本页", true);
return;
}
// 弹窗被拦截时用 <a target=_blank> 再试,仍不跳转当前页
var link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.rel = "noopener noreferrer";
link.style.display = "none";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showStatus("若未打开支付页,请允许本站弹窗后重试", true);
}
document.addEventListener("keydown", function (event) {
if (root.hidden) return;
if (event.key === "Escape") {
event.preventDefault();
close();
return;
}
if (event.key !== "Tab") return;
var focusable = root.querySelectorAll("button:not([disabled]), a[href]");
if (!focusable.length) return;
var first = focusable[0];
var last = focusable[focusable.length - 1];
if (event.shiftKey && (document.activeElement === first || document.activeElement === panel)) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first.focus();
}
});
window.openRechargeModal = function (trigger) {
open(trigger || null);
};
if (new URLSearchParams(window.location.search).get("recharge") === "1") open(null);
})();