feat(ux): after-sale multi-step, ban appeal, message types, coupon wallet
Orders center gains after-sale tickets (return ship/cancel/timeline), coupon wallet list, ban-appeal page, and expanded message center tabs.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Ban appeal page styles.
|
||||
* @package AKSRT
|
||||
*/
|
||||
.aksrt-ban-appeal .form-control {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid var(--main-border-color, #ddd);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.aksrt-ban-appeal .mb15 { margin-bottom: 15px; }
|
||||
.aksrt-ban-appeal .but.c-blue {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
background: var(--focus-color, #2f6df6);
|
||||
color: #fff;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
padding: 10px 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.aksrt-ban-appeal .c-red { color: #e74c3c; }
|
||||
.aksrt-ban-appeal .muted-box {
|
||||
background: var(--surface-2, #f5f6f7);
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
@@ -92,3 +92,89 @@
|
||||
.aksrt-orders-page__tabs {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
|
||||
/* After-sale multi-step + coupon wallet */
|
||||
.aksrt-orders-page__extra-nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 0 0 12px;
|
||||
}
|
||||
.aksrt-orders-page__extra-link {
|
||||
padding: 6px 12px;
|
||||
border-radius: 999px;
|
||||
background: var(--surface-2, #f3f4f6);
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: 13px;
|
||||
}
|
||||
.aksrt-orders-page__extra-link.is-active {
|
||||
background: var(--focus-color, var(--color-primary));
|
||||
color: #fff;
|
||||
}
|
||||
.aksrt-as-list { display: grid; gap: 12px; }
|
||||
.aksrt-as-card {
|
||||
border: 1px solid var(--main-border-color, #eee);
|
||||
border-radius: 10px;
|
||||
padding: 14px;
|
||||
background: var(--main-bg-color, #fff);
|
||||
}
|
||||
.aksrt-as-card__head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.aksrt-as-card__status {
|
||||
margin-left: auto;
|
||||
color: var(--focus-color, #2f6df6);
|
||||
font-weight: 600;
|
||||
}
|
||||
.aksrt-as-timeline {
|
||||
margin: 10px 0 0;
|
||||
padding-left: 18px;
|
||||
color: var(--muted-2-color, #888);
|
||||
font-size: 12px;
|
||||
}
|
||||
.aksrt-as-card__actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.aksrt-coupon-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.aksrt-coupon-card {
|
||||
border: 1px dashed var(--focus-color, #2f6df6);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
background: color-mix(in srgb, var(--focus-color, #2f6df6) 6%, #fff);
|
||||
}
|
||||
.aksrt-coupon-card__value {
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: var(--focus-color, #2f6df6);
|
||||
}
|
||||
.aksrt-coupon-card__code {
|
||||
font-family: ui-monospace, monospace;
|
||||
margin: 6px 0;
|
||||
}
|
||||
.aksrt-coupon-card__meta {
|
||||
font-size: 12px;
|
||||
color: var(--muted-2-color, #888);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.aksrt-orders-page__field { margin-bottom: 12px; }
|
||||
.aksrt-orders-page__input,
|
||||
.aksrt-orders-page__select,
|
||||
.aksrt-orders-page__textarea {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid var(--main-border-color, #ddd);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Ban appeal form submit.
|
||||
* @package AKSRT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
function ajaxUrl() {
|
||||
if (window.aksrtData && window.aksrtData.ajaxUrl) return window.aksrtData.ajaxUrl;
|
||||
if (window._win && window._win.ajax_url) return window._win.ajax_url;
|
||||
return '/wp-admin/admin-ajax.php';
|
||||
}
|
||||
function toast(msg) {
|
||||
if (window.aksrt && typeof window.aksrt.toast === 'function') {
|
||||
window.aksrt.toast(msg);
|
||||
return;
|
||||
}
|
||||
window.alert(msg);
|
||||
}
|
||||
function init() {
|
||||
var form = document.querySelector('.aksrt-ban-appeal-form');
|
||||
if (!form) return;
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var btn = form.querySelector('button[type="submit"]');
|
||||
if (btn) btn.disabled = true;
|
||||
var fd = new FormData(form);
|
||||
if (!fd.get('action')) fd.set('action', 'aksrt_ban_appeal_submit');
|
||||
fetch(ajaxUrl(), { method: 'POST', body: fd, credentials: 'same-origin' })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
if (!data || data.error) {
|
||||
toast((data && data.msg) || '提交失败');
|
||||
return;
|
||||
}
|
||||
toast(data.msg || '提交成功');
|
||||
if (data.reload) window.setTimeout(function () { location.reload(); }, 400);
|
||||
})
|
||||
.catch(function () { toast('网络错误'); })
|
||||
.finally(function () { if (btn) btn.disabled = false; });
|
||||
});
|
||||
}
|
||||
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
|
||||
else init();
|
||||
})();
|
||||
+143
-2
@@ -617,9 +617,150 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Close modal
|
||||
if (event.target.closest("[data-aksrt-aftersale-modal-close]") || (event.target.classList && event.target.classList.contains("aksrt-modal__overlay"))) {
|
||||
// Return shipping
|
||||
var returnShipBtn = event.target.closest("[data-aksrt-return-ship]");
|
||||
if (returnShipBtn) {
|
||||
openReturnShipModal(returnShipBtn.getAttribute("data-aksrt-return-ship"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel after-sale ticket
|
||||
var asCancelBtn = event.target.closest("[data-aksrt-as-cancel]");
|
||||
if (asCancelBtn) {
|
||||
var tid = asCancelBtn.getAttribute("data-aksrt-as-cancel");
|
||||
if (!tid || !window.confirm("确认取消该售后申请?")) return;
|
||||
asCancelBtn.disabled = true;
|
||||
request("/shop/frontend/after-sale/" + tid + "/cancel", { reason: "" })
|
||||
.then(function (result) {
|
||||
asCancelBtn.disabled = false;
|
||||
if (!result || !result.success) {
|
||||
showToast((result && result.message) || "取消失败");
|
||||
return;
|
||||
}
|
||||
showToast(result.message || "已取消售后");
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(function () {
|
||||
asCancelBtn.disabled = false;
|
||||
showToast("网络错误");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Close after-sale modal
|
||||
if (event.target.closest("[data-aksrt-aftersale-modal-close]") || (event.target.classList && event.target.classList.contains("aksrt-modal__overlay") && event.target.closest("[data-aksrt-aftersale-modal]"))) {
|
||||
closeAfterSaleModal();
|
||||
return;
|
||||
}
|
||||
|
||||
// Close return-ship modal
|
||||
if (event.target.closest("[data-aksrt-return-ship-close]") || (event.target.classList && event.target.classList.contains("aksrt-modal__overlay") && event.target.closest("[data-aksrt-return-ship-modal]"))) {
|
||||
closeReturnShipModal();
|
||||
}
|
||||
});
|
||||
|
||||
/* ── Return shipping modal ── */
|
||||
var returnShipModal = page.querySelector("[data-aksrt-return-ship-modal]");
|
||||
var returnShipForm = page.querySelector("[data-aksrt-return-ship-form]");
|
||||
function openReturnShipModal(ticketId) {
|
||||
if (!returnShipModal || !returnShipForm) return;
|
||||
returnShipForm.reset();
|
||||
var idInput = returnShipForm.querySelector('[name="ticket_id"]');
|
||||
if (idInput) idInput.value = ticketId || "";
|
||||
returnShipModal.hidden = false;
|
||||
}
|
||||
function closeReturnShipModal() {
|
||||
if (returnShipModal) returnShipModal.hidden = true;
|
||||
}
|
||||
if (returnShipForm) {
|
||||
returnShipForm.addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
var fd = new FormData(returnShipForm);
|
||||
var tid = fd.get("ticket_id");
|
||||
var carrier = (fd.get("carrier") || "").trim();
|
||||
var tracking = (fd.get("tracking_no") || "").trim();
|
||||
if (!carrier || !tracking) {
|
||||
showToast("请填写快递公司与运单号");
|
||||
return;
|
||||
}
|
||||
var btn = returnShipForm.querySelector('button[type="submit"]');
|
||||
if (btn) { btn.disabled = true; }
|
||||
request("/shop/frontend/after-sale/" + tid + "/return-shipping", {
|
||||
carrier: carrier,
|
||||
tracking_no: tracking
|
||||
}).then(function (result) {
|
||||
if (btn) btn.disabled = false;
|
||||
if (!result || !result.success) {
|
||||
showToast((result && result.message) || "提交失败");
|
||||
return;
|
||||
}
|
||||
closeReturnShipModal();
|
||||
showToast(result.message || "退货物流已提交");
|
||||
window.location.reload();
|
||||
}).catch(function () {
|
||||
if (btn) btn.disabled = false;
|
||||
showToast("网络错误");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ── Coupon wallet ── */
|
||||
var couponRoot = page.querySelector("[data-aksrt-coupon-wallet-list]");
|
||||
if (couponRoot) {
|
||||
request("/shop/frontend/coupons").then(function (result) {
|
||||
var items = (result && result.data && result.data.items) || (result && result.items) || [];
|
||||
// normalize success envelope
|
||||
if (result && result.data && result.data.data && result.data.data.items) {
|
||||
items = result.data.data.items;
|
||||
}
|
||||
if (result && result.success && result.data && result.data.items) {
|
||||
items = result.data.items;
|
||||
}
|
||||
// handle this success() wrapper: {success,data:{items}}
|
||||
if (Array.isArray(result && result.data)) items = result.data;
|
||||
if (!items.length && result && result.data && Array.isArray(result.data.items)) {
|
||||
items = result.data.items;
|
||||
}
|
||||
// fallback parse
|
||||
try {
|
||||
if (!items.length && result && result.data && result.data.data) {
|
||||
items = result.data.data.items || [];
|
||||
}
|
||||
} catch (e) {}
|
||||
if (!items || !items.length) {
|
||||
couponRoot.innerHTML = '<p class="muted-2-color">暂无可用优惠券</p>';
|
||||
return;
|
||||
}
|
||||
var html = '<div class="aksrt-coupon-grid">';
|
||||
items.forEach(function (c) {
|
||||
var val = c.type === "percent" ? (c.value + "%") : ("¥" + Number(c.value || 0).toFixed(2));
|
||||
html += '<div class="aksrt-coupon-card">';
|
||||
html += '<div class="aksrt-coupon-card__value">' + val + '</div>';
|
||||
html += '<div class="aksrt-coupon-card__code">' + (c.code || "") + '</div>';
|
||||
if (c.min_amount > 0) {
|
||||
html += '<div class="aksrt-coupon-card__meta">满 ¥' + Number(c.min_amount).toFixed(2) + ' 可用</div>';
|
||||
}
|
||||
if (c.expires_at) {
|
||||
html += '<div class="aksrt-coupon-card__meta">有效期至 ' + c.expires_at + '</div>';
|
||||
}
|
||||
html += '<button type="button" class="btn-outline btn-sm" data-aksrt-copy-coupon="' + (c.code || "") + '">复制券码</button>';
|
||||
html += '</div>';
|
||||
});
|
||||
html += '</div>';
|
||||
couponRoot.innerHTML = html;
|
||||
}).catch(function () {
|
||||
couponRoot.innerHTML = '<p class="muted-2-color">加载失败</p>';
|
||||
});
|
||||
page.addEventListener("click", function (e) {
|
||||
var b = e.target.closest("[data-aksrt-copy-coupon]");
|
||||
if (!b) return;
|
||||
var code = b.getAttribute("data-aksrt-copy-coupon") || "";
|
||||
if (!code) return;
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(code).then(function () { showToast("已复制 " + code); });
|
||||
} else {
|
||||
showToast(code);
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user