/** * AKSRT VIP pay modal — JSON view model + canonical purchase coordinator. * * @package AKSRT */ (function () { "use strict"; function text(value) { return String(value == null ? "" : value); } function node(tag, className, value) { var el = document.createElement(tag); if (className) el.className = className; if (value !== undefined && value !== null) el.textContent = text(value); return el; } function imageNode(src, className) { if (!src) return null; var image = document.createElement("img"); image.className = className || ""; image.src = text(src); image.alt = ""; image.decoding = "async"; return image; } function append(parent, child) { if (child) parent.appendChild(child); return child; } function levelMap(levels) { var map = Object.create(null); (Array.isArray(levels) ? levels : []).forEach(function (level) { if (level && level.level) map[String(level.level)] = level; }); return map; } function actionLabel(action) { if (action === "renew") return "续费"; if (action === "upgrade") return "升级"; return "开通"; } function actionKey(action) { return action === "pay" ? "purchase" : action; } function actionReason(reason) { if (reason === "no_package") return "暂无可用套餐"; if (reason === "not_available") return "当前不可用"; return ""; } // 会员图标(Zibll zibpay_get_vip_icon:vip_N.svg 或自定义 img_icon)。 function vipIcon(levelInfo) { if (levelInfo && levelInfo.img_icon) { var img = node("img", "img-icon"); img.src = text(levelInfo.img_icon); img.alt = text(levelInfo.name || ""); img.decoding = "async"; return img; } return node("i", "fa fas fa-gem"); } // 价格行(Zibll:mark 小号 px12 前缀 + 数字;原价 original-price.relative)。 function priceRow(mark, priceLabel, showLabel) { var row = node("div", "flex abl gap6"); var price = node("div", "product-price c-red"); var label = text(priceLabel || ""); if (mark && label.indexOf(mark) === 0) { append(price, node("span", "px12", mark)); append(price, node("span", "", label.slice(mark.length))); } else { append(price, node("span", "", label)); } append(row, price); if (showLabel) { var original = node("div", "original-price relative muted-2-color"); var showText = text(showLabel); if (mark && showText.indexOf(mark) === 0) { append(original, node("span", "px12", mark)); append(original, node("span", "", showText.slice(mark.length))); } else { append(original, node("span", "", showText)); } append(row, original); } return row; } function renderProducts(parent, items, mark) { if (!Array.isArray(items) || !items.length) { append(parent, node("div", "muted-2-color text-center padding-10", "暂无可用套餐")); return; } var wrap = node("div", "mb10 label-box charge-box"); items.forEach(function (item, index) { if (!item || !item.package_id) return; var label = node("label"); var input = node("input"); input.className = "hide vip-product-input"; input.type = "radio"; input.name = "vip_product_id"; input.value = String(item.package_id); input.setAttribute("data-aksrt-vip-package", ""); input.checked = index === 0; append(label, input); // Zibll 套餐卡:zib-widget vip-product relative text-center product-box // (右上 tag + 价格行 + 时长 badge,无标题行)。 var product = node("div", "zib-widget vip-product relative text-center product-box"); if (item.discount_tag) append(product, node("div", "abs-right vip-tag badg jb-yellow", item.discount_tag)); append(product, priceRow(mark, item.price_label || "", item.show_price_label || "")); if (item.days_label) append(product, node("div", "muted-2-color c-blue em09 p2-10 badg radius", item.days_label)); append(label, product); append(wrap, label); }); append(parent, wrap); } function renderMethods(parent, methods, cardPass, wallet) { methods = Array.isArray(methods) ? methods : []; if (!methods.length) return; // 无可用支付方式:由按钮区渲染 Zibll 同款 badg 提示。 wallet = wallet || {}; var defaultMethod = text(methods[0].id || "balance"); // 支付方式选择行(Zibll zibpay_get_initiate_pay_input 同构: // .payment-method-radio.hollow-radio + logo 图 + data-for 选中模型; // 与余额充值/购买积分弹窗完全一致的组件)。 if (methods.length > 1) { append(parent, node("div", "muted-2-color em09 mb6", "请选择支付方式")); var row = node("div", "flex mb10"); methods.forEach(function (method, index) { var id = text(method.id || "balance"); var item = node("div", "flex jc hh payment-method-radio hollow-radio flex-auto pointer" + (index === 0 ? " active" : "")); item.setAttribute("data-for", "payment_method"); item.setAttribute("data-value", id); if (method.logo) { var img = node("img"); img.src = text(method.logo); img.alt = id + "-logo"; img.decoding = "async"; append(item, img); } append(item, node("div", "", method.name || id || "")); append(row, item); }); append(parent, row); } // 我的余额盒(Zibll user_balance_box 同构:选中余额渠道时显示)。 if (methods.some(function (m) { return text(m.id) === "balance"; })) { var balanceBox = node("div", "mb10 muted-box padding-h10"); balanceBox.setAttribute("data-controller", "payment_method"); balanceBox.setAttribute("data-condition", "=="); balanceBox.setAttribute("data-value", "balance"); if (defaultMethod !== "balance") balanceBox.style.display = "none"; var balanceRow = node("div", "flex jsb ac"); append(balanceRow, node("span", "muted-2-color", "我的余额")); var balanceValue = node("div", "c-blue-2"); append(balanceValue, node("span", "px12 mr3", wallet.mark || "¥")); append(balanceValue, node("span", "em14", text(wallet.balance || "0.00"))); append(balanceRow, balanceValue); append(balanceBox, balanceRow); append(parent, balanceBox); } // 卡密盒(Zibll password_box 同构:mb10 padding-h10 padding-w6 + // data-controller="payment_method" 契约 + form-control 输入)。 if (cardPass) { var box = node("div", "mb10 padding-h10 padding-w6"); box.setAttribute("data-controller", "payment_method"); box.setAttribute("data-condition", "=="); box.setAttribute("data-value", "card_pass"); if (defaultMethod !== "card_pass") box.style.display = "none"; if (cardPass.desc) append(box, node("div", "muted-box muted-2-color padding-10 mb10 em09", cardPass.desc)); append(box, node("div", "muted-2-color em09 mb6", cardPass.only_password ? "请输入卡密" : "请输入卡号和密码")); if (!cardPass.only_password) { var cardInput = node("input", "form-control mb6"); cardInput.type = "text"; cardInput.name = "card_pass[card]"; cardInput.placeholder = "卡号"; cardInput.autocomplete = "off"; append(box, cardInput); } var pwInput = node("input", "form-control"); pwInput.type = "text"; pwInput.name = "card_pass[password]"; pwInput.placeholder = "卡密"; pwInput.autocomplete = "off"; append(box, pwInput); append(parent, box); } var hidden = node("input"); hidden.type = "hidden"; hidden.name = "payment_method"; hidden.value = defaultMethod; append(parent, hidden); } // 渠道显隐:通用 data-controller 契约(==/!= 匹配当前 payment_method); // 选中 card_pass 时隐藏套餐(.charge-box),与参考主题 pay.js 行为一致。 function applyVipMethodVisibility(root) { var pane = root.closest ? root.closest(".aksrt-vip-pane") : null; pane = pane || root; var value = selectedMethod(pane); pane.querySelectorAll('[data-controller="payment_method"]').forEach(function (el) { var condition = el.getAttribute("data-condition") || "=="; var target = el.getAttribute("data-value") || ""; var match = condition === "!=" ? value !== target : value === target; el.style.display = match ? "" : "none"; }); pane.querySelectorAll(".charge-box").forEach(function (el) { el.style.display = value === "card_pass" ? "none" : ""; }); } // ===== 积分兑换会员弹窗(参考主题 refresh_modal 同构静态壳) ===== // 弹窗壳由服务端静态输出(inc/helpers/aksrt-vip.php → wp_footer), // 此处只负责开合与提交,形态对齐余额充值/购买积分弹窗的自包含开关: // .in 显隐 + .modal-backdrop + body.modal-open + ESC,不依赖 jQuery/Bootstrap // modal 运行时。 var pointsBackdrop = null; var pointsBound = false; var pointsFocusReturn = null; function pointsModal() { return document.querySelector("[data-aksrt-vip-points-modal]"); } function openPointsModal(trigger) { var modal = pointsModal(); if (!modal || modal.classList.contains("in")) return; bindPointsModal(); pointsFocusReturn = trigger || document.activeElement; // 打开态用 flex 而非 block:壳的 .flex.jc 负责双轴居中 // (.modal.flex .modal-dialog{margin:0} 在 block 下会把对话框顶到左上角)。 modal.style.display = "flex"; void modal.offsetWidth; // 强制 reflow,让 .fade 过渡从初始态开始 modal.classList.add("in"); if (!pointsBackdrop) { pointsBackdrop = document.createElement("div"); pointsBackdrop.className = "modal-backdrop fade in"; pointsBackdrop.setAttribute("data-aksrt-vip-points-backdrop", "1"); document.body.appendChild(pointsBackdrop); } document.body.classList.add("modal-open"); // 焦点移入兑换弹窗:ESC 只收起本层,不会冒泡到下层会员弹窗。 var closeBtn = modal.querySelector('[data-dismiss="modal"]'); try { (closeBtn || modal).focus(); } catch (error) {} } function closePointsModal() { var modal = pointsModal(); if (!modal || !modal.classList.contains("in")) return; modal.classList.remove("in"); // 同页可能另有静态弹窗(余额充值/购买积分)打开,仅在没有 .modal.in 时解锁。 if (!document.querySelector(".modal.in")) document.body.classList.remove("modal-open"); if (pointsBackdrop && pointsBackdrop.parentNode) pointsBackdrop.parentNode.removeChild(pointsBackdrop); pointsBackdrop = null; window.setTimeout(function () { if (modal && !modal.classList.contains("in")) modal.style.display = ""; var target = pointsFocusReturn; pointsFocusReturn = null; if (target && document.contains(target) && typeof target.focus === "function") { try { target.focus(); } catch (error) {} } }, 300); } function exchangePoints(button) { var modal = pointsModal(); if (!modal || !button || button.disabled) return; var hidden = modal.querySelector('input[name="product_id"]'); var packageId = hidden ? parseInt(hidden.value, 10) || 0 : 0; if (!packageId) { notyf("请选择兑换套餐", "danger"); return; } var coordinator = window.AksrtVipPurchaseCoordinator; if (!coordinator || typeof coordinator.exchange !== "function") { notyf("会员兑换暂不可用", "danger"); return; } button.disabled = true; button.classList.add("is-loading"); notyf("正在兑换会员…", "load", "", "aksrt-vip-points-toast"); coordinator.exchange({ packageId: packageId, tags: ["vip", "orders"] }).then(function (response) { button.disabled = false; button.classList.remove("is-loading"); if (response && response.ok) { var data = response.data || response.json || {}; notyf(data.message || "兑换成功,正在刷新…", "success", 5, "aksrt-vip-points-toast"); window.setTimeout(function () { window.location.reload(); }, 800); return; } notyf(response && response.json && response.json.message ? response.json.message : "兑换失败,请重试。", "danger", 5, "aksrt-vip-points-toast"); }).catch(function () { button.disabled = false; button.classList.remove("is-loading"); notyf("网络异常,请稍后重试。", "danger", 5, "aksrt-vip-points-toast"); }); } function bindPointsModal() { var modal = pointsModal(); if (!modal || pointsBound) return; pointsBound = true; modal.addEventListener("click", function (event) { // 参考主题契约:点遮罩(壳自身)或 data-dismiss="modal" 关闭按钮收起弹窗。 if (event.target === modal || (event.target.closest && event.target.closest('[data-dismiss="modal"]'))) { closePointsModal(); return; } // 参考主题 data-for/data-value 选中模型:会员兑换卡片。 var card = event.target.closest ? event.target.closest('[data-for="product_id"]') : null; if (!card) return; modal.querySelectorAll('[data-for="product_id"]').forEach(function (el) { el.classList.toggle("active", el === card); }); var hidden = modal.querySelector('input[name="product_id"]'); if (hidden) hidden.value = card.getAttribute("data-value") || ""; }); var form = modal.querySelector("[data-aksrt-vip-points-form]"); if (form) { form.addEventListener("submit", function (event) { event.preventDefault(); exchangePoints(modal.querySelector("[data-aksrt-vip-points-submit]")); }); } document.addEventListener("keydown", function (event) { if (event.key === "Escape" && modal.classList.contains("in")) closePointsModal(); }); } function renderModalView(body, view) { view = view || {}; if (body.replaceChildren) body.replaceChildren(); else body.innerHTML = ""; if (!view.enabled) { append(body, node("div", "box-body payvip-modal text-center padding-20", "会员功能未启用。")); return; } var catalog = view.catalog || {}; var member = view.member || {}; var levels = levelMap(view.levels); var groups = Array.isArray(catalog.level_packages) ? catalog.level_packages : []; var methods = Array.isArray(view.payment_methods) ? view.payment_methods : []; var cardPass = view.card_pass && view.card_pass.enabled ? view.card_pass : null; var wallet = { balance: text(catalog.wallet_balance || "0.00"), mark: text(view.currency_mark || "¥") }; var allowed = view.allowed_actions || {}; var reasons = view.action_reasons || {}; var modal = node("div", "box-body payvip-modal"); modal.setAttribute("data-aksrt-vip-modal", ""); if (view.version && view.version.catalog) modal.setAttribute("data-aksrt-vip-version", view.version.catalog); // 关闭按钮(Zibll 原版内联 SVG close 图标)。 var close = document.createElement("button"); close.type = "button"; close.className = "close"; close.setAttribute("data-aksrt-modal-close", ""); close.setAttribute("aria-hidden", "true"); close.setAttribute("aria-label", "关闭"); var closeSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); closeSvg.setAttribute("class", "ic-close"); closeSvg.setAttribute("viewBox", "0 0 1024 1024"); var closePath = document.createElementNS("http://www.w3.org/2000/svg", "path"); closePath.setAttribute("d", "M573.44 512.128l237.888 237.696a43.328 43.328 0 0 1 0 59.712 43.392 43.392 0 0 1-59.712 0L513.728 571.84 265.856 819.712a44.672 44.672 0 0 1-61.568 0 44.672 44.672 0 0 1 0-61.568L452.16 510.272 214.208 272.448a43.328 43.328 0 0 1 0-59.648 43.392 43.392 0 0 1 59.712 0l237.952 237.76 246.272-246.272a44.672 44.672 0 0 1 61.568 0 44.672 44.672 0 0 1 0 61.568L573.44 512.128z"); closeSvg.appendChild(closePath); close.appendChild(closeSvg); append(modal, close); // 用户信息(Zibll:list-inline user-box)。 var userBox = node("ul", "list-inline user-box"); var avatarItem = node("li"); var avatarWrap = node("div", "avatar-img"); if (member.avatar_url) { var avatar = node("img"); avatar.src = text(member.avatar_url); avatar.alt = ""; avatar.width = 42; avatar.height = 42; append(avatarWrap, avatar); } append(avatarItem, avatarWrap); append(userBox, avatarItem); var userInfo = node("li"); append(userInfo, node("b", "em12", member.name || "")); if (member.level > 0) { var expiry = node("div", "muted-2-color em09"); var badge = node("span", "badg c-yellow vip-expdate-tag", member.expires_label || ""); append(expiry, badge); append(userInfo, expiry); } else if (member.state === "expired") { append(userInfo, node("div", "muted-2-color em09", "已过期")); } else if (catalog.desc) { append(userInfo, node("div", "muted-2-color em09", catalog.desc)); } append(userBox, userInfo); append(modal, userBox); // 会员缩略卡 tabs(Zibll vip-cardminis:vip-card.vip-cardmini + active-icon 勾)。 var tabs = node("ul", "flex jsb mt10 mb20 vip-cardminis gutters-5"); var content = node("div", "tab-content mt10"); var activeIndex = -1; groups.forEach(function (group, index) { if (activeIndex >= 0 || !group) return; if (Number(group.level) === Number(view.prefer_level)) activeIndex = index; }); if (activeIndex < 0 && groups.length) activeIndex = 0; groups.forEach(function (group, index) { if (!group || !Array.isArray(group.items) || !group.items.length) return; var level = Number(group.level || 0); var action = text(group.action || "pay"); var tabId = "tab-payvip-" + level; var active = index === activeIndex; var levelInfo = levels[String(level)] || {}; var tabItem = node("li", "relative" + (active ? " active" : "")); var tab = document.createElement("a"); tab.href = "javascript:;"; tab.setAttribute("data-vip-tab", tabId); var miniCard = node("div", "vip-card vip-cardmini level-" + level + " vip-theme" + level); var miniBa = node("div", "abs-center vip-baicon"); append(miniBa, vipIcon(levelInfo)); append(miniCard, miniBa); var miniIconbox = node("div", "v-iconbox flex ac gap10"); var miniIcon = node("div", "v-icon flex jc"); append(miniIcon, vipIcon(levelInfo)); append(miniIconbox, miniIcon); var miniInfo = node("div", "v-info"); append(miniInfo, node("div", "v-name", actionLabel(action) + (levelInfo.name || group.name || "VIP" + level))); append(miniInfo, node("div", "v-desc em09", levelInfo.desc || "")); append(miniIconbox, miniInfo); append(miniCard, miniIconbox); append(tab, miniCard); append(tabItem, tab); var activeIcon = node("div", "abs-right active-icon"); append(activeIcon, node("i", "fa fas fa-check-circle")); activeIcon.setAttribute("aria-hidden", "true"); append(tabItem, activeIcon); append(tabs, tabItem); // pane(Zibll tab-pane fade active in)。 var pane = node("div", "tab-pane fade aksrt-vip-pane" + (active ? " active in" : "")); pane.id = tabId; pane.hidden = !active; var form = document.createElement("form"); form.setAttribute("onsubmit", "return false;"); var row = node("div", "pay-vip-form-row"); // 左侧会员信息(Zibll zibpay_get_pay_vip_info_box)。 var info = node("div", "text-center pay-vip-info"); var iconbox = node("div", "v-iconbox mb10 flex jc gap10"); var vicon = node("div", "v-icon flex jc"); append(vicon, vipIcon(levelInfo)); append(iconbox, vicon); var vinfo = node("div", "v-info"); append(vinfo, node("div", "v-name", levelInfo.name || group.name || "VIP" + level)); append(vinfo, node("div", "v-desc em09", levelInfo.desc || "")); append(iconbox, vinfo); append(info, iconbox); if (levelInfo.equity) { var equity = document.createElement("ul"); equity.className = "v-equity"; equity.innerHTML = text(levelInfo.equity); append(info, equity); } var infoBa = node("div", "abs-center vip-baicon"); append(infoBa, vipIcon(levelInfo)); append(info, infoBa); append(row, info); // 右侧:套餐盒 → 积分兑换入口 → more → 支付方式/卡密 → 立即支付。 var products = node("div", "pay-vip-products"); renderProducts(products, group.items, wallet.mark); var points = catalog.points_exchange || {}; if (allowed.points_exchange !== false && points.enabled && Array.isArray(points.packages) && points.packages.length) { // 参考主题 zibpay_get_pay_uservip_modal 的积分兑换入口: // btn-block but mb10 padding-lg c-green mini-radius + points-color 图标 + // fa-angle-right;点击开服务端静态兑换弹窗(不再跳转用户中心)。 var pointsLink = node("a", "btn-block but mb10 padding-lg c-green mini-radius"); pointsLink.href = "javascript:;"; pointsLink.setAttribute("data-aksrt-vip-points-open", ""); pointsLink.innerHTML = '' + "积分兑换会员" + ''; append(products, pointsLink); } if (catalog.more) append(products, node("div", "muted-2-color mb10 em09 muted-box padding-10 mini-radius", catalog.more)); renderMethods(products, methods, cardPass, wallet); var actionName = actionKey(action); var actionAllowed = allowed[actionName] === true; var noMethod = methods.length === 0; var reason = actionReason(reasons[actionName]); var canPurchase = actionAllowed && !noMethod; // 按钮字样对齐参考主题:会员弹窗即 zibpay_get_initiate_pay_input(4) // 默认文案「立即支付」(开通/续费场景一致);无可用支付方式时渲染 // Zibll 同款 badg 提示,而非禁用按钮。 if (noMethod) { append(products, node("span", "badg px12 c-yellow-2", "暂时无法支付,请与客服联系")); } else { var submit = node("button", "mt6 but jb-red initiate-pay btn-block radius", canPurchase ? "立即支付" : (reason || "暂不可购买")); submit.type = "button"; submit.disabled = !canPurchase; submit.setAttribute("data-vip-submit", ""); append(products, submit); } append(row, products); append(form, row); append(pane, form); append(content, pane); }); append(modal, tabs); append(modal, content); if (catalog.help_text) append(modal, node("div", "muted-2-color em09 mb6", catalog.help_text)); // 卡密渠道初始显隐(选中 card_pass 时隐藏套餐、显示卡密输入盒)。 modal.querySelectorAll(".aksrt-vip-pane").forEach(function (pane) { applyVipMethodVisibility(pane); }); append(body, modal); } function selectedMethod(root) { var hidden = root.querySelector('input[name="payment_method"]'); if (hidden && hidden.value) return hidden.value; var first = root.querySelector('[data-for="payment_method"]'); return first ? first.getAttribute("data-value") : "balance"; } function selectedPackage(root) { var checked = root.querySelector('[data-aksrt-vip-package]:checked'); return checked ? parseInt(checked.value, 10) : 0; } var activePurchase = null; var activePurchaseToastId = ""; function restoreButton(button) { if (!button) return; button.disabled = false; button.classList.remove("is-loading"); } function purchaseFromPane(pane, button) { var packageId = selectedPackage(pane); if (!packageId) { notyf("请选择套餐", "danger"); return; } if (!button || button.disabled) return; var coordinator = window.AksrtVipPurchaseCoordinator; if (!coordinator || typeof coordinator.start !== "function") { notyf("会员购买暂不可用", "danger"); return; } var waitingPayment = false; button.disabled = true; button.classList.add("is-loading"); activePurchaseToastId = "aksrt-vip-purchase-toast"; notyf("正在创建会员订单…", "load", "", activePurchaseToastId); activePurchase = coordinator.start({ packageId: packageId, paymentMethod: selectedMethod(pane), tags: ["vip", "orders"], onPending: function (data) { waitingPayment = true; if (data.payment_url) window.open(data.payment_url, "_blank"); notyf(data.message || "请完成支付,支付成功后将自动刷新。", "info", 5, activePurchaseToastId); activePurchaseToastId = "aksrt-vip-payment-toast"; notyf("等待支付结果…", "load", "", activePurchaseToastId); }, onSuccess: function (result) { activePurchase = null; restoreButton(button); var toastId = waitingPayment ? "aksrt-vip-payment-toast" : "aksrt-vip-purchase-toast"; notyf((result.data && result.data.message) || "开通成功,正在刷新…", "success", 5, toastId); activePurchaseToastId = ""; window.setTimeout(function () { window.location.reload(); }, 800); }, onFailure: function (result) { activePurchase = null; restoreButton(button); notyf(result.data && result.data.message ? result.data.message : "支付未完成,请重试。", "danger", 5, "aksrt-vip-payment-toast"); activePurchaseToastId = ""; }, onTimeout: function () { activePurchase = null; restoreButton(button); notyf("支付状态暂未确认,请稍后在订单中心查看。", "danger", 5, "aksrt-vip-payment-toast"); activePurchaseToastId = ""; }, onError: function (response) { activePurchase = null; restoreButton(button); var message = response && response.json && response.json.message ? response.json.message : "开通失败"; if (response && response.status === 401) { message = "请先登录"; var login = document.querySelector(".signin-loader"); if (login) login.click(); } notyf(message, "danger", 5, activePurchaseToastId || "aksrt-vip-purchase-toast"); activePurchaseToastId = ""; }, }); } // 卡密兑换会员(type=vip):直兑,不创建支付订单。 function redeemVipCardPass(pane, button) { var pwEl = pane.querySelector('input[name="card_pass[password]"]'); var cardEl = pane.querySelector('input[name="card_pass[card]"]'); var password = pwEl ? String(pwEl.value || "").trim() : ""; if (!password) { notyf("请输入卡密", "danger"); if (pwEl) pwEl.focus(); return; } if (!button || button.disabled) return; var request = window.AksrtRequest; if (!request || typeof request.request !== "function") { notyf("会员兑换暂不可用", "danger"); return; } button.disabled = true; button.classList.add("is-loading"); notyf("正在兑换会员…", "load", "", "aksrt-vip-purchase-toast"); var key = typeof request.createIdempotencyKey === "function" ? request.createIdempotencyKey() : ""; request.request("/pay/card-pass/redeem", { method: "POST", headers: key ? { "Idempotency-Key": key } : {}, body: JSON.stringify({ type: "vip", card: cardEl ? String(cardEl.value || "").trim() : "", password: password, }), }).then(function (response) { button.disabled = false; button.classList.remove("is-loading"); if (!response.ok || (response.json && response.json.code && !response.json.success)) { notyf((response.json && response.json.message) || "兑换失败", "danger", 5, "aksrt-vip-purchase-toast"); return; } var data = response.data || (response.json && response.json.data) || {}; if (window.AksrtModalRuntime && typeof window.AksrtModalRuntime.invalidate === "function") { window.AksrtModalRuntime.invalidate(["vip", "orders"]); } notyf(data.message || "兑换成功,正在刷新…", "success", 5, "aksrt-vip-purchase-toast"); window.setTimeout(function () { window.location.reload(); }, 800); }).catch(function () { button.disabled = false; button.classList.remove("is-loading"); notyf("网络错误,请重试", "danger", 5, "aksrt-vip-purchase-toast"); }); } function bindModalUi(root) { if (!root || root.dataset.aksrtVipBound === "1") return; root.dataset.aksrtVipBound = "1"; root.addEventListener("click", function (event) { var methodItem = event.target.closest ? event.target.closest('[data-for="payment_method"]') : null; if (methodItem) { var pane = methodItem.closest(".aksrt-vip-pane") || root; pane.querySelectorAll('[data-for="payment_method"]').forEach(function (el) { el.classList.toggle("active", el === methodItem); }); var hidden = pane.querySelector('input[name="payment_method"]'); if (hidden) hidden.value = methodItem.getAttribute("data-value") || ""; applyVipMethodVisibility(pane); return; } var tab = event.target.closest("[data-vip-tab]"); if (tab) { event.preventDefault(); var id = tab.getAttribute("data-vip-tab"); root.querySelectorAll("[data-vip-tab]").forEach(function (item) { if (item.parentElement) item.parentElement.classList.toggle("active", item === tab); }); root.querySelectorAll(".aksrt-vip-pane").forEach(function (pane) { var active = pane.id === id; pane.classList.toggle("active", active); pane.classList.toggle("in", active); }); return; } var pointsLink = event.target.closest("[data-aksrt-vip-points-open]"); if (pointsLink) { event.preventDefault(); openPointsModal(pointsLink); return; } var submit = event.target.closest("[data-vip-submit]"); if (submit) { event.preventDefault(); purchaseFromPane(submit.closest(".aksrt-vip-pane") || root, submit); } }); } function vipPay(trigger) { var level = trigger ? parseInt(trigger.getAttribute("vip-level") || trigger.getAttribute("data-vip-level") || "1", 10) || 1 : 1; window.AksrtModalRuntime.openRemote({ url: "/pay/vip/modal", query: { vip_level: level }, className: "aksrt-vip-modal-shell", skeleton: '
加载中…
', telemetry: "vip", kind: "vip", responseType: "json", cacheTtl: 15000, cacheTags: ["vip"], renderData: function (data, session) { renderModalView(session.content, data); bindModalUi(session.content); }, onError: function (error) { var unauthorized = error && error.code === "unauthorized"; notyf(unauthorized ? "请先登录" : ((error && error.message) || "会员套餐加载失败,请重试"), "danger"); if (unauthorized) { window.AksrtModalRuntime.close("unauthorized"); var login = document.querySelector(".signin-loader"); if (login) login.click(); } }, }); } function onDocClick(event) { var trigger = event.target.closest(".pay-vip, a.pay-vip, .float-btn.pay-vip, [data-aksrt-pay-vip]"); if (!trigger) return; var href = (trigger.getAttribute("href") || "").trim(); if (href && href !== "#" && href.indexOf("javascript:") !== 0 && !trigger.classList.contains("pay-vip") && !trigger.hasAttribute("data-aksrt-pay-vip") && !trigger.hasAttribute("vip-level") && !trigger.hasAttribute("data-vip-level")) { return; } event.preventDefault(); event.stopPropagation(); vipPay(trigger); } document.addEventListener("aksrt:modal:close", function (event) { var detail = event && event.detail ? event.detail : {}; var options = detail.session && detail.session.options ? detail.session.options : {}; if (options.kind !== "vip" || !activePurchase) return; if (typeof activePurchase.abort === "function") activePurchase.abort(); activePurchase = null; if (activePurchaseToastId) { notyf("已取消会员购买", "warning", 3, activePurchaseToastId); activePurchaseToastId = ""; } }); function bindOnce() { if (window.__aksrtPayVipBound) return; window.__aksrtPayVipBound = true; document.addEventListener("click", onDocClick, true); bindPointsModal(); } jQuery(document).off("auto_fun.aksrt-pay-vip").on("auto_fun.aksrt-pay-vip", bindOnce); })();