feat(shop): complete storefront archive, seller edit, revenue
Wire product cat/tag archives to settings-driven sort and AJAX paging, seller product options/video/params editing, revenue withdraw form and order review submit — finishing remaining shop frontend gaps after buy-path.
This commit is contained in:
1 parent
5a8f08db8a
commit
f3db6c89cc
17 files changed
+1024
-248
No files matched your search
+140
-32
@@ -1,44 +1,152 @@
|
||||
/**
|
||||
* AKSRT Product Archive — 商品归档页交互
|
||||
*
|
||||
* 处理商品分类/标签归档页的筛选、排序和加载更多。
|
||||
* Product archive — sort + AJAX load more.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var grid = document.getElementById('aksrt-product-grid');
|
||||
if (!grid) return;
|
||||
var root = document.querySelector("[data-aksrt-product-archive]");
|
||||
if (!root) return;
|
||||
|
||||
// 商品卡片懒加载图片观察器
|
||||
if ('IntersectionObserver' in window) {
|
||||
var imgObserver = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (entry.isIntersecting) {
|
||||
var img = entry.target;
|
||||
if (img.dataset.src) {
|
||||
img.src = img.dataset.src;
|
||||
img.removeAttribute('data-src');
|
||||
}
|
||||
imgObserver.unobserve(img);
|
||||
}
|
||||
});
|
||||
}, { rootMargin: '200px' });
|
||||
function restBase() {
|
||||
var site = (window.aksrtData && aksrtData.siteUrl) ? String(aksrtData.siteUrl).replace(/\/$/, "") : "";
|
||||
return site + "/wp-json/aksrt/v1";
|
||||
}
|
||||
|
||||
grid.querySelectorAll('img[data-src]').forEach(function (img) {
|
||||
imgObserver.observe(img);
|
||||
});
|
||||
function toast(msg) {
|
||||
if (typeof window.aksrtToast === "function") {
|
||||
window.aksrtToast(msg);
|
||||
return;
|
||||
}
|
||||
if (window.console) console.log(msg);
|
||||
}
|
||||
|
||||
var grid = root.querySelector("[data-aksrt-product-grid], #aksrt-product-grid");
|
||||
var countEl = root.querySelector("[data-aksrt-archive-count]");
|
||||
var loadMoreBtn = root.querySelector("[data-aksrt-shop-load-more]");
|
||||
var state = {
|
||||
taxonomy: root.getAttribute("data-taxonomy") || "",
|
||||
termId: Number(root.getAttribute("data-term-id") || 0),
|
||||
orderby: root.getAttribute("data-orderby") || "date",
|
||||
page: Number(root.getAttribute("data-page") || 1),
|
||||
maxPages: Number(root.getAttribute("data-max-pages") || 1),
|
||||
paging: root.getAttribute("data-paging") || "number",
|
||||
ias: root.getAttribute("data-ias") === "1",
|
||||
iasMax: Number(root.getAttribute("data-ias-max") || 5),
|
||||
loading: false,
|
||||
autoLoads: 0,
|
||||
};
|
||||
|
||||
function fetchArchive(page, orderby, replace) {
|
||||
if (state.loading) return Promise.resolve();
|
||||
state.loading = true;
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.disabled = true;
|
||||
loadMoreBtn.textContent = "加载中...";
|
||||
}
|
||||
|
||||
// 商品卡片 hover 效果增强
|
||||
grid.querySelectorAll('.aksrt-product-card').forEach(function (card) {
|
||||
card.addEventListener('mouseenter', function () {
|
||||
this.classList.add('aksrt-product-card--hover');
|
||||
var qs = new URLSearchParams();
|
||||
qs.set("taxonomy", state.taxonomy);
|
||||
qs.set("term_id", String(state.termId));
|
||||
qs.set("page", String(page));
|
||||
qs.set("orderby", orderby || state.orderby);
|
||||
|
||||
return fetch(restBase() + "/shop/frontend/products/archive?" + qs.toString(), {
|
||||
method: "GET",
|
||||
credentials: "same-origin",
|
||||
headers: {
|
||||
"X-WP-Nonce": (window.aksrtData && aksrtData.restNonce) || "",
|
||||
},
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (result) {
|
||||
state.loading = false;
|
||||
if (!result || !result.success || !result.data) {
|
||||
toast((result && result.message) || "加载失败");
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.disabled = false;
|
||||
loadMoreBtn.textContent = "加载更多";
|
||||
}
|
||||
return;
|
||||
}
|
||||
var data = result.data;
|
||||
state.page = Number(data.page || page);
|
||||
state.maxPages = Number(data.max_pages || 1);
|
||||
state.orderby = data.orderby || state.orderby;
|
||||
root.setAttribute("data-page", String(state.page));
|
||||
root.setAttribute("data-max-pages", String(state.maxPages));
|
||||
root.setAttribute("data-orderby", state.orderby);
|
||||
|
||||
if (countEl && typeof data.total !== "undefined") {
|
||||
countEl.textContent = "共 " + data.total + " 件商品";
|
||||
}
|
||||
|
||||
if (grid) {
|
||||
if (replace) {
|
||||
grid.innerHTML = data.html || "";
|
||||
} else if (data.html) {
|
||||
grid.insertAdjacentHTML("beforeend", data.html);
|
||||
}
|
||||
}
|
||||
|
||||
root.querySelectorAll("[data-aksrt-shop-orderby]").forEach(function (a) {
|
||||
a.classList.toggle("is-active", a.getAttribute("data-aksrt-shop-orderby") === state.orderby);
|
||||
});
|
||||
card.addEventListener('mouseleave', function () {
|
||||
this.classList.remove('aksrt-product-card--hover');
|
||||
});
|
||||
});
|
||||
|
||||
if (loadMoreBtn) {
|
||||
var hasMore = state.page < state.maxPages;
|
||||
loadMoreBtn.style.display = hasMore ? "" : "none";
|
||||
loadMoreBtn.disabled = false;
|
||||
loadMoreBtn.textContent = "加载更多";
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
state.loading = false;
|
||||
if (loadMoreBtn) {
|
||||
loadMoreBtn.disabled = false;
|
||||
loadMoreBtn.textContent = "加载更多";
|
||||
}
|
||||
toast("网络错误");
|
||||
});
|
||||
}
|
||||
|
||||
root.addEventListener("click", function (e) {
|
||||
var sort = e.target.closest("[data-aksrt-shop-orderby]");
|
||||
if (sort && root.contains(sort)) {
|
||||
e.preventDefault();
|
||||
var orderby = sort.getAttribute("data-aksrt-shop-orderby") || "date";
|
||||
if (orderby === state.orderby && state.paging === "ajax") return;
|
||||
state.orderby = orderby;
|
||||
state.autoLoads = 0;
|
||||
try {
|
||||
var u = new URL(window.location.href);
|
||||
u.searchParams.set("shop_orderby", orderby);
|
||||
u.searchParams.delete("paged");
|
||||
window.history.replaceState({}, "", u.toString());
|
||||
} catch (err) {}
|
||||
fetchArchive(1, orderby, true);
|
||||
return;
|
||||
}
|
||||
|
||||
var more = e.target.closest("[data-aksrt-shop-load-more]");
|
||||
if (more && root.contains(more)) {
|
||||
e.preventDefault();
|
||||
if (state.page >= state.maxPages) return;
|
||||
fetchArchive(state.page + 1, state.orderby, false);
|
||||
}
|
||||
});
|
||||
|
||||
if (state.paging === "ajax" && state.ias && "IntersectionObserver" in window && loadMoreBtn) {
|
||||
var io = new IntersectionObserver(function (entries) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) return;
|
||||
if (state.loading || state.page >= state.maxPages) return;
|
||||
if (state.iasMax > 0 && state.autoLoads >= state.iasMax) return;
|
||||
state.autoLoads += 1;
|
||||
fetchArchive(state.page + 1, state.orderby, false);
|
||||
});
|
||||
}, { rootMargin: "240px" });
|
||||
io.observe(loadMoreBtn);
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user