/**
* Knowledge-payment order center interactions.
*
* @package AKSRT
*/
(function () {
"use strict";
var instances = new WeakMap();
function request(path, body, method) {
var options = { method: method || "POST" };
if (body !== undefined) options.body = JSON.stringify(body || {});
return window.AksrtRequest.request(path, options);
}
function orderPath(orderNumber, suffix) {
return "/orders/" + encodeURIComponent(orderNumber || "") + (suffix || "");
}
function errorMessage(error, fallback) {
if (error && error.message) return String(error.message);
return fallback || "请求失败";
}
function escapeHtml(value) {
return String(value == null ? "" : value)
.replace(/&/g, "&").replace(//g, ">").replace(/\"/g, """)
.replace(/'/g, "'");
}
function formatMoney(order) {
var amount = Number(order && order.amount || 0);
return order && order.is_points
? escapeHtml(order.currency_symbol || "积分") + " " + Math.round(amount)
: "¥" + amount.toFixed(2);
}
function orderTag(orderNumber) {
return "order:" + String(orderNumber || "").toLowerCase();
}
function invalidateOrder(orderNumber, order) {
var tags = order && Array.isArray(order.invalidation_tags) ? order.invalidation_tags : [
"orders",
orderTag(orderNumber),
];
window.AksrtModalRuntime.invalidate(tags);
}
function activeDetail(state, number) {
return state.detailOrderNumber === number
&& !!state.detailSession
&& !state.detailSession.closed
&& state.detailSession.options
&& state.detailSession.options.kind === "orders"
&& window.AksrtModalRuntime.getActive() === state.detailSession.shell;
}
function detailSkeleton() {
return '
' +
'' +
'' +
'' +
'
';
}
function renderDetail(state, order, session) {
var allowedActions = order.allowed_actions || {};
var reconciliation = order.reconciliation || {};
var image = order.image || "";
var title = order.product_name || "订单";
var status = order.status_group || "closed";
var html = '
';
html += '' + escapeHtml(order.status_label || "") + "";
html += '' + formatMoney(order) + "
" +
'";
}
function renderStats(state, stats) {
var root = state.root.querySelector("[data-aksrt-order-stats]");
if (!root) return;
root.innerHTML = '
全部' + Number(stats.total || 0) + "
" +
'
待支付' + Number(stats.pending || 0) + "
" +
'
已生效' + Number(stats.completed || 0) + "
";
}
function renderPagination(state, view) {
var existing = state.root.querySelector(".aksrt-orders-page__pagination");
if (existing) existing.remove();
if (Number(view.total_pages || 1) <= 1) return;
var root = document.createElement("nav");
root.className = "aksrt-orders-page__pagination";
root.setAttribute("aria-label", "订单分页");
var base = new URL(window.location.href);
for (var i = 1; i <= Number(view.total_pages); i++) {
base.searchParams.set("order_page", String(i));
var link = document.createElement("a");
link.className = "aksrt-orders-page__page-chip" + (i === Number(view.page) ? " is-active" : "");
link.href = base.toString();
link.textContent = String(i);
root.appendChild(link);
}
var list = state.root.querySelector("[data-aksrt-order-list]");
if (list) list.after(root);
}
function updateCountdowns(state) {
state.root.querySelectorAll("[data-aksrt-order-countdown]").forEach(function (node) {
var value = Math.max(0, Number(node.getAttribute("data-aksrt-order-countdown") || 0) - 1);
node.setAttribute("data-aksrt-order-countdown", String(value));
node.textContent = value ? "剩余支付时间 " + value + " 秒" : "订单即将关闭";
});
}
function renderView(state, view) {
renderStats(state, view.stats || {});
var list = state.root.querySelector("[data-aksrt-order-list]");
if (!list) return;
var items = Array.isArray(view.items) ? view.items : [];
if (!items.length) {
list.innerHTML = '
没有匹配的订单
换个条件试试,或清除当前筛选。
';
list.classList.add("is-empty");
} else {
list.classList.remove("is-empty");
list.innerHTML = items.map(cardHtml).join("");
}
renderPagination(state, view);
updateCountdowns(state);
}
function refreshView(state) {
return request(currentViewPath(), undefined, "GET").then(function (result) {
if (!result || !result.data) throw new Error("刷新失败");
renderView(state, result.data);
return result.data;
}).catch(function (error) {
notyf(errorMessage(error, "订单状态已变更,请刷新后查看"), "danger");
return null;
});
}
function startPayment(state, button) {
var number = button.getAttribute("data-aksrt-order-pay") || "";
var method = button.getAttribute("data-aksrt-order-method") || "";
if (!number || button.disabled) return;
button.disabled = true;
request(orderPath(number, "/pay"), method ? { payment_method: method } : {}, "POST").then(function (result) {
var data = result.data || {};
invalidateOrder(number, data.order);
if (data.redirect && data.payment_url) {
window.location.assign(data.payment_url);
return;
}
notyf(data.message || "支付成功", "success");
refreshView(state);
if (activeDetail(state, number)) openDetail(state, number);
}).catch(function (error) {
button.disabled = false;
notyf(errorMessage(error, "网络错误,请稍后重试"), "danger");
});
}
function closeOrder(state, button) {
var number = button.getAttribute("data-aksrt-order-cancel") || "";
if (!number || button.disabled) return;
if (button.getAttribute("data-aksrt-confirm") !== "true") {
button.setAttribute("data-aksrt-confirm", "true");
button.textContent = "确认关闭";
return;
}
button.disabled = true;
request(orderPath(number, "/cancel"), {}, "POST").then(function (result) {
var data = result.data || {};
invalidateOrder(number, data.order);
notyf("订单已关闭", "success");
refreshView(state);
if (activeDetail(state, number)) openDetail(state, number);
}).catch(function (error) {
button.disabled = false;
button.removeAttribute("data-aksrt-confirm");
button.textContent = "关闭订单";
notyf(errorMessage(error, "网络错误,请稍后重试"), "danger");
});
}
function closest(target, selector) {
return target && target.closest ? target.closest(selector) : null;
}
function initRoot(root) {
if (instances.has(root) || !window.AksrtModalRuntime.isRolloutEnabled("order")) return;
var state = {
root: root,
detailOrderNumber: "",
detailSession: null,
detailReplacement: false,
detailReplacementSession: null,
countdownTimer: null,
};
state.onRootClick = function (event) {
var filterToggle = closest(event.target, "[data-aksrt-orders-filter-toggle]");
if (filterToggle && root.contains(filterToggle)) {
var panel = root.querySelector("[data-aksrt-orders-filter-panel]");
var expanded = filterToggle.getAttribute("aria-expanded") === "true";
filterToggle.setAttribute("aria-expanded", String(!expanded));
if (panel) panel.hidden = expanded;
return;
}
var detail = closest(event.target, "[data-aksrt-order-detail]");
if (detail && root.contains(detail)) { openDetail(state, detail.getAttribute("data-aksrt-order-detail")); return; }
var pay = closest(event.target, "[data-aksrt-order-pay]");
if (pay && root.contains(pay)) { event.preventDefault(); startPayment(state, pay); return; }
var cancel = closest(event.target, "[data-aksrt-order-cancel]");
if (cancel && root.contains(cancel)) { event.preventDefault(); closeOrder(state, cancel); }
};
state.onModalClose = function (event) {
var detail = event && event.detail ? event.detail : {};
if (!state.detailSession || detail.session !== state.detailSession) return;
if (detail.reason === "replace" && state.detailReplacement && detail.session === state.detailReplacementSession) return;
state.detailSession = null;
state.detailOrderNumber = "";
state.detailReplacement = false;
state.detailReplacementSession = null;
};
state.onDocumentClick = function (event) {
if (!state.detailSession || window.AksrtModalRuntime.getActive() !== state.detailSession.shell) return;
var refresh = closest(event.target, "[data-aksrt-order-refresh]");
if (refresh) {
event.preventDefault();
refreshDetail(state, refresh.getAttribute("data-aksrt-order-refresh") || "");
return;
}
var pay = closest(event.target, "[data-aksrt-order-pay]");
if (pay && !root.contains(pay)) {
event.preventDefault();
startPayment(state, pay);
return;
}
var cancel = closest(event.target, "[data-aksrt-order-cancel]");
if (cancel && !root.contains(cancel)) {
event.preventDefault();
closeOrder(state, cancel);
}
};
root.addEventListener("click", state.onRootClick);
document.addEventListener("aksrt:modal:close", state.onModalClose);
document.addEventListener("click", state.onDocumentClick);
state.countdownTimer = window.setInterval(function () { updateCountdowns(state); }, 1000);
instances.set(root, state);
}
function rootsIn(root) {
if (!root) return [];
var roots = [];
if (root.matches && root.matches("[data-aksrt-order-center]")) roots.push(root);
if (root.querySelectorAll) root.querySelectorAll("[data-aksrt-order-center]").forEach(function (item) { roots.push(item); });
return roots;
}
function init(root) {
rootsIn(root || document).forEach(initRoot);
}
function destroy(root) {
rootsIn(root).forEach(function (item) {
var state = instances.get(item);
if (!state) return;
if (activeDetail(state, state.detailOrderNumber)) window.AksrtModalRuntime.close("replace");
item.removeEventListener("click", state.onRootClick);
document.removeEventListener("aksrt:modal:close", state.onModalClose);
document.removeEventListener("click", state.onDocumentClick);
window.clearInterval(state.countdownTimer);
instances.delete(item);
});
}
window.AKSRTOrderCenter = { init: init, destroy: destroy };
if (window.AksrtFrontend && typeof window.AksrtFrontend.register === "function") {
window.AksrtFrontend.register("aksrt-order-center", init);
}
init(document);
}());