/**
* AKSRT Order Center — v2.0
*
* 前台订单中心交互:
* - 支付 / 取消 / 售后:操作成功后局部刷新订单卡片,不再整页 reload
* - 倒计时
* - Toast 通知替代 window.alert
*
* @package AKSRT
*/
(function () {
"use strict";
var page = document.querySelector("[data-aksrt-order-center]");
if (!page || !window.aksrtData) {
return;
}
/* ── Toast helper ── */
function showToast(text, duration) {
duration = duration || 2500;
var container = document.getElementById("toast-container");
if (!container) {
container = document.createElement("div");
container.id = "toast-container";
container.style.cssText = "position:fixed;bottom:24px;right:24px;z-index:99999;display:flex;flex-direction:column-reverse;gap:10px;pointer-events:none;";
document.body.appendChild(container);
}
var toast = document.createElement("div");
toast.style.cssText = "pointer-events:auto;display:flex;align-items:center;gap:8px;padding:10px 20px;background:rgba(0,0,0,0.78);backdrop-filter:blur(12px);color:#fff;font-family:var(--font-ui);font-size:14px;font-weight:500;border-radius:100px;box-shadow:0 4px 20px rgba(0,0,0,0.2);animation:aksrtToastIn 0.35s cubic-bezier(0.22,1,0.36,1) forwards;white-space:nowrap;";
toast.textContent = text;
container.appendChild(toast);
setTimeout(function () {
toast.style.animation = "aksrtToastOut 0.4s ease forwards";
setTimeout(function () { if (toast.parentNode) toast.parentNode.removeChild(toast); }, 400);
}, duration);
}
// Inject toast keyframes if not present
if (!document.getElementById("aksrt-toast-keyframes")) {
var style = document.createElement("style");
style.id = "aksrt-toast-keyframes";
style.textContent = "@keyframes aksrtToastIn{0%{opacity:0;transform:translateY(16px) scale(0.92)}100%{opacity:1;transform:translateY(0) scale(1)}}@keyframes aksrtToastOut{0%{opacity:1;transform:translateY(0) scale(1)}100%{opacity:0;transform:translateY(8px) scale(0.95)}}";
document.head.appendChild(style);
}
/* ── REST helper ── */
function restRoot() {
return ((aksrtData.siteUrl || "").replace(/\/$/, "")) + "/wp-json/aksrt/v1";
}
function request(path, body, method) {
return fetch(restRoot() + path, {
method: method || "POST",
headers: {
"Content-Type": "application/json",
"X-WP-Nonce": aksrtData.restNonce
},
body: body === undefined ? undefined : JSON.stringify(body || {})
}).then(function (response) {
return response.json();
});
}
function cartUrl() {
return aksrtData.cartUrl || (aksrtData.routes && aksrtData.routes.cart) || "/";
}
/* ── 扫码支付弹层(微信 Native code_url 等)── */
function showPaymentQr(content, orderNumber) {
var existing = document.getElementById("aksrt-pay-qr-overlay");
if (existing) existing.remove();
var overlay = document.createElement("div");
overlay.id = "aksrt-pay-qr-overlay";
overlay.style.cssText = "position:fixed;inset:0;z-index:100000;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.5);";
var qrImg = "";
if (window.AksrtShare && typeof window.AksrtShare.buildQrDataUrl === "function") {
var dataUrl = window.AksrtShare.buildQrDataUrl(content, 220);
if (dataUrl) {
qrImg = '';
}
}
if (!qrImg) {
qrImg = '
' + String(content).replace(/[<>&]/g, "") + "
"; } var card = document.createElement("div"); card.style.cssText = "background:#fff;border-radius:12px;padding:24px;max-width:300px;text-align:center;box-shadow:0 10px 40px rgba(0,0,0,0.2);"; card.innerHTML = '支付完成后本页将自动更新
' + ''; overlay.appendChild(card); document.body.appendChild(overlay); function close() { overlay.remove(); } overlay.addEventListener("click", function (e) { if (e.target === overlay) close(); }); card.querySelector("#aksrt-pay-qr-close").addEventListener("click", function () { close(); // 关闭后查询订单是否已到账 if (orderNumber) { request("/shop/frontend/orders/" + orderNumber, {}).then(function () { window.location.reload(); }).catch(function () {}); } }); } /* ── 第三方支付返回提示(?payment=success|pending|cancelled)── */ (function paymentReturnNotice() { var params = new URLSearchParams(window.location.search); var pay = params.get("payment"); if (!pay) return; var map = { success: "支付成功!", pending: "支付处理中,到账后将自动更新。", cancelled: "支付已取消。", fail: "支付失败,请重试。" }; showToast(map[pay] || "支付状态:" + pay, 3500); })(); /* ── Local card refresh helpers ── */ function findOrderCard(orderNumber) { return page.querySelector('[data-aksrt-order-card="' + orderNumber + '"]'); } function updateCardStatus(card, newStatus, statusLabel) { if (!card) return; var badge = card.querySelector(".aksrt-orders-page__card-status, .aksrt-orders-page__item-badge"); if (badge) { badge.textContent = statusLabel || newStatus; } // Hide action buttons that are no longer relevant var actions = card.querySelectorAll("[data-aksrt-order-pay], [data-aksrt-order-cancel], [data-aksrt-order-after-sale], [data-aksrt-order-receipt], [data-aksrt-order-rebuy]"); for (var i = 0; i < actions.length; i++) { actions[i].style.display = "none"; } // Hide countdown if present var countdown = card.querySelector("[data-aksrt-order-countdown]"); if (countdown) { countdown.style.display = "none"; } } /* ── After-Sale Modal ── */ var afterSaleModal = page.querySelector("[data-aksrt-aftersale-modal]"); var afterSaleForm = page.querySelector("[data-aksrt-aftersale-form]"); var afterSaleOrderInput = afterSaleForm ? afterSaleForm.querySelector('[name="order_number"]') : null; function openAfterSaleModal(orderNumber) { if (!afterSaleModal || !afterSaleForm) { showToast("售后表单加载失败,请刷新页面后重试。"); return; } afterSaleForm.reset(); if (afterSaleOrderInput) afterSaleOrderInput.value = orderNumber; afterSaleModal.hidden = false; } function closeAfterSaleModal() { if (afterSaleModal) afterSaleModal.hidden = true; } if (afterSaleForm) { afterSaleForm.addEventListener("submit", function (event) { event.preventDefault(); var formData = new FormData(afterSaleForm); var orderNumber = formData.get("order_number"); var reason = (formData.get("reason") || "").trim(); if (!reason) { showToast("请填写售后原因。"); return; } var submitBtn = afterSaleForm.querySelector('button[type="submit"]'); if (submitBtn) { submitBtn.disabled = true; submitBtn.textContent = "提交中..."; } request("/shop/frontend/orders/" + orderNumber + "/after-sale", { type: formData.get("type") || "refund", reason: reason, note: (formData.get("note") || "").trim() }).then(function (result) { if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = "提交售后"; } if (!result.success) { showToast(result.message || "提交售后失败。"); return; } closeAfterSaleModal(); showToast("售后申请已提交。"); // Local refresh: update card status var card = findOrderCard(orderNumber); updateCardStatus(card, "refunded", "已退款"); }).catch(function () { if (submitBtn) { submitBtn.disabled = false; submitBtn.textContent = "提交售后"; } showToast("网络错误,请稍后重试。"); }); }); } /* ── Countdown timer ── */ function updateCountdowns() { var nodes = page.querySelectorAll("[data-aksrt-order-countdown]"); for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; var value = Number(node.getAttribute("data-aksrt-order-countdown") || 0); if (!value) continue; value -= 1; node.setAttribute("data-aksrt-order-countdown", String(value)); node.textContent = value > 0 ? "剩余支付时间 " + value + " 秒" : "待支付已超时,请重新发起。"; } } setInterval(updateCountdowns, 1000); /* ── Event delegation ── */ page.addEventListener("click", function (event) { // Timeline toggle var timelineToggle = event.target.closest("[data-aksrt-toggle-timeline]"); if (timelineToggle) { var timeline = timelineToggle.closest("[data-aksrt-timeline]"); var body = timeline ? timeline.querySelector(".aksrt-orders-page__timeline-body") : null; if (body) body.hidden = !body.hidden; return; } // Confirm receipt var receiptBtn = event.target.closest("[data-aksrt-order-receipt]"); if (receiptBtn) { var receiptOrder = receiptBtn.getAttribute("data-aksrt-order-receipt"); if (!receiptOrder) return; if (!window.confirm("确认已收到货物?")) return; receiptBtn.disabled = true; request("/shop/frontend/orders/" + receiptOrder + "/confirm-receipt", {}) .then(function (result) { receiptBtn.disabled = false; if (!result || !result.success) { showToast((result && result.message) || "确认收货失败"); return; } showToast("已确认收货"); updateCardStatus(findOrderCard(receiptOrder), "completed", "已完成"); }) .catch(function () { receiptBtn.disabled = false; showToast("网络错误"); }); return; } // Rebuy var rebuyBtn = event.target.closest("[data-aksrt-order-rebuy]"); if (rebuyBtn) { var rebuyOrder = rebuyBtn.getAttribute("data-aksrt-order-rebuy"); if (!rebuyOrder) return; rebuyBtn.disabled = true; request("/shop/frontend/orders/" + rebuyOrder + "/rebuy", {}) .then(function (result) { rebuyBtn.disabled = false; if (!result || !result.success) { showToast((result && result.message) || "再次购买失败"); return; } showToast("已加入购物车"); window.location.href = cartUrl(); }) .catch(function () { rebuyBtn.disabled = false; showToast("网络错误"); }); return; } // Review submit modal var reviewBtn = event.target.closest("[data-aksrt-order-review]"); if (reviewBtn) { var reviewOrder = reviewBtn.getAttribute("data-aksrt-order-review"); var card = reviewBtn.closest("[data-aksrt-order-card]"); var productId = 0; if (card) { var firstItem = card.querySelector("[data-product-id]"); if (firstItem) productId = Number(firstItem.getAttribute("data-product-id") || 0); } if (!productId) { // try parse from item title block dataset if present var any = card ? card.querySelector(".aksrt-orders-page__card-item") : null; if (any && any.getAttribute("data-product-id")) { productId = Number(any.getAttribute("data-product-id") || 0); } } if (!reviewOrder) return; var content = window.prompt("请输入评价内容(可选)", "好评!"); if (content === null) return; var rating = window.prompt("商品评分 1-5", "5"); var r = Math.max(1, Math.min(5, parseInt(rating || "5", 10) || 5)); reviewBtn.disabled = true; request("/shop/frontend/orders/" + reviewOrder + "/review", { product_id: productId, content: content || "好评!", rating_product: r, rating_service: r, rating_shipping: r }).then(function (result) { reviewBtn.disabled = false; if (!result || !result.success) { showToast((result && result.message) || "评价失败"); return; } showToast(result.message || "评价已提交"); updateCardStatus(findOrderCard(reviewOrder), "completed", "已完成"); }).catch(function () { reviewBtn.disabled = false; showToast("网络错误"); }); return; } // Pay var payButton = event.target.closest("[data-aksrt-order-pay]"); if (payButton) { var payOrderNumber = payButton.getAttribute("data-aksrt-order-pay"); // 支付方式取订单创建时选定的方式(按钮 data 属性可覆盖); // 留空则由服务端使用订单存储的 payment_method。 var payMethod = payButton.getAttribute("data-aksrt-order-method") || ""; payButton.disabled = true; payButton.textContent = "处理中..."; request("/shop/frontend/orders/" + payOrderNumber + "/pay", payMethod ? { payment_method: payMethod } : {}) .then(function (result) { if (!result.success) { payButton.disabled = false; payButton.textContent = "立即支付"; showToast(result.message || "支付失败。"); return; } var data = result.data || {}; // 跳转/扫码型网关:到第三方支付页或展示二维码,订单仍为待支付, // 由回调确认到账。 if (data.redirect) { if (data.payment_url && /^https?:\/\//i.test(data.payment_url)) { window.location.href = data.payment_url; return; } if (data.qr_content || data.payment_url) { showPaymentQr(data.qr_content || data.payment_url, payOrderNumber); payButton.disabled = false; payButton.textContent = "已下单,待支付"; return; } } // 同步型网关(站内余额):已到账。 showToast("支付成功!"); var card = findOrderCard(payOrderNumber); updateCardStatus(card, "paid", "已支付"); }) .catch(function () { payButton.disabled = false; payButton.textContent = "立即支付"; showToast("网络错误,请稍后重试。"); }); return; } // Cancel var cancelButton = event.target.closest("[data-aksrt-order-cancel]"); if (cancelButton) { var cancelOrderNumber = cancelButton.getAttribute("data-aksrt-order-cancel"); cancelButton.disabled = true; cancelButton.textContent = "取消中..."; request("/shop/frontend/orders/" + cancelOrderNumber + "/cancel") .then(function (result) { if (!result.success) { cancelButton.disabled = false; cancelButton.textContent = "取消订单"; showToast(result.message || "取消失败。"); return; } showToast("订单已取消。"); var card = findOrderCard(cancelOrderNumber); updateCardStatus(card, "cancelled", "已取消"); }) .catch(function () { cancelButton.disabled = false; cancelButton.textContent = "取消订单"; showToast("网络错误,请稍后重试。"); }); return; } // After-Sale var afterSaleButton = event.target.closest("[data-aksrt-order-after-sale]"); if (afterSaleButton) { var afterSaleOrderNumber = afterSaleButton.getAttribute("data-aksrt-order-after-sale"); openAfterSaleModal(afterSaleOrderNumber); return; } // Close modal if (event.target.closest("[data-aksrt-aftersale-modal-close]") || (event.target.classList && event.target.classList.contains("aksrt-modal__overlay"))) { closeAfterSaleModal(); } }); })();