fix(frontend): keep asset and homepage filters in DOM #18
+63
-25
@@ -528,7 +528,18 @@
|
||||
var item = document.createElement('button');
|
||||
item.type = 'button';
|
||||
item.className = 'uc-transfer-user';
|
||||
item.innerHTML = '<img' + window.aksrtGetLazyImageAttr('lazy_avatar', u.avatar || '', 'uc-transfer-user__avatar', 'sm') + ' alt=""><span>' + (u.display_name || u.user_login) + '</span><span class="muted-2-color em09">@' + (u.user_login || '') + '</span>';
|
||||
var avatar = document.createElement('img');
|
||||
avatar.className = 'uc-transfer-user__avatar';
|
||||
avatar.alt = '';
|
||||
avatar.src = String(u.avatar || '');
|
||||
item.appendChild(avatar);
|
||||
var displayName = document.createElement('span');
|
||||
displayName.textContent = String(u.display_name || u.user_login || '');
|
||||
item.appendChild(displayName);
|
||||
var login = document.createElement('span');
|
||||
login.className = 'muted-2-color em09';
|
||||
login.textContent = '@' + String(u.user_login || '');
|
||||
item.appendChild(login);
|
||||
item.addEventListener('click', function () {
|
||||
if (recipientInput) recipientInput.value = String(u.id);
|
||||
if (selected) selected.textContent = '已选择:' + (u.display_name || u.user_login);
|
||||
@@ -737,31 +748,58 @@
|
||||
}
|
||||
|
||||
function initAssetTabs() {
|
||||
var nav = document.querySelectorAll('[data-aksrt-asset-tab]');
|
||||
if (!nav.length) return;
|
||||
nav.forEach(function (link) {
|
||||
if (link.dataset.aksrtAssetTabBound === 'true') return;
|
||||
link.dataset.aksrtAssetTabBound = 'true';
|
||||
link.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
var key = link.getAttribute('data-aksrt-asset-tab');
|
||||
document.querySelectorAll('.uc-asset-tabs__nav [data-aksrt-asset-tab]').forEach(function (a) {
|
||||
var li = a.closest('li');
|
||||
if (!li) return;
|
||||
var aKey = a.getAttribute('data-aksrt-asset-tab');
|
||||
var on = aKey === key || (key === 'points_date' && aKey === 'points_free');
|
||||
li.classList.toggle('active', on);
|
||||
});
|
||||
var tabs = document.querySelector('.uc-asset-tabs');
|
||||
if (tabs && typeof tabs.scrollIntoView === 'function') {
|
||||
tabs.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
document.querySelectorAll('[data-aksrt-asset-pane]').forEach(function (pane) {
|
||||
var on = pane.getAttribute('data-aksrt-asset-pane') === key;
|
||||
pane.classList.toggle('is-active', on);
|
||||
pane.hidden = !on;
|
||||
});
|
||||
if (document.documentElement.dataset.aksrtAssetTabsBound === 'true') return;
|
||||
document.documentElement.dataset.aksrtAssetTabsBound = 'true';
|
||||
|
||||
function select(key) {
|
||||
document.querySelectorAll('.uc-asset-tabs__nav [data-aksrt-asset-tab]').forEach(function (link) {
|
||||
var li = link.closest('li');
|
||||
if (!li) return;
|
||||
var linkKey = link.getAttribute('data-aksrt-asset-tab');
|
||||
li.classList.toggle('active', linkKey === key || (key === 'points_date' && linkKey === 'points_free'));
|
||||
});
|
||||
document.querySelectorAll('[data-aksrt-asset-pane]').forEach(function (pane) {
|
||||
var active = pane.getAttribute('data-aksrt-asset-pane') === key;
|
||||
pane.classList.toggle('is-active', active);
|
||||
pane.hidden = !active;
|
||||
});
|
||||
}
|
||||
|
||||
function loadPage(key, page) {
|
||||
var panel = document.querySelector('#panel-credits');
|
||||
var rest = (window.aksrtData && (window.aksrtData.restUrl || window.aksrtData.apiUrl)) || '';
|
||||
if (!panel || !rest) return;
|
||||
panel.classList.add('is-loading');
|
||||
var url = rest.replace(/\/$/, '') + '/user-center/panel/credits?asset=' + encodeURIComponent(key) + '&page=' + encodeURIComponent(page);
|
||||
fetch(url, {
|
||||
credentials: 'same-origin',
|
||||
headers: { 'X-WP-Nonce': (window.aksrtData && (window.aksrtData.restNonce || window.aksrtData.nonce)) || '' }
|
||||
}).then(function (response) {
|
||||
return response.json().then(function (payload) {
|
||||
if (!response.ok || !payload || !payload.success || !payload.data || typeof payload.data.html !== 'string') throw new Error('asset-page-load-failed');
|
||||
panel.innerHTML = payload.data.html;
|
||||
if (window.jQuery) jQuery(document).trigger('post_ajax.ed', [panel]);
|
||||
if (typeof window.auto_fun === 'function') window.auto_fun();
|
||||
select(key);
|
||||
});
|
||||
}).catch(function () {
|
||||
notyf('记录加载失败,请重试', 'danger');
|
||||
}).finally(function () {
|
||||
panel.classList.remove('is-loading');
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
var pageButton = e.target.closest('[data-aksrt-asset-page]');
|
||||
if (pageButton) {
|
||||
e.preventDefault();
|
||||
loadPage(pageButton.getAttribute('data-aksrt-asset-key') || 'points', parseInt(pageButton.getAttribute('data-aksrt-asset-page') || '1', 10) || 1);
|
||||
return;
|
||||
}
|
||||
var link = e.target.closest('[data-aksrt-asset-tab]');
|
||||
if (!link) return;
|
||||
e.preventDefault();
|
||||
select(link.getAttribute('data-aksrt-asset-tab'));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+43
-89
@@ -11,7 +11,6 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var SORT_QUERY_KEY = 'home_sort';
|
||||
var DEFAULT_SORT = 'modified';
|
||||
var REST_PATH = '/wp-json/aksrt/v1/homepage/tab-posts';
|
||||
|
||||
@@ -19,10 +18,6 @@
|
||||
* Utilities
|
||||
* ============================================================ */
|
||||
|
||||
function getViewMode() {
|
||||
return getDefaultView();
|
||||
}
|
||||
|
||||
function getRenderedPostCount(scope) {
|
||||
if (!scope) return 0;
|
||||
return scope.querySelectorAll('.posts-item, .posts-mini').length;
|
||||
@@ -42,7 +37,7 @@
|
||||
|
||||
function getDefaultSort() {
|
||||
var configured = window.aksrtData && aksrtData.homepageDefaultSort;
|
||||
var allowed = ['modified', 'date', 'downloads', 'views', 'likes', 'comments'];
|
||||
var allowed = ['modified', 'date', 'views', 'like', 'comment_count', 'favorite', 'rand'];
|
||||
return allowed.indexOf(configured) !== -1 ? configured : DEFAULT_SORT;
|
||||
}
|
||||
|
||||
@@ -51,12 +46,6 @@
|
||||
return panel && panel.getAttribute('data-view') === 'card' ? 'card' : 'list';
|
||||
}
|
||||
|
||||
function isSortAjaxEnabled(sortbar) {
|
||||
var attr = sortbar && sortbar.getAttribute('data-sort-ajax');
|
||||
if (attr === 'false') return false;
|
||||
return !(window.aksrtData && aksrtData.homepageSortAjax === false);
|
||||
}
|
||||
|
||||
function isStickyTabsEnabled() {
|
||||
return !(window.aksrtData && aksrtData.homepageStickyTabs === false);
|
||||
}
|
||||
@@ -66,14 +55,11 @@
|
||||
return baseUrl.replace(/\/?$/, '');
|
||||
}
|
||||
|
||||
function getSortFromUrl() {
|
||||
return new URLSearchParams(window.location.search).get(SORT_QUERY_KEY) || getDefaultSort();
|
||||
function getCurrentSort(stream) {
|
||||
var activeLink = stream ? stream.querySelector('.aksrt-homepage__sortbar-link.is-active, .aksrt-homepage__sortbar-dropdown-item.is-active') : null;
|
||||
return (activeLink && activeLink.getAttribute('data-sort')) || getDefaultSort();
|
||||
}
|
||||
|
||||
function getCurrentSort(stream) {
|
||||
var activeLink = stream ? stream.querySelector('.aksrt-homepage__sortbar-link.is-active') : null;
|
||||
return (activeLink && activeLink.getAttribute('data-sort')) || getSortFromUrl();
|
||||
}
|
||||
|
||||
function setActiveSortLink(sortbar, sort) {
|
||||
var links = sortbar.querySelectorAll('.aksrt-homepage__sortbar-link, .aksrt-homepage__sortbar-dropdown-item');
|
||||
@@ -88,20 +74,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeHomepageUrl(url) {
|
||||
url.searchParams.delete('paged');
|
||||
url.searchParams.delete('page');
|
||||
url.pathname = url.pathname.replace(/\/page\/\d+\/?$/, '/');
|
||||
return url;
|
||||
}
|
||||
|
||||
function replaceUrlSort(sort) {
|
||||
if (!window.history || !window.history.replaceState) return;
|
||||
var url = normalizeHomepageUrl(new URL(window.location.href));
|
||||
url.searchParams.set(SORT_QUERY_KEY, sort);
|
||||
window.history.replaceState({}, '', url.toString());
|
||||
}
|
||||
|
||||
function getStreamViewMode(stream) {
|
||||
var panel = getActivePanel(stream);
|
||||
return panel && panel.getAttribute('data-view') === 'card' ? 'card' : 'list';
|
||||
@@ -124,12 +96,6 @@
|
||||
return panel.getAttribute('data-tab-orderby') || '';
|
||||
}
|
||||
|
||||
function getPanelSource(panel) {
|
||||
var target = panel ? panel.getAttribute('data-home-tab-panel') : '';
|
||||
if (target === 'latest') return 'home';
|
||||
return target ? 'home' : 'widget';
|
||||
}
|
||||
|
||||
function buildRestUrl(options) {
|
||||
options = options || {};
|
||||
return getRestBaseUrl() + REST_PATH +
|
||||
@@ -137,9 +103,7 @@
|
||||
'&page=' + encodeURIComponent(options.page || 1) +
|
||||
'&per_page=' + encodeURIComponent(options.perPage || 10) +
|
||||
'&sort=' + encodeURIComponent(options.sort || getDefaultSort()) +
|
||||
'&page_url=' + encodeURIComponent(options.pageUrl || window.location.href) +
|
||||
'&panel=' + encodeURIComponent(options.panel || 'latest') +
|
||||
'&source=' + encodeURIComponent(options.source || 'home') +
|
||||
'&tab_orderby=' + encodeURIComponent(options.tabOrderby || '');
|
||||
}
|
||||
|
||||
@@ -149,7 +113,7 @@
|
||||
|
||||
/**
|
||||
* Dispatch post_ajax.before — fired before AJAX request is sent.
|
||||
* Detail: { termId, page, sort, viewMode, panel, source, url }
|
||||
* Detail: { termId, page, sort, viewMode, panel, url }
|
||||
*/
|
||||
function dispatchBeforeEvent(container, detail) {
|
||||
try {
|
||||
@@ -162,7 +126,7 @@
|
||||
|
||||
/**
|
||||
* Dispatch post_ajax.ed — fired after AJAX response is injected.
|
||||
* Detail: { termId, page, sort, viewMode, panel, source, total, hasMore }
|
||||
* Detail: { termId, page, sort, viewMode, panel, total, hasMore }
|
||||
*/
|
||||
function dispatchAfterEvent(container, detail) {
|
||||
try {
|
||||
@@ -245,18 +209,16 @@
|
||||
button.addEventListener('click', function () {
|
||||
button.disabled = true;
|
||||
button.textContent = (window.aksrtData && aksrtData.ajaxLoading) || '正在加载...';
|
||||
requestHomepagePanel(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page + 1,
|
||||
perPage: options.perPage,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
pageUrl: options.pageUrl,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
tabOrderby: options.tabOrderby,
|
||||
append: true
|
||||
});
|
||||
requestHomepagePanel(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page + 1,
|
||||
perPage: options.perPage,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
tabOrderby: options.tabOrderby,
|
||||
append: true
|
||||
});
|
||||
});
|
||||
footer.appendChild(button);
|
||||
panel.appendChild(footer);
|
||||
@@ -293,33 +255,30 @@
|
||||
* 4. aksrt:posts:rendered (after lazyload rebind)
|
||||
*/
|
||||
function requestHomepagePanel(panel, requestOptions) {
|
||||
var options = {
|
||||
termId: requestOptions.termId || 0,
|
||||
page: requestOptions.page || 1,
|
||||
perPage: requestOptions.perPage || getHomepagePerPage(panel),
|
||||
sort: requestOptions.sort || getDefaultSort(),
|
||||
viewMode: requestOptions.viewMode || getDefaultView(),
|
||||
pageUrl: requestOptions.pageUrl || window.location.href,
|
||||
panel: requestOptions.panel || panel.getAttribute('data-home-tab-panel') || 'latest',
|
||||
source: requestOptions.source || getPanelSource(panel),
|
||||
tabOrderby: requestOptions.tabOrderby || getPanelTabOrderby(panel) || '',
|
||||
append: requestOptions.append === true
|
||||
};
|
||||
var options = {
|
||||
termId: requestOptions.termId || 0,
|
||||
page: requestOptions.page || 1,
|
||||
perPage: requestOptions.perPage || getHomepagePerPage(panel),
|
||||
sort: requestOptions.sort || getDefaultSort(),
|
||||
viewMode: requestOptions.viewMode || getDefaultView(),
|
||||
panel: requestOptions.panel || panel.getAttribute('data-home-tab-panel') || 'latest',
|
||||
tabOrderby: requestOptions.tabOrderby || getPanelTabOrderby(panel) || '',
|
||||
append: requestOptions.append === true
|
||||
};
|
||||
|
||||
var restUrl = buildRestUrl(options);
|
||||
var retryCount = 0;
|
||||
var maxRetries = 1;
|
||||
|
||||
// 1. Pre-request event
|
||||
dispatchBeforeEvent(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
url: restUrl
|
||||
});
|
||||
dispatchBeforeEvent(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
url: restUrl
|
||||
});
|
||||
|
||||
// Full refreshes replace the panel; append requests keep existing cards.
|
||||
if (!options.append) {
|
||||
@@ -365,11 +324,10 @@
|
||||
dispatchAfterEvent(panel, {
|
||||
termId: options.termId,
|
||||
page: options.page,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
total: data.total || 0,
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
total: data.total || 0,
|
||||
hasMore: !!data.has_more
|
||||
});
|
||||
|
||||
@@ -393,7 +351,6 @@
|
||||
sort: options.sort,
|
||||
viewMode: options.viewMode,
|
||||
panel: options.panel,
|
||||
source: options.source,
|
||||
total: 0,
|
||||
hasMore: false
|
||||
});
|
||||
@@ -477,9 +434,8 @@
|
||||
perPage: getHomepagePerPage(panel),
|
||||
sort: currentSort,
|
||||
viewMode: viewMode,
|
||||
panel: target,
|
||||
source: 'home',
|
||||
tabOrderby: tabOrderby
|
||||
panel: target,
|
||||
tabOrderby: tabOrderby
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -600,7 +556,7 @@
|
||||
function initSortbar() {
|
||||
document.querySelectorAll('.aksrt-homepage__stream').forEach(function (stream) {
|
||||
var sortbar = stream.querySelector('.aksrt-homepage__sortbar');
|
||||
if (!sortbar || !isSortAjaxEnabled(sortbar)) return;
|
||||
if (!sortbar) return;
|
||||
|
||||
sortbar.addEventListener('click', function (event) {
|
||||
var link = event.target.closest('.aksrt-homepage__sortbar-link, .aksrt-homepage__sortbar-dropdown-item');
|
||||
@@ -612,17 +568,15 @@
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
setActiveSortLink(sortbar, sort);
|
||||
replaceUrlSort(sort);
|
||||
setActiveSortLink(sortbar, sort);
|
||||
|
||||
requestHomepagePanel(activePanel, {
|
||||
requestHomepagePanel(activePanel, {
|
||||
termId: termId,
|
||||
page: 1,
|
||||
perPage: getHomepagePerPage(activePanel),
|
||||
sort: sort,
|
||||
viewMode: getStreamViewMode(stream),
|
||||
panel: activePanel.getAttribute('data-home-tab-panel') || 'latest',
|
||||
source: 'home'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
html += '<strong class="aksrt-order-detail__hero-amount">' + formatMoney(order) + "</strong></div>";
|
||||
html += '<div class="aksrt-order-detail__product">';
|
||||
html += image
|
||||
? '<img' + window.aksrtGetLazyImageAttr('lazy_posts_thumb', image, 'aksrt-order-detail__thumb') + ' alt="">'
|
||||
? '<img src="' + escapeHtml(image) + '" class="aksrt-order-detail__thumb" alt="">'
|
||||
: '<span class="aksrt-order-detail__thumb aksrt-order-detail__thumb--empty"><i class="fa fas fa-book"></i></span>';
|
||||
html += '<div><strong class="aksrt-order-detail__product-title">' + escapeHtml(title) + "</strong>";
|
||||
html += '<span class="aksrt-order-detail__product-meta">' + escapeHtml(order.product_type_label || "") + "</span></div></div>";
|
||||
@@ -179,7 +179,7 @@
|
||||
|
||||
function cardHtml(order) {
|
||||
var image = order.image
|
||||
? '<img' + window.aksrtGetLazyImageAttr('lazy_posts_thumb', order.image, 'aksrt-orders-page__card-img') + ' alt="">'
|
||||
? '<img src="' + escapeHtml(order.image) + '" class="aksrt-orders-page__card-img" alt="">'
|
||||
: '<div class="aksrt-orders-page__card-art" aria-hidden="true"><i class="fa fas fa-book"></i></div>';
|
||||
var countdown = Number(order.time_left || 0) > 0
|
||||
? '<span class="aksrt-orders-page__countdown" data-aksrt-order-countdown="' + Number(order.time_left) + '"></span>'
|
||||
|
||||
@@ -288,7 +288,7 @@
|
||||
items.forEach(function (item) {
|
||||
html += '<a class="aksrt-doc-index-card" href="' + this.escHtml(item.url) + '" data-cat-id="' + (item.cat_id || 0) + '">';
|
||||
if (item.thumbnail) {
|
||||
html += '<img' + window.aksrtGetLazyImageAttr('lazy_other', item.thumbnail, 'aksrt-doc-index-card__thumb') + ' alt="">';
|
||||
html += '<img src="' + this.escHtml(item.thumbnail) + '" class="aksrt-doc-index-card__thumb" alt="">';
|
||||
}
|
||||
html += '<div class="aksrt-doc-index-card__body">';
|
||||
html += '<h3 class="aksrt-doc-index-card__title">' + this.escHtml(item.title) + '</h3>';
|
||||
|
||||
@@ -17,10 +17,14 @@
|
||||
return el;
|
||||
}
|
||||
|
||||
function lazyImage(key, src, className, size) {
|
||||
var template = document.createElement("template");
|
||||
template.innerHTML = "<img" + window.aksrtGetLazyImageAttr(key, src, className, size) + ' alt="" decoding="async">';
|
||||
return template.content.firstElementChild;
|
||||
function imageNode(src, className) {
|
||||
if (!src) return null;
|
||||
var image = document.createElement("img");
|
||||
image.className = className || "";
|
||||
image.src = text(src);
|
||||
image.alt = "";
|
||||
image.decoding = "async";
|
||||
return image;
|
||||
}
|
||||
|
||||
function append(parent, child) {
|
||||
@@ -312,7 +316,7 @@
|
||||
var levelInfo = levels[String(level)] || {};
|
||||
var levelHeader = node("div", "aksrt-vip-level-header");
|
||||
if (levelInfo.img_icon) {
|
||||
var levelIcon = lazyImage("lazy_other", text(levelInfo.img_icon), "aksrt-vip-level-icon");
|
||||
var levelIcon = imageNode(text(levelInfo.img_icon), "aksrt-vip-level-icon");
|
||||
append(levelHeader, levelIcon);
|
||||
}
|
||||
append(levelHeader, node("div", "v-name font-bold", group.name || levelInfo.name || "VIP" + level));
|
||||
|
||||
@@ -42,8 +42,10 @@
|
||||
|
||||
/* ==================== Dashboard 导航 ==================== */
|
||||
function initDashboardNavigation() {
|
||||
if (document.documentElement.dataset.aksrtUserCenterNavigationInitialized === 'true') return;
|
||||
var tabContainer = document.querySelector('.uc-mobile-tabs');
|
||||
if (!tabContainer) return;
|
||||
document.documentElement.dataset.aksrtUserCenterNavigationInitialized = 'true';
|
||||
|
||||
var tabs = tabContainer.querySelectorAll('[data-tab]');
|
||||
var sidebarBtns = document.querySelectorAll('.uc-sidebar [data-tab]');
|
||||
@@ -107,6 +109,7 @@
|
||||
if (name === 'revenue') allowedParams = ['reward_tab', 'commission_page', 'user_page'];
|
||||
if (name === 'posts') allowedParams = ['post_status', 'posts_page'];
|
||||
if (name === 'follow') allowedParams = ['follow_list', 'follow_page'];
|
||||
if (name === 'credits') allowedParams = ['asset', 'page'];
|
||||
allowedParams.forEach(function(key) {
|
||||
if (params.get(key)) url += (url.indexOf('?') === -1 ? '?' : '&') + key + '=' + encodeURIComponent(params.get(key));
|
||||
});
|
||||
@@ -166,8 +169,6 @@
|
||||
|
||||
function activate(name, updateHistory, forceLoad, queryParams) {
|
||||
if (!panels[name]) name = defaultTab;
|
||||
// VIP membership may change outside this page, so never reuse stale HTML.
|
||||
if (name === 'vip' && !forceLoad) forceLoad = true;
|
||||
return loadPanel(name, forceLoad, queryParams).then(function() {
|
||||
switchTo(name);
|
||||
if (updateHistory) updateUrl(name);
|
||||
@@ -187,11 +188,11 @@
|
||||
return tabAliases[name] || name;
|
||||
}
|
||||
|
||||
function updateUrl(name, sourceUrl) {
|
||||
if (!window.history.replaceState) return;
|
||||
function updateUrl(name, sourceUrl) {
|
||||
if (!window.history.pushState) return;
|
||||
var pathTab = name === 'credits' ? 'balance' : name;
|
||||
var u = new URL('/user/' + pathTab + '/', window.location.origin);
|
||||
if (sourceUrl && name !== 'revenue' && name !== 'orders') {
|
||||
if (sourceUrl && name !== 'revenue' && name !== 'orders' && name !== 'credits') {
|
||||
var source = new URL(sourceUrl, window.location.href);
|
||||
source.searchParams.forEach(function(value, key) { u.searchParams.set(key, value); });
|
||||
}
|
||||
@@ -249,8 +250,8 @@
|
||||
name = tabAliases[name] || name;
|
||||
if (!name || !panels[name]) return;
|
||||
e.preventDefault();
|
||||
var hasQuery = url.search !== '';
|
||||
activate(name, false, hasQuery, url.searchParams).then(function() { updateUrl(name, url.href); });
|
||||
var hasQuery = url.search !== '' && name !== 'credits';
|
||||
activate(name, false, hasQuery, name === 'credits' ? null : url.searchParams).then(function() { updateUrl(name, name === 'credits' ? '' : url.href); });
|
||||
}, true);
|
||||
var creatorPanel = panels.creator ? panels.creator.panel : null;
|
||||
if (creatorPanel) {
|
||||
@@ -269,11 +270,21 @@
|
||||
});
|
||||
}
|
||||
window.addEventListener('popstate', function() {
|
||||
activate(tabFromUrl(), false, window.location.search !== '', new URLSearchParams(window.location.search));
|
||||
var current = new URL(window.location.href);
|
||||
['wallet_page', 'credits_page', 'asset', 'page'].forEach(function (key) { current.searchParams.delete(key); });
|
||||
if (current.href !== window.location.href && window.history.replaceState) {
|
||||
window.history.replaceState({}, '', current.pathname + current.search + current.hash);
|
||||
}
|
||||
activate(tabFromUrl(), false, false, null);
|
||||
});
|
||||
if (drawerTrigger) drawerTrigger.addEventListener('click', openDrawer);
|
||||
if (drawerOverlay) drawerOverlay.addEventListener('click', closeDrawer);
|
||||
var initialTab = tabFromUrl();
|
||||
if (initialTab === 'credits' && window.history && window.history.replaceState) {
|
||||
var cleanUrl = new URL(window.location.href);
|
||||
['wallet_page', 'credits_page', 'asset', 'page'].forEach(function (key) { cleanUrl.searchParams.delete(key); });
|
||||
window.history.replaceState({}, '', cleanUrl.pathname + cleanUrl.search + cleanUrl.hash);
|
||||
}
|
||||
if (initialTab === 'orders' && window.location.search && window.history.replaceState) {
|
||||
window.history.replaceState({}, '', window.location.pathname + window.location.hash);
|
||||
}
|
||||
|
||||
@@ -2258,21 +2258,6 @@ _win.bd.on('click', '[data-toggle="RefreshModal"]', function (e) {
|
||||
return false;
|
||||
});
|
||||
|
||||
_win.bd.on('click', '.show-order-modal', function (e) {
|
||||
e.preventDefault();
|
||||
var _this = jQuery(this);
|
||||
var order_id = _this.attr('data-order-id');
|
||||
var is_new = _this.attr('new-modal');
|
||||
refresh_modal({
|
||||
class: 'full-sm body-bg',
|
||||
height: 420,
|
||||
mobile_from_bottom: true,
|
||||
touch_close: true,
|
||||
new: is_new,
|
||||
remote: _win.ajax_url + '?action=order_details_modal&order_id=' + order_id,
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 刷新模态框
|
||||
* @param {object} _config
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -150,7 +150,7 @@ if (!function_exists('aksrt_homepage_get_sort_mode')) {
|
||||
$override_sort = get_query_var('aksrt_homepage_sort_override');
|
||||
$sort = is_string($override_sort) && $override_sort !== ''
|
||||
? sanitize_key($override_sort)
|
||||
: (isset($_GET['home_sort']) ? sanitize_key(wp_unslash((string) $_GET['home_sort'])) : $default_sort);
|
||||
: $default_sort;
|
||||
|
||||
return in_array($sort, $allowed, true) ? $sort : $default_sort;
|
||||
}
|
||||
@@ -279,19 +279,15 @@ if (!function_exists('aksrt_homepage_render_sortbar')) {
|
||||
}
|
||||
|
||||
$current = aksrt_homepage_get_sort_mode();
|
||||
$sort_ajax_enabled = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::homepage_sort_ajax_enabled()
|
||||
: true;
|
||||
$is_dropdown = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::home_list_sort_dropdown()
|
||||
: false;
|
||||
$base_url = remove_query_arg('home_sort', get_pagenum_link(aksrt_homepage_get_current_page()));
|
||||
$sort_items = aksrt_homepage_get_sort_items();
|
||||
$all_labels = class_exists('\AKSRT\Settings\Settings')
|
||||
? \AKSRT\Settings\Settings::homepage_sort_labels()
|
||||
: $sort_items;
|
||||
?>
|
||||
<div class="aksrt-homepage__sortbar" data-sort-ajax="<?php echo $sort_ajax_enabled ? 'true' : 'false'; ?>" aria-label="<?php esc_attr_e('Homepage Sort', 'aksrt'); ?>">
|
||||
<div class="aksrt-homepage__sortbar" aria-label="<?php esc_attr_e('Homepage Sort', 'aksrt'); ?>">
|
||||
<?php if ($is_dropdown) : ?>
|
||||
<div class="aksrt-homepage__sortbar-dropdown">
|
||||
<button type="button" class="aksrt-homepage__sortbar-current" data-sort-dropdown-trigger>
|
||||
@@ -300,26 +296,24 @@ if (!function_exists('aksrt_homepage_render_sortbar')) {
|
||||
</button>
|
||||
<div class="aksrt-homepage__sortbar-dropdown-menu" hidden>
|
||||
<?php foreach ($sort_items as $sort_key => $label) : ?>
|
||||
<a
|
||||
class="aksrt-homepage__sortbar-dropdown-item<?php echo $sort_key === $current ? ' is-active' : ''; ?>"
|
||||
href="<?php echo esc_url(add_query_arg('home_sort', $sort_key, $base_url)); ?>"
|
||||
data-sort="<?php echo esc_attr($sort_key); ?>"
|
||||
>
|
||||
<?php echo esc_html($label); ?>
|
||||
</a>
|
||||
<button type="button"
|
||||
class="aksrt-homepage__sortbar-dropdown-item<?php echo $sort_key === $current ? ' is-active' : ''; ?>"
|
||||
data-sort="<?php echo esc_attr($sort_key); ?>"
|
||||
>
|
||||
<?php echo esc_html($label); ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="aksrt-homepage__sortbar-links">
|
||||
<?php foreach ($sort_items as $sort_key => $label) : ?>
|
||||
<a
|
||||
class="aksrt-homepage__sortbar-link<?php echo $sort_key === $current ? ' is-active' : ''; ?>"
|
||||
href="<?php echo esc_url(add_query_arg('home_sort', $sort_key, $base_url)); ?>"
|
||||
data-sort="<?php echo esc_attr($sort_key); ?>"
|
||||
>
|
||||
<?php echo esc_html($label); ?>
|
||||
</a>
|
||||
<button type="button"
|
||||
class="aksrt-homepage__sortbar-link<?php echo $sort_key === $current ? ' is-active' : ''; ?>"
|
||||
data-sort="<?php echo esc_attr($sort_key); ?>"
|
||||
>
|
||||
<?php echo esc_html($label); ?>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -17,8 +17,11 @@ defined('ABSPATH') || exit;
|
||||
</h3>
|
||||
</div>
|
||||
<?php
|
||||
$credits_page = max(1, isset($_GET['credits_page']) ? (int) $_GET['credits_page'] : 1);
|
||||
$log = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => $user_id, 'asset' => 'points', 'page' => $credits_page, 'per_page' => 10]);
|
||||
$asset_request = is_array($asset_request ?? null) ? $asset_request : [];
|
||||
$credits_page = ($asset_request['asset'] ?? '') === 'points'
|
||||
? max(1, (int) ($asset_request['page'] ?? 1))
|
||||
: 1;
|
||||
$log = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => $user_id, 'asset' => 'points', 'page' => $credits_page, 'per_page' => 10]);
|
||||
if (!empty($log['items'])) :
|
||||
?>
|
||||
<div class="uc-transactions__list">
|
||||
@@ -55,8 +58,8 @@ defined('ABSPATH') || exit;
|
||||
</div>
|
||||
<?php
|
||||
$total_pages = (int) ceil((int) ($log['total'] ?? 0) / 10);
|
||||
if ($total_pages > 1) {
|
||||
aksrt_render_profile_pagination($total_pages, $credits_page, 'credits_page');
|
||||
if ($total_pages > 1 && function_exists('aksrt_render_asset_pagination')) {
|
||||
aksrt_render_asset_pagination($total_pages, $credits_page, 'points');
|
||||
}
|
||||
?>
|
||||
<?php else : ?>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* User center balance transaction list.
|
||||
*
|
||||
* Expects extracted $context vars.
|
||||
*
|
||||
* @package AKSRT
|
||||
*/
|
||||
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
$asset_request = is_array($asset_request ?? null) ? $asset_request : [];
|
||||
$wallet_page = ($asset_request['asset'] ?? '') === 'balance'
|
||||
? max(1, (int) ($asset_request['page'] ?? 1))
|
||||
: 1;
|
||||
$wlog = \AKSRT\Ledger\LedgerQuery::get_instance()->history([
|
||||
'user_id' => (int) ($user_id ?? 0),
|
||||
'asset' => 'balance',
|
||||
'page' => $wallet_page,
|
||||
'per_page' => 10,
|
||||
]);
|
||||
?>
|
||||
<div class="uc-transactions uc-transactions--wallet">
|
||||
<div class="uc-transactions__header">
|
||||
<h3 class="uc-transactions__title">
|
||||
<i class="fa fas fa-list-ul" aria-hidden="true"></i>
|
||||
<?php esc_html_e('余额记录', 'aksrt'); ?>
|
||||
</h3>
|
||||
</div>
|
||||
<?php if (!empty($wlog['items'])) : ?>
|
||||
<div class="uc-transactions__list">
|
||||
<?php foreach ($wlog['items'] as $row) :
|
||||
$delta = (int) $row['delta_minor'];
|
||||
$delta_class = $delta >= 0 ? 'is-positive' : 'is-negative';
|
||||
$delta_txt = ($delta > 0 ? '+' : '-') . \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, abs($delta))->formatted();
|
||||
$record_note = (string) $row['reason'] === 'points_exchange'
|
||||
? (string) $row['ref_key']
|
||||
: (string) ($row['remark'] ?? '');
|
||||
if (in_array((string) $row['reason'], ['withdraw_hold', 'withdraw_refund'], true)) {
|
||||
$record_note = (string) ($row['withdrawal_number'] ?? '');
|
||||
}
|
||||
?>
|
||||
<div class="uc-transactions__item">
|
||||
<div class="uc-transactions__icon <?php echo esc_attr($delta_class); ?>">
|
||||
<i class="fa fas fa-<?php echo $delta >= 0 ? 'arrow-up' : 'arrow-down'; ?>" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="uc-transactions__info">
|
||||
<div class="uc-transactions__reason">
|
||||
<?php echo esc_html(aksrt_asset_reason_label((string) $row['reason'])); ?>
|
||||
<?php if ($record_note !== '') : ?>
|
||||
<span class="uc-transactions__remark">(<?php echo esc_html($record_note); ?>)</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uc-transactions__time"><?php echo esc_html(get_date_from_gmt((string) $row['created_at'], 'Y-m-d H:i')); ?></div>
|
||||
</div>
|
||||
<div class="uc-transactions__amount">
|
||||
<span class="uc-transactions__delta <?php echo esc_attr($delta_class); ?>"><?php echo esc_html($delta_txt); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$total_pages = (int) ceil((int) ($wlog['total'] ?? 0) / 10);
|
||||
if ($total_pages > 1 && function_exists('aksrt_render_asset_pagination')) {
|
||||
aksrt_render_asset_pagination($total_pages, $wallet_page, 'balance');
|
||||
}
|
||||
?>
|
||||
<?php else : ?>
|
||||
<div class="uc-transactions__empty">
|
||||
<p><?php esc_html_e('还没有任何余额流水', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -234,65 +234,5 @@ endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (empty($skip_wallet_ledger)) : ?>
|
||||
<div class="uc-transactions uc-transactions--wallet">
|
||||
<div class="uc-transactions__header">
|
||||
<h3 class="uc-transactions__title">
|
||||
<i class="fa fas fa-list-ul" aria-hidden="true"></i>
|
||||
<?php esc_html_e('余额记录', 'aksrt'); ?>
|
||||
</h3>
|
||||
</div>
|
||||
<?php
|
||||
$wallet_page = max(1, isset($_GET['wallet_page']) ? (int) $_GET['wallet_page'] : 1);
|
||||
$wlog = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => (int) $user_id, 'asset' => 'balance', 'page' => $wallet_page, 'per_page' => 10]);
|
||||
if (!empty($wlog['items'])) :
|
||||
?>
|
||||
<div class="uc-transactions__list">
|
||||
<?php foreach ($wlog['items'] as $row) :
|
||||
$delta = (int) $row['delta_minor'];
|
||||
$delta_class = $delta >= 0 ? 'is-positive' : 'is-negative';
|
||||
$delta_txt = ($delta > 0 ? '+' : '-') . \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, abs($delta))->formatted();
|
||||
$record_note = in_array((string) $row['reason'], ['withdraw_hold', 'withdraw_refund'], true)
|
||||
? (string) ($row['withdrawal_number'] ?? '')
|
||||
: (string) ($row['remark'] ?? '');
|
||||
?>
|
||||
<div class="uc-transactions__item">
|
||||
<div class="uc-transactions__icon <?php echo esc_attr($delta_class); ?>">
|
||||
<i class="fa fas fa-<?php echo $delta >= 0 ? 'arrow-up' : 'arrow-down'; ?>" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="uc-transactions__info">
|
||||
<div class="uc-transactions__reason">
|
||||
<?php echo esc_html(aksrt_asset_reason_label((string) $row['reason'])); ?>
|
||||
<?php if ($record_note !== '') : ?>
|
||||
<span class="uc-transactions__remark">(<?php echo esc_html($record_note); ?>)</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uc-transactions__time"><?php echo esc_html(get_date_from_gmt((string) $row['created_at'], 'Y-m-d H:i')); ?></div>
|
||||
</div>
|
||||
<div class="uc-transactions__amount">
|
||||
<span class="uc-transactions__delta <?php echo esc_attr($delta_class); ?>"><?php echo esc_html($delta_txt); ?></span>
|
||||
<span class="uc-transactions__balance">
|
||||
<?php
|
||||
printf(
|
||||
esc_html__('余额 %s', 'aksrt'),
|
||||
esc_html(\AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, (int) $row['balance_after_minor'])->formatted())
|
||||
);
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$total_pages = (int) ceil((int) ($wlog['total'] ?? 0) / 10);
|
||||
if ($total_pages > 1 && function_exists('aksrt_render_profile_pagination')) {
|
||||
aksrt_render_profile_pagination($total_pages, $wallet_page, 'wallet_page');
|
||||
}
|
||||
?>
|
||||
<?php else : ?>
|
||||
<div class="uc-transactions__empty">
|
||||
<div class="uc-transactions__empty-icon"><i class="fa fas fa-money-bill" aria-hidden="true"></i></div>
|
||||
<p><?php esc_html_e('还没有任何余额流水', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; // skip_wallet_ledger ?>
|
||||
<?php require __DIR__ . '/credits-wallet-ledger.php'; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -44,8 +44,12 @@ if ($show_wallet || $show_credits) {
|
||||
|
||||
// Tabbed ledgers (legacy record tabs).
|
||||
if ($show_wallet || $show_credits) :
|
||||
$active_record = $show_wallet ? 'balance' : 'points';
|
||||
$show_tasks = $show_credits && class_exists('\AKSRT\Credits\PointsFree') && \AKSRT\Credits\PointsFree::enabled();
|
||||
$asset_request = is_array($asset_request ?? null) ? $asset_request : [];
|
||||
$requested_asset = in_array(($asset_request['asset'] ?? ''), ['balance', 'points'], true) ? $asset_request['asset'] : '';
|
||||
$active_record = $requested_asset !== ''
|
||||
? $requested_asset
|
||||
: ($show_wallet ? 'balance' : 'points');
|
||||
?>
|
||||
<div class="uc-asset-tabs">
|
||||
<ul class="uc-asset-tabs__nav list-inline tab-nav-theme font-bold">
|
||||
@@ -68,58 +72,7 @@ if ($show_wallet || $show_credits) :
|
||||
<div class="uc-asset-tabs__content tab-content">
|
||||
<?php if ($show_wallet) : ?>
|
||||
<div class="tab-pane<?php echo $active_record === 'balance' ? ' is-active' : ''; ?>" id="record_tab_balance" data-aksrt-asset-pane="balance"<?php echo $active_record === 'balance' ? '' : ' hidden'; ?>>
|
||||
<?php
|
||||
$skip_wallet_ledger = false;
|
||||
// Render only the ledger portion by reusing balance log markup.
|
||||
$user_id = (int) ($user_id ?? 0);
|
||||
$wallet_page = max(1, isset($_GET['wallet_page']) ? (int) $_GET['wallet_page'] : 1);
|
||||
$wlog = \AKSRT\Ledger\LedgerQuery::get_instance()->history(['user_id' => $user_id, 'asset' => 'balance', 'page' => $wallet_page, 'per_page' => 10]);
|
||||
?>
|
||||
<div class="uc-transactions uc-transactions--wallet">
|
||||
<?php if (!empty($wlog['items'])) : ?>
|
||||
<div class="uc-transactions__list">
|
||||
<?php foreach ($wlog['items'] as $row) :
|
||||
$delta = (int) $row['delta_minor'];
|
||||
$delta_class = $delta >= 0 ? 'is-positive' : 'is-negative';
|
||||
$delta_txt = ($delta > 0 ? '+' : '-') . \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, abs($delta))->formatted();
|
||||
$record_note = (string) $row['reason'] === 'points_exchange'
|
||||
? (string) $row['ref_key']
|
||||
: (string) $row['remark'];
|
||||
if (in_array((string) $row['reason'], ['withdraw_hold', 'withdraw_refund'], true)) {
|
||||
$record_note = (string) ($row['withdrawal_number'] ?? '');
|
||||
}
|
||||
?>
|
||||
<div class="uc-transactions__item">
|
||||
<div class="uc-transactions__icon <?php echo esc_attr($delta_class); ?>">
|
||||
<i class="fa fas fa-<?php echo $delta >= 0 ? 'arrow-up' : 'arrow-down'; ?>" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="uc-transactions__info">
|
||||
<div class="uc-transactions__reason">
|
||||
<?php echo esc_html(aksrt_asset_reason_label((string) $row['reason'])); ?>
|
||||
<?php if ($record_note !== '') : ?>
|
||||
<span class="uc-transactions__remark">(<?php echo esc_html($record_note); ?>)</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="uc-transactions__time"><?php echo esc_html(get_date_from_gmt((string) $row['created_at'], 'Y-m-d H:i')); ?></div>
|
||||
</div>
|
||||
<div class="uc-transactions__amount">
|
||||
<span class="uc-transactions__delta <?php echo esc_attr($delta_class); ?>"><?php echo esc_html($delta_txt); ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php
|
||||
$total_pages = (int) ceil((int) ($wlog['total'] ?? 0) / 10);
|
||||
if ($total_pages > 1 && function_exists('aksrt_render_profile_pagination')) {
|
||||
aksrt_render_profile_pagination($total_pages, $wallet_page, 'wallet_page');
|
||||
}
|
||||
?>
|
||||
<?php else : ?>
|
||||
<div class="uc-transactions__empty">
|
||||
<p><?php esc_html_e('还没有任何余额流水', 'aksrt'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php require $dir . '/credits-wallet-ledger.php'; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($show_credits) : ?>
|
||||
|
||||
@@ -114,9 +114,7 @@ class GlobalController extends ControllerBase {
|
||||
'page' => ['type' => 'integer', 'default' => 1, 'sanitize_callback' => 'absint'],
|
||||
'per_page' => ['type' => 'integer', 'default' => 10, 'sanitize_callback' => 'absint'],
|
||||
'sort' => ['type' => 'string', 'default' => 'modified', 'sanitize_callback' => 'sanitize_text_field'],
|
||||
'page_url' => ['type' => 'string', 'default' => '', 'sanitize_callback' => 'esc_url_raw'],
|
||||
'panel' => ['type' => 'string', 'default' => 'latest', 'sanitize_callback' => 'sanitize_key'],
|
||||
'source' => ['type' => 'string', 'default' => 'home', 'sanitize_callback' => 'sanitize_key'],
|
||||
'tab_orderby' => ['type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_key'],
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -479,7 +479,6 @@ trait ScriptsPart1c {
|
||||
'commentPaginationMode' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_comment_pagination_mode() : 'numbered',
|
||||
'homepagePostsPerPage' => function_exists('aksrt_homepage_get_tab_posts_per_page') ? aksrt_homepage_get_tab_posts_per_page() : (int) get_option('posts_per_page'),
|
||||
'homepageDefaultSort' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::homepage_default_sort() : 'modified',
|
||||
'homepageSortAjax' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::homepage_sort_ajax_enabled() : true,
|
||||
'homepageStickyTabs' => class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::homepage_sticky_tabs_enabled() : true,
|
||||
'homePostsListEnabled' => !class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::home_posts_list_enabled(),
|
||||
'homeListSortEnabled' => !class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::home_list_sort_enabled(),
|
||||
|
||||
@@ -175,10 +175,6 @@ class HomeCms {
|
||||
return $settings['home_list1_orderby_option']['lists'][0] ?? 'modified';
|
||||
}
|
||||
|
||||
public static function homepage_sort_ajax_enabled(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function homepage_sticky_tabs_enabled(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -68,13 +68,6 @@ trait HomepageReader {
|
||||
return HomeCms::homepage_default_sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the homepage sortbar should refresh through AJAX.
|
||||
*/
|
||||
public static function homepage_sort_ajax_enabled(): bool {
|
||||
return HomeCms::homepage_sort_ajax_enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the homepage tabs should use sticky/affix behaviour.
|
||||
*/
|
||||
|
||||
+24
-1
@@ -46,6 +46,16 @@ class Center {
|
||||
return preg_match('/^[a-z0-9_-]+$/', (string) $value) === 1;
|
||||
},
|
||||
],
|
||||
'asset' => [
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'sanitize_callback' => 'sanitize_key',
|
||||
],
|
||||
'page' => [
|
||||
'type' => 'integer',
|
||||
'default' => 1,
|
||||
'sanitize_callback' => 'absint',
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
@@ -68,6 +78,17 @@ class Center {
|
||||
return new \WP_Error('aksrt_user_center_context', __('用户中心数据加载失败', 'aksrt'), ['status' => 500]);
|
||||
}
|
||||
|
||||
$asset_request = [];
|
||||
if ($tab === 'credits') {
|
||||
$asset = sanitize_key((string) $request->get_param('asset'));
|
||||
$asset = in_array($asset, ['balance', 'points'], true) ? $asset : '';
|
||||
$asset_request = [
|
||||
'asset' => $asset,
|
||||
'page' => max(1, min(100, (int) $request->get_param('page'))),
|
||||
];
|
||||
$context['asset_request'] = $asset_request;
|
||||
}
|
||||
|
||||
$income_request = [];
|
||||
if ($tab === 'creator') {
|
||||
$income_request = [
|
||||
@@ -104,7 +125,9 @@ class Center {
|
||||
'reward_tab' => $revenue_request['reward_tab'] ?? '',
|
||||
'creator_income' => $income_request,
|
||||
'commission_page' => $revenue_request['commission_page'] ?? 1,
|
||||
'user_page' => $revenue_request['user_page'] ?? 1,
|
||||
'user_page' => $revenue_request['user_page'] ?? 1,
|
||||
'asset' => $asset_request['asset'] ?? '',
|
||||
'asset_page' => $asset_request['page'] ?? 1,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,48 @@ if (!function_exists('aksrt_render_profile_pagination')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_asset_pagination')) {
|
||||
/**
|
||||
* Render user asset pagination without URL state.
|
||||
*/
|
||||
function aksrt_render_asset_pagination(int $total_pages, int $current, string $asset): void {
|
||||
if ($total_pages <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current = max(1, min($total_pages, $current));
|
||||
$pages = array_values(array_unique(array_filter([
|
||||
1,
|
||||
$current - 1,
|
||||
$current,
|
||||
$current + 1,
|
||||
$total_pages,
|
||||
], static fn(int $page): bool => $page >= 1 && $page <= $total_pages)));
|
||||
sort($pages);
|
||||
|
||||
echo '<nav class="profile-pagination" aria-label="' . esc_attr__('分页', 'aksrt') . '">';
|
||||
if ($current > 1) {
|
||||
echo '<button type="button" class="page-numbers prev" data-aksrt-asset-page="' . (int) ($current - 1) . '" data-aksrt-asset-key="' . esc_attr($asset) . '"><span aria-hidden="true">‹</span><span class="screen-reader-text">' . esc_html__('上一页', 'aksrt') . '</span></button>';
|
||||
}
|
||||
$previous = 0;
|
||||
foreach ($pages as $page) {
|
||||
if ($previous > 0 && $page > $previous + 1) {
|
||||
echo '<span class="page-numbers dots">…</span>';
|
||||
}
|
||||
if ($page === $current) {
|
||||
echo '<span class="page-numbers current" aria-current="page">' . (int) $page . '</span>';
|
||||
} else {
|
||||
echo '<button type="button" class="page-numbers" data-aksrt-asset-page="' . (int) $page . '" data-aksrt-asset-key="' . esc_attr($asset) . '">' . (int) $page . '</button>';
|
||||
}
|
||||
$previous = $page;
|
||||
}
|
||||
if ($current < $total_pages) {
|
||||
echo '<button type="button" class="page-numbers next" data-aksrt-asset-page="' . (int) ($current + 1) . '" data-aksrt-asset-key="' . esc_attr($asset) . '"><span aria-hidden="true">›</span><span class="screen-reader-text">' . esc_html__('下一页', 'aksrt') . '</span></button>';
|
||||
}
|
||||
echo '</nav>';
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('aksrt_render_profile_empty')) {
|
||||
/**
|
||||
* 渲染空状态卡片
|
||||
|
||||
@@ -78,16 +78,32 @@ test('user asset submissions send idempotency keys', () => {
|
||||
})
|
||||
|
||||
test('profile asset records show order references and only the changed amount', () => {
|
||||
for (const file of ['profile-credits.php', 'credits-transactions.php']) {
|
||||
for (const file of ['credits-transactions.php', 'credits-wallet-ledger.php']) {
|
||||
const source = fs.readFileSync(path.join(root, 'inc', 'helpers', 'user-center-renderers', file), 'utf8')
|
||||
assert.match(source, /\$record_note\s*=\s*\(string\) \$row\['reason'\] === 'points_exchange'[\s\S]*?\(string\) \$row\['ref_key'\]/)
|
||||
assert.doesNotMatch(source, /uc-transactions__balance|交易 #%d|\$row\['fee_minor'\]|\$row\['ref_id'\]/)
|
||||
}
|
||||
})
|
||||
|
||||
test('asset record tabs and pagination stay in the DOM without URL state', () => {
|
||||
const profile = fs.readFileSync(path.join(root, 'inc', 'helpers', 'user-center-renderers', 'profile-credits.php'), 'utf8')
|
||||
const points = fs.readFileSync(path.join(root, 'inc', 'helpers', 'user-center-renderers', 'credits-transactions.php'), 'utf8')
|
||||
const wallet = fs.readFileSync(path.join(root, 'inc', 'helpers', 'user-center-renderers', 'credits-wallet-ledger.php'), 'utf8')
|
||||
const credits = fs.readFileSync(path.join(root, 'assets', 'js', 'credits.js'), 'utf8')
|
||||
const center = fs.readFileSync(path.join(root, 'src', 'User', 'Center.php'), 'utf8')
|
||||
|
||||
assert.match(profile, /data-aksrt-asset-tab="balance"/)
|
||||
assert.match(profile, /data-aksrt-asset-tab="points"/)
|
||||
assert.match(points, /aksrt_render_asset_pagination\([^;]+, 'points'\)/)
|
||||
assert.match(wallet, /aksrt_render_asset_pagination\([^;]+, 'balance'\)/)
|
||||
assert.doesNotMatch(profile + points + wallet, /\$_GET\[['"](?:wallet_page|credits_page)['"]\]/)
|
||||
assert.match(credits, /data-aksrt-asset-page/)
|
||||
assert.match(credits, /user-center\/panel\/credits\?asset=/)
|
||||
assert.match(center, /'asset'\s*=>\s*\[/)
|
||||
assert.match(center, /\$context\['asset_request'\]/)
|
||||
})
|
||||
test('core asset paths never use floating-point money helpers', () => {
|
||||
const files = [
|
||||
'src/Ledger/AssetAmount.php',
|
||||
'src/Ledger/LedgerCommand.php',
|
||||
'src/Ledger/LedgerService.php',
|
||||
'src/Credits/BalanceService.php',
|
||||
|
||||
@@ -39,13 +39,13 @@ test('native and front-end surfaces expose immutable business numbers', () => {
|
||||
assert.match(read('src/Admin/Native/PayWithdrawals.php'), /提现单号/)
|
||||
assert.match(read('src/Payment/UserOrders.php'), /\$view\['flow_number'\]/)
|
||||
assert.match(read('assets/js/order-center.js'), /\["流水号", order\.flow_number \|\| "—"\]/)
|
||||
assert.match(read('inc/helpers/user-center-renderers/credits-wallet.php'), /withdrawal_number/)
|
||||
assert.match(read('inc/helpers/user-center-renderers/credits-wallet-ledger.php'), /withdrawal_number/)
|
||||
})
|
||||
|
||||
test('balance history renders withdrawal numbers from the committed flow', () => {
|
||||
const query = read('src/Ledger/LedgerQuery.php')
|
||||
const profile = read('inc/helpers/user-center-renderers/profile-credits.php')
|
||||
const wallet = read('inc/helpers/user-center-renderers/credits-wallet.php')
|
||||
const profile = read('inc/helpers/user-center-renderers/credits-wallet-ledger.php')
|
||||
const wallet = read('inc/helpers/user-center-renderers/credits-wallet.php') + read('inc/helpers/user-center-renderers/credits-wallet-ledger.php')
|
||||
assert.match(query, /LEFT JOIN \{\$flow_table\} f ON f\.ledger_transaction_id = t\.id/)
|
||||
assert.match(query, /'withdrawal_number'\s*=>\s*\(string\)/)
|
||||
for (const source of [profile, wallet]) {
|
||||
|
||||
@@ -99,6 +99,29 @@ test('routed modules use one namespaced auto_fun owner and no registry', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('user center navigation initializes once across auto_fun rescans', () => {
|
||||
const source = read('assets/js/routes/user-center.js');
|
||||
const initAt = source.indexOf('function initDashboardNavigation()');
|
||||
const guardAt = source.indexOf('aksrtUserCenterNavigationInitialized', initAt);
|
||||
const initialActivateAt = source.indexOf('activate(initialTab, false)', initAt);
|
||||
|
||||
assert.ok(initAt >= 0);
|
||||
assert.ok(guardAt > initAt && guardAt < initialActivateAt);
|
||||
assert.match(source.slice(initAt, initialActivateAt), /if \(document\.documentElement\.dataset\.aksrtUserCenterNavigationInitialized === 'true'\) return;/);
|
||||
assert.match(source.slice(initAt, initialActivateAt), /document\.documentElement\.dataset\.aksrtUserCenterNavigationInitialized = 'true';/);
|
||||
assert.doesNotMatch(source, /name === 'vip' && !forceLoad\) forceLoad = true/);
|
||||
});
|
||||
|
||||
test('homepage sort refreshes one DOM panel without URL state', () => {
|
||||
const source = read('assets/js/homepage-fixed.js')
|
||||
const homepage = read('inc/helpers/aksrt-homepage.php')
|
||||
const controller = read('src/Admin/GlobalController.php')
|
||||
assert.match(source, /event\.preventDefault\(\)/)
|
||||
assert.match(source, /requestHomepagePanel\(activePanel, \{/)
|
||||
assert.doesNotMatch(source, /home_sort|replaceState|location\.search|data-sort-ajax|homepageSortAjax/)
|
||||
assert.doesNotMatch(homepage, /home_sort|data-sort-ajax|add_query_arg\(['"]home_sort['"]|homepage_sort_ajax_enabled/)
|
||||
assert.doesNotMatch(controller, /'page_url'\s*=>|'source'\s*=>/)
|
||||
})
|
||||
test('HTML fragment injection announces post_ajax before auto_fun', () => {
|
||||
for (const file of ['assets/js/core/pagination.js', 'assets/js/author.js', 'assets/js/credits.js', 'assets/js/routes/user-center.js']) {
|
||||
const source = read(file);
|
||||
|
||||
@@ -157,6 +157,18 @@ test('lazySizes has one auto_fun integration owner and loader boots main once',
|
||||
assert.match(runtime, /var cases = jQuery\('\.vanilla-tilt:not\(\.is-initialized\)'\);[\s\S]*?if \(!cases\.length\)[\s\S]*?tbquire\(\['tilt'\]/);
|
||||
assert.doesNotMatch(pagination, /IntersectionObserver|new Image\(/);
|
||||
assert.doesNotMatch(widgets, /IntersectionObserver/);
|
||||
const dynamicSources = [
|
||||
read('assets/js/order-center.js'),
|
||||
read('assets/js/credits.js'),
|
||||
read('assets/js/page-navs.js'),
|
||||
read('assets/js/pay-vip.js'),
|
||||
loader,
|
||||
].join('\n');
|
||||
const legacyDynamicImageApi = 'aksrt' + 'GetLazyImageAttr';
|
||||
assert.equal(dynamicSources.includes(legacyDynamicImageApi), false);
|
||||
assert.match(read('assets/js/order-center.js'), /<img src="' \+ escapeHtml\(image\)/);
|
||||
assert.match(read('assets/js/page-navs.js'), /<img src="' \+ this\.escHtml\(item\.thumbnail\)/);
|
||||
assert.match(read('assets/js/pay-vip.js'), /document\.createElement\("img"\)/);
|
||||
});
|
||||
|
||||
test('post lists have no second lazy switch and keep legacy fallback thumbnails', () => {
|
||||
|
||||
Reference in New Issue
Block a user