207 lines
6.6 KiB
JavaScript
Vendored
207 lines
6.6 KiB
JavaScript
Vendored
/**
|
||
* 营销账户账单页面的服务端局部导航。
|
||
*
|
||
* 链接始终保留完整 href 作为渐进增强回退;普通左键操作只替换当前
|
||
* 工作区并同步 History,避免平台标签、京东账单类型、筛选和分页触发整页刷新。
|
||
*/
|
||
(function () {
|
||
const workspaceSelector = '[data-marketing-account-bills-workspace]';
|
||
const pagePathMarker = '/workspace/billing-transactions/marketing-account-bills';
|
||
let activeRequest = null;
|
||
|
||
function currentWorkspace() {
|
||
return document.querySelector(workspaceSelector);
|
||
}
|
||
|
||
function isSupportedUrl(url) {
|
||
const target = new URL(url, window.location.origin);
|
||
|
||
return target.origin === window.location.origin
|
||
&& target.pathname.indexOf(pagePathMarker) !== -1;
|
||
}
|
||
|
||
function updateHeader(nextDocument) {
|
||
const currentHeader = document.querySelector('[data-page-title-first]');
|
||
const nextHeader = nextDocument.querySelector('[data-page-title-first]');
|
||
|
||
if (currentHeader && nextHeader) {
|
||
currentHeader.innerHTML = nextHeader.innerHTML;
|
||
}
|
||
|
||
if (nextDocument.title) {
|
||
document.title = nextDocument.title;
|
||
}
|
||
}
|
||
|
||
function setLoading(workspace, loading) {
|
||
const status = workspace.querySelector('[data-marketing-account-bills-status]');
|
||
|
||
if (loading) {
|
||
workspace.setAttribute('aria-busy', 'true');
|
||
if (status) {
|
||
status.textContent = '正在加载账单数据';
|
||
}
|
||
} else {
|
||
workspace.removeAttribute('aria-busy');
|
||
}
|
||
}
|
||
|
||
function showError(workspace, url) {
|
||
const error = workspace.querySelector('[data-marketing-account-bills-navigation-error]');
|
||
const status = workspace.querySelector('[data-marketing-account-bills-status]');
|
||
|
||
setLoading(workspace, false);
|
||
|
||
if (status) {
|
||
status.textContent = '账单内容加载失败';
|
||
}
|
||
|
||
if (error) {
|
||
const retry = error.querySelector('[data-marketing-account-bills-retry]');
|
||
error.hidden = false;
|
||
if (retry) {
|
||
retry.href = url;
|
||
}
|
||
}
|
||
}
|
||
|
||
function initialiseInsertedContent(workspace) {
|
||
if (window.Alpine && typeof window.Alpine.initTree === 'function') {
|
||
window.Alpine.initTree(workspace);
|
||
}
|
||
}
|
||
|
||
async function navigate(url, options) {
|
||
const settings = Object.assign({ pushState: true, focus: null }, options || {});
|
||
const workspace = currentWorkspace();
|
||
|
||
if (!workspace || !isSupportedUrl(url)) {
|
||
return false;
|
||
}
|
||
|
||
if (activeRequest) {
|
||
activeRequest.abort();
|
||
}
|
||
|
||
const request = new AbortController();
|
||
activeRequest = request;
|
||
setLoading(workspace, true);
|
||
|
||
try {
|
||
const response = await window.fetch(url, {
|
||
credentials: 'same-origin',
|
||
headers: {
|
||
Accept: 'text/html',
|
||
'X-Requested-With': 'XMLHttpRequest',
|
||
},
|
||
signal: request.signal,
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error(`HTTP ${response.status}`);
|
||
}
|
||
|
||
const html = await response.text();
|
||
const nextDocument = new DOMParser().parseFromString(html, 'text/html');
|
||
const nextWorkspace = nextDocument.querySelector(workspaceSelector);
|
||
|
||
if (!nextWorkspace) {
|
||
throw new Error('目标页面缺少营销账单工作区');
|
||
}
|
||
|
||
const importedWorkspace = document.importNode(nextWorkspace, true);
|
||
workspace.replaceWith(importedWorkspace);
|
||
initialiseInsertedContent(importedWorkspace);
|
||
updateHeader(nextDocument);
|
||
|
||
const target = new URL(url, window.location.origin);
|
||
const relativeUrl = `${target.pathname}${target.search}${target.hash}`;
|
||
|
||
if (settings.pushState && relativeUrl !== `${window.location.pathname}${window.location.search}${window.location.hash}`) {
|
||
window.history.pushState({ marketingAccountBills: true }, '', relativeUrl);
|
||
}
|
||
|
||
if (settings.focus) {
|
||
const focusTarget = importedWorkspace.querySelector(settings.focus);
|
||
if (focusTarget) {
|
||
window.requestAnimationFrame(() => focusTarget.focus({ preventScroll: true }));
|
||
}
|
||
}
|
||
|
||
return true;
|
||
} catch (error) {
|
||
if (error.name !== 'AbortError') {
|
||
showError(workspace, url);
|
||
}
|
||
|
||
return false;
|
||
} finally {
|
||
if (activeRequest === request) {
|
||
activeRequest = null;
|
||
}
|
||
}
|
||
}
|
||
|
||
document.addEventListener('click', (event) => {
|
||
const link = event.target.closest(
|
||
`${workspaceSelector} .business-tab-link, `
|
||
+ `${workspaceSelector} [data-jd-wallet-navigation], `
|
||
+ `${workspaceSelector} .jd-wallet-pagination a`
|
||
);
|
||
|
||
if (!link
|
||
|| link.hasAttribute('data-marketing-account-bills-full-page')
|
||
|| event.button !== 0
|
||
|| event.metaKey
|
||
|| event.ctrlKey
|
||
|| event.shiftKey
|
||
|| event.altKey
|
||
|| link.target === '_blank'
|
||
) {
|
||
return;
|
||
}
|
||
|
||
if (!isSupportedUrl(link.href)) {
|
||
return;
|
||
}
|
||
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
|
||
const focusSelector = link.classList.contains('marketing-bills-subtab')
|
||
? '.marketing-bills-subtab.is-active'
|
||
: '.business-tab-link.is-active';
|
||
|
||
navigate(link.href, { focus: focusSelector });
|
||
}, true);
|
||
|
||
document.addEventListener('submit', (event) => {
|
||
const form = event.target.closest(`${workspaceSelector} [data-jd-wallet-filter]`);
|
||
|
||
if (!form) {
|
||
return;
|
||
}
|
||
|
||
event.preventDefault();
|
||
const target = new URL(form.action, window.location.origin);
|
||
|
||
new FormData(form).forEach((value, key) => {
|
||
const normalized = String(value).trim();
|
||
if (normalized === '') {
|
||
target.searchParams.delete(key);
|
||
} else {
|
||
target.searchParams.set(key, normalized);
|
||
}
|
||
});
|
||
|
||
target.searchParams.delete('page');
|
||
navigate(target.href, { focus: '#jd-filter-store' });
|
||
}, true);
|
||
|
||
window.addEventListener('popstate', () => {
|
||
if (currentWorkspace() && isSupportedUrl(window.location.href)) {
|
||
navigate(window.location.href, { pushState: false });
|
||
}
|
||
});
|
||
}());
|