用户公开主页全局采用DOM无刷新加载

This commit is contained in:
kate522 committed 2026-08-23 14:55:24 +08:00
1 parent c3f66e9a14
commit bb9a410ad6
14 files changed
+569 -231

No files matched your search

+23
View File
@@ -504,7 +504,12 @@
gap: 4px;
padding: 4px 12px;
font-size: 14px;
font-family: inherit;
background: none;
border: 0;
color: inherit;
text-decoration: none;
cursor: pointer;
transition: color .2s;
}
@@ -567,3 +572,21 @@
.aksrt-profile-details-modal__dialog dt { color: var(--color-muted, #6b7280); }
.aksrt-profile-details-modal__dialog dd { margin: 0; overflow-wrap: anywhere; }
.aksrt-profile-details-modal__close { position: absolute; top: 12px; right: 12px; width: 32px; height: 32px; border: 0; border-radius: 50%; background: transparent; font-size: 24px; cursor: pointer; }
/* Button-driven panel pagination + fragments (no URL state) */
.aksrt-user-home .profile-pagination button.page-numbers {
font: inherit;
cursor: pointer;
}
.aksrt-user-home .profile-pagination button.page-numbers:hover {
color: var(--color-primary);
border-color: var(--color-primary);
background: var(--color-primary-soft);
}
.aksrt-user-home .dashboard-panel.is-loading {
opacity: .6;
transition: opacity var(--dur-fast, .15s) var(--ease, ease);
pointer-events: none;
}
+77 -21
View File
@@ -1,26 +1,22 @@
/**
* AKSRT Public User Home runtime
*
* Handles public user-home dashboard tabs and cover uploads.
* Loaded on /user/{nicename}/ (author archives 301-redirect here).
* Handles public user-home dashboard tabs, panel fragment loading and cover
* uploads. The URL stays clean (/author/{name}/) — tabs, follow sub-tabs and
* pagination are loaded via the aksrt/v1 user-home panel REST fragment.
*
* @package AKSRT
*/
/* global aksrtAuthorPage */
/* global aksrtAuthorPage, aksrtData, AksrtFrontend, notyf */
(function () {
'use strict';
function updateTabUrl(root, name, defaultTab) {
if (!window.history || typeof window.history.replaceState !== 'function') return;
var url = new URL(window.location.href);
if (!name || name === defaultTab) {
url.searchParams.delete('tab');
} else {
url.searchParams.set('tab', name);
function notifyLoadError() {
if (typeof notyf === 'function') {
notyf('加载失败,请重试', 'danger');
}
window.history.replaceState({}, '', url.toString());
}
function initPublicDashboards() {
@@ -32,6 +28,7 @@
if (!tabs.length) return;
var defaultTab = root.dataset.defaultTab || tabs[0].getAttribute('data-tab') || 'posts';
var userId = parseInt(root.dataset.userId || '0', 10);
var panels = {};
tabs.forEach(function (tab) {
@@ -45,7 +42,7 @@
}
});
function switchTo(name, syncUrl) {
function switchTo(name) {
if (!panels[name]) {
name = defaultTab;
}
@@ -61,24 +58,83 @@
panels[key].panel.setAttribute('hidden', '');
}
});
if (syncUrl) {
updateTabUrl(root, name, defaultTab);
}
}
function resolveInitialTab() {
var url = new URL(window.location.href);
return url.searchParams.get('tab') || defaultTab;
function loadPanelBody(panel, name, page, sub) {
var cfg = window.aksrtData || {};
var restBase = cfg.apiUrl || cfg.restUrl || '';
if (!userId || !restBase) return Promise.reject(new Error('rest-unavailable'));
if (panel._aksrtUhRequest) return panel._aksrtUhRequest;
var followSub = sub || panel.dataset.uhSub || 'followers';
panel.dataset.uhPage = String(page);
panel.dataset.uhSub = followSub;
panel.classList.add('is-loading');
var url = restBase.replace(/\/$/, '') + '/user-home/panel/' + userId + '/' + encodeURIComponent(name)
+ '?page=' + encodeURIComponent(page) + '&sub=' + encodeURIComponent(followSub);
panel._aksrtUhRequest = fetch(url, {
credentials: 'same-origin',
headers: {
'X-WP-Nonce': cfg.restNonce || cfg.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('panel-load-failed');
}
panel.innerHTML = payload.data.html;
if (window.AksrtFrontend && typeof window.AksrtFrontend.rehydrate === 'function') {
window.AksrtFrontend.rehydrate(panel, 'ajax');
}
});
}).finally(function () {
panel._aksrtUhRequest = null;
panel.classList.remove('is-loading');
});
return panel._aksrtUhRequest;
}
function panelNameOf(panel) {
var name = (panel.id || '').replace(/^panel-/, '');
return panels[name] ? name : '';
}
tabs.forEach(function (tab) {
tab.addEventListener('click', function () {
switchTo(tab.getAttribute('data-tab'), true);
switchTo(tab.getAttribute('data-tab'));
});
});
switchTo(resolveInitialTab(), false);
// Delegate sub-tab / pagination clicks so buttons injected by REST
// fragments keep working without rebinding.
root.addEventListener('click', function (event) {
var target = event.target && event.target.closest ? event.target : null;
if (!target) return;
var subBtn = target.closest('[data-uh-sub]');
if (subBtn) {
event.preventDefault();
var followPanel = subBtn.closest('.dashboard-panel');
if (!followPanel) return;
var sub = subBtn.getAttribute('data-uh-sub') === 'following' ? 'following' : 'followers';
loadPanelBody(followPanel, 'follow', 1, sub).catch(notifyLoadError);
return;
}
var pageBtn = target.closest('[data-uh-page]');
if (!pageBtn) return;
event.preventDefault();
var panel = pageBtn.closest('.dashboard-panel');
if (!panel) return;
var name = panelNameOf(panel);
if (!name) return;
var page = Math.max(1, parseInt(pageBtn.getAttribute('data-uh-page') || '1', 10) || 1);
loadPanelBody(panel, name, page, panel.dataset.uhSub || 'followers').catch(notifyLoadError);
});
switchTo(defaultTab);
});
}