feat(shop): wire storefront buy path to server cart
Connect product options/add-cart, server cart checkout payloads, favorite/rebuy/receipt REST, and order-center actions without localStorage dual-read or hardcoded cart/orders URL hacks.
This commit is contained in:
1 parent
2ed3ffe317
commit
50e3db85bb
6 files changed
+621
-304
No files matched your search
+89
-62
@@ -6,7 +6,28 @@
|
||||
return;
|
||||
}
|
||||
|
||||
var CART_KEY = "aksrt_cart";
|
||||
function restBase() {
|
||||
return ((aksrtData.siteUrl || "").replace(/\/$/, "")) + "/wp-json/aksrt/v1";
|
||||
}
|
||||
function rest(path, method, body) {
|
||||
var opts = {
|
||||
method: method || "GET",
|
||||
credentials: "same-origin",
|
||||
headers: { "X-WP-Nonce": aksrtData.restNonce || "" }
|
||||
};
|
||||
if (body !== undefined) {
|
||||
opts.headers["Content-Type"] = "application/json";
|
||||
opts.body = JSON.stringify(body);
|
||||
}
|
||||
return fetch(restBase() + path, opts).then(function (r) { return r.json(); });
|
||||
}
|
||||
function ordersUrl() {
|
||||
return aksrtData.ordersUrl || (aksrtData.routes && aksrtData.routes.orders) || "/";
|
||||
}
|
||||
function shopHomeUrl() {
|
||||
return (aksrtData.routes && aksrtData.routes.home) || aksrtData.siteUrl || "/";
|
||||
}
|
||||
var cartItems = [];
|
||||
var currencySymbol = page.getAttribute("data-currency-symbol") || "¥";
|
||||
var itemsEl = page.querySelector("[data-aksrt-cart-items]");
|
||||
var subtotalEl = page.querySelector("[data-aksrt-summary-subtotal]");
|
||||
@@ -20,18 +41,8 @@
|
||||
var previewState = null;
|
||||
var searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
function getCart() {
|
||||
try {
|
||||
var parsed = JSON.parse(localStorage.getItem(CART_KEY) || "[]");
|
||||
return Array.isArray(parsed) ? parsed : [];
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function setCart(items) {
|
||||
localStorage.setItem(CART_KEY, JSON.stringify(items));
|
||||
}
|
||||
function getCart() { return cartItems; }
|
||||
function setCart(items) { cartItems = Array.isArray(items) ? items : []; }
|
||||
|
||||
function money(value) {
|
||||
return currencySymbol + Number(value || 0).toFixed(2);
|
||||
@@ -46,7 +57,8 @@
|
||||
var items = getCart().map(function (item) {
|
||||
return {
|
||||
product_id: Number(item.product_id || item.id || 0),
|
||||
quantity: Number(item.qty || item.quantity || 1)
|
||||
quantity: Number(item.qty || item.quantity || 1),
|
||||
options_string: item.options_string || ""
|
||||
};
|
||||
}).filter(function (item) {
|
||||
return item.product_id > 0;
|
||||
@@ -69,7 +81,7 @@
|
||||
'<div class="aksrt-cart-page__empty">' +
|
||||
'<i class="fas fa-shopping-cart" aria-hidden="true"></i>' +
|
||||
"<p>购物车为空,去商品页添加想购买的内容。</p>" +
|
||||
'<a href="/" class="btn-outline btn-sm">继续浏览</a>' +
|
||||
'<a href="' + shopHomeUrl() + '" class="btn-outline btn-sm">继续浏览</a>' +
|
||||
"</div>";
|
||||
subtotalEl.textContent = money(0);
|
||||
shippingEl.textContent = money(0);
|
||||
@@ -84,15 +96,19 @@
|
||||
var html = "";
|
||||
items.forEach(function (item, index) {
|
||||
var qty = Number(item.qty || item.quantity || 1);
|
||||
var price = Number(item.price || 0);
|
||||
var lineTotal = qty * price;
|
||||
var price = Number(item.unit_price != null ? item.unit_price : (item.price != null ? item.price : (item.product && item.product.price) || 0));
|
||||
var lineTotal = Number(item.line_total != null ? item.line_total : qty * price);
|
||||
total += lineTotal;
|
||||
var title = item.title || (item.product && item.product.title) || "商品";
|
||||
var image = item.image || (item.product && item.product.image) || "";
|
||||
var opts = item.options_label || item.options_string || "";
|
||||
|
||||
html += '' +
|
||||
'<article class="aksrt-cart-page__item" data-cart-index="' + index + '">' +
|
||||
(item.image ? '<img class="aksrt-cart-page__item-image" src="' + item.image + '" alt="">' : '<div class="aksrt-cart-page__item-image aksrt-cart-page__item-image--placeholder"><i class="fas fa-box"></i></div>') +
|
||||
'<article class="aksrt-cart-page__item" data-cart-index="' + index + '" data-product-id="' + Number(item.product_id || item.id || 0) + '" data-options-string="' + String(item.options_string || "").replace(/"/g, """) + '">' +
|
||||
(image ? '<img class="aksrt-cart-page__item-image" src="' + image + '" alt="">' : '<div class="aksrt-cart-page__item-image aksrt-cart-page__item-image--placeholder"><i class="fas fa-box"></i></div>') +
|
||||
'<div class="aksrt-cart-page__item-main">' +
|
||||
'<h3>' + (item.title || "商品") + "</h3>" +
|
||||
'<h3>' + title + "</h3>" +
|
||||
(opts ? "<small>" + opts + "</small>" : "") +
|
||||
'<p>' + money(price) + "</p>" +
|
||||
"</div>" +
|
||||
'<div class="aksrt-cart-page__item-qty">' +
|
||||
@@ -124,18 +140,7 @@
|
||||
createBtn.disabled = !data;
|
||||
}
|
||||
|
||||
function request(path, body) {
|
||||
return fetch("/wp-json/aksrt/v1" + path, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-WP-Nonce": aksrtData.restNonce
|
||||
},
|
||||
body: JSON.stringify(body || {})
|
||||
}).then(function (response) {
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
function request(path, body) { return rest(path, "POST", body || {}); }
|
||||
|
||||
function previewCheckout() {
|
||||
var payload = getPayload();
|
||||
@@ -183,12 +188,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
localStorage.removeItem(CART_KEY);
|
||||
var orderNumber = (result.data && result.data.order_number) || "";
|
||||
var ordersUrl = window.location.pathname.replace("cart", "orders") + "?order_status=pending";
|
||||
var nextOrdersUrl = ordersUrl() + (String(ordersUrl()).indexOf("?") >= 0 ? "&" : "?") + "order_status=pending";
|
||||
|
||||
if (!orderNumber) {
|
||||
window.location.href = ordersUrl;
|
||||
window.location.href = nextOrdersUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,10 +205,10 @@
|
||||
return;
|
||||
}
|
||||
// 二维码 / 余额 / 失败:统一回订单中心处理(含 ?payment 提示)。
|
||||
window.location.href = ordersUrl;
|
||||
window.location.href = nextOrdersUrl;
|
||||
})
|
||||
.catch(function () {
|
||||
window.location.href = ordersUrl;
|
||||
window.location.href = nextOrdersUrl;
|
||||
});
|
||||
})
|
||||
.catch(function () {
|
||||
@@ -217,31 +221,36 @@
|
||||
var actionButton = event.target.closest("[data-qty-action]");
|
||||
if (actionButton) {
|
||||
var itemEl = actionButton.closest("[data-cart-index]");
|
||||
var index = Number(itemEl.getAttribute("data-cart-index"));
|
||||
var items = getCart();
|
||||
if (!items[index]) {
|
||||
if (!itemEl) return;
|
||||
var productId = Number(itemEl.getAttribute("data-product-id") || 0);
|
||||
var optionsString = itemEl.getAttribute("data-options-string") || "";
|
||||
var action = actionButton.getAttribute("data-qty-action");
|
||||
var path = "/shop/frontend/cart/add";
|
||||
var body = { product_id: productId, options_string: optionsString, count: 1 };
|
||||
if (action === "dec") {
|
||||
path = "/shop/frontend/cart/reduce";
|
||||
} else if (action === "remove") {
|
||||
path = "/shop/frontend/cart/remove";
|
||||
body = { product_id: productId, options_string: optionsString };
|
||||
} else if (action !== "inc") {
|
||||
return;
|
||||
}
|
||||
|
||||
var action = actionButton.getAttribute("data-qty-action");
|
||||
if (action === "inc") {
|
||||
items[index].qty = Number(items[index].qty || 1) + 1;
|
||||
} else if (action === "dec") {
|
||||
items[index].qty = Math.max(1, Number(items[index].qty || 1) - 1);
|
||||
} else if (action === "remove") {
|
||||
items.splice(index, 1);
|
||||
}
|
||||
|
||||
setCart(items);
|
||||
setSummary(null);
|
||||
renderCart();
|
||||
rest(path, "POST", body).then(function (result) {
|
||||
if (!result || !result.success) {
|
||||
window.alert((result && result.message) || "操作失败");
|
||||
return;
|
||||
}
|
||||
setSummary(null);
|
||||
loadServerCart();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.target.closest("[data-aksrt-clear-cart]")) {
|
||||
localStorage.removeItem(CART_KEY);
|
||||
setSummary(null);
|
||||
renderCart();
|
||||
rest("/shop/frontend/cart/empty", "POST", {}).then(function () {
|
||||
setSummary(null);
|
||||
loadServerCart();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,10 +266,28 @@
|
||||
|
||||
var resumeButton = event.target.closest("[data-aksrt-resume-order]");
|
||||
if (resumeButton) {
|
||||
window.location.href = window.location.pathname.replace("cart", "orders") + "?order_status=pending";
|
||||
window.location.href = ordersUrl() + (String(ordersUrl()).indexOf("?") >= 0 ? "&" : "?") + "order_status=pending";
|
||||
}
|
||||
});
|
||||
|
||||
function loadServerCart() {
|
||||
return rest("/shop/frontend/cart", "GET").then(function (result) {
|
||||
var items = (result && result.success && result.data && result.data.items) ? result.data.items : [];
|
||||
items = items.map(function (it) {
|
||||
it.qty = it.quantity || it.qty || 1;
|
||||
it.price = it.unit_price != null ? it.unit_price : (it.product && it.product.price) || 0;
|
||||
it.title = it.title || (it.product && it.product.title) || "商品";
|
||||
it.image = it.image || (it.product && it.product.image) || "";
|
||||
return it;
|
||||
});
|
||||
setCart(items);
|
||||
renderCart();
|
||||
}).catch(function () {
|
||||
setCart([]);
|
||||
renderCart();
|
||||
});
|
||||
}
|
||||
|
||||
var couponInput = page.querySelector("[data-aksrt-coupon-code]");
|
||||
if (couponInput && searchParams.has("coupon")) {
|
||||
couponInput.value = searchParams.get("coupon") || "";
|
||||
@@ -300,7 +327,7 @@
|
||||
}
|
||||
|
||||
function refreshAddressList() {
|
||||
fetch("/wp-json/aksrt/v1/shop/frontend/address", {
|
||||
fetch(restBase() + "/shop/frontend/address", {
|
||||
headers: { "X-WP-Nonce": aksrtData.restNonce }
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
@@ -389,9 +416,9 @@
|
||||
if (deleteBtn) {
|
||||
var deleteId = deleteBtn.getAttribute("data-aksrt-address-delete");
|
||||
if (!confirm("确定删除该地址吗?")) return;
|
||||
request("/shop/frontend/address/" + deleteId, {}).then(function (result) {
|
||||
if (!result.success) {
|
||||
alert(result.message || "删除失败。");
|
||||
rest("/shop/frontend/address/" + deleteId, "DELETE").then(function (result) {
|
||||
if (!result || !result.success) {
|
||||
alert((result && result.message) || "删除失败。");
|
||||
return;
|
||||
}
|
||||
refreshAddressList();
|
||||
@@ -452,5 +479,5 @@
|
||||
});
|
||||
}
|
||||
|
||||
renderCart();
|
||||
loadServerCart();
|
||||
})();
|
||||
Reference in new issue
Block a user