feat: preserve supplier page state during local navigation
This commit is contained in:
parent
2394dc912a
commit
6b3632fa65
@ -546,6 +546,7 @@
|
||||
'business-page--marketing-account-balance' => $isMarketingAccountBalancePage,
|
||||
])
|
||||
@if ($isMarketingAccountBillsPage) data-marketing-account-bills-workspace @endif
|
||||
@if ($section['slug'] === 'supplier-payables') data-supplier-workspace @endif
|
||||
>
|
||||
@if ($isMarketingAccountBillsPage)
|
||||
<p class="sr-only" role="status" aria-live="polite" data-marketing-account-bills-status></p>
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
@push('body_end')
|
||||
<script>
|
||||
(() => {
|
||||
const selector = '[data-supplier-workspace]';
|
||||
const initial = document.querySelector(selector);
|
||||
if (!initial) return;
|
||||
const cache = new Map();
|
||||
const loaded = new Set([...document.scripts].map(script => script.src));
|
||||
let current = location.href;
|
||||
let pending = false;
|
||||
const heading = document.querySelector('#main-body h1');
|
||||
const remember = () => cache.set(current, {
|
||||
node: document.querySelector(selector),
|
||||
title: document.title,
|
||||
heading: heading ? heading.innerHTML : '',
|
||||
});
|
||||
remember();
|
||||
|
||||
async function navigate(href, push = true) {
|
||||
if (pending) return;
|
||||
const previous = document.querySelector(selector);
|
||||
pending = true;
|
||||
previous.setAttribute('aria-busy', 'true');
|
||||
const status = previous.querySelector('[data-supplier-navigation-status]');
|
||||
status.textContent = '正在加载…';
|
||||
try {
|
||||
let next = cache.get(href);
|
||||
let scripts = [];
|
||||
if (!next) {
|
||||
const response = await fetch(href, {credentials: 'same-origin', headers: {Accept: 'text/html'}});
|
||||
if (!response.ok) throw new Error('HTTP ' + response.status);
|
||||
const doc = new DOMParser().parseFromString(await response.text(), 'text/html');
|
||||
const node = doc.querySelector(selector);
|
||||
if (!node) throw new Error('页面不可用或登录已过期');
|
||||
scripts = [...doc.querySelectorAll('script[src]')].map(s => s.src)
|
||||
.filter(src => new URL(src).origin === location.origin && new URL(src).pathname.startsWith('/public/js/ecommerce-finance/') && !loaded.has(src));
|
||||
next = {node: document.importNode(node, true), title: doc.title, heading: doc.querySelector('#main-body h1')?.innerHTML || ''};
|
||||
}
|
||||
remember();
|
||||
previous.replaceWith(next.node);
|
||||
// Keep each mounted Vue page alive while switching, preserving its filters and pagination.
|
||||
for (const src of scripts) {
|
||||
await new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = () => { loaded.add(src); resolve(); };
|
||||
script.onerror = () => { script.remove(); reject(new Error('页面脚本加载失败')); };
|
||||
document.body.appendChild(script);
|
||||
});
|
||||
}
|
||||
cache.set(href, next);
|
||||
current = href;
|
||||
document.title = next.title;
|
||||
if (heading) heading.innerHTML = next.heading;
|
||||
next.node.querySelector('[data-supplier-navigation-status]').textContent = '';
|
||||
if (push && location.href !== href) history.pushState({}, '', href);
|
||||
next.node.querySelector('.supplier-page-navigation [aria-current]')?.focus({preventScroll: true});
|
||||
} catch (error) {
|
||||
const visible = document.querySelector(selector);
|
||||
if (visible !== previous) visible.replaceWith(previous);
|
||||
status.textContent = '加载失败,原页面已保留。请重新点击目录重试。';
|
||||
} finally {
|
||||
previous.removeAttribute('aria-busy');
|
||||
pending = false;
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', event => {
|
||||
const link = event.target.closest('.supplier-page-navigation a');
|
||||
if (!link || event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey) return;
|
||||
event.preventDefault();
|
||||
navigate(link.href);
|
||||
});
|
||||
window.addEventListener('popstate', () => {
|
||||
if (location.pathname.includes('/workspace/supplier-payables/')) navigate(location.href, false);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@endpush
|
||||
@ -2,6 +2,7 @@
|
||||
$supplierPages = $section['pages'] ?? [];
|
||||
$supplierCurrent = $page['slug'] ?? null;
|
||||
@endphp
|
||||
<p role="status" aria-live="polite" data-supplier-navigation-status></p>
|
||||
<nav class="business-tab-bar supplier-page-navigation" aria-label="供应商应付页面">
|
||||
@foreach ($supplierPages as $supplierPage)
|
||||
@php
|
||||
@ -29,3 +30,4 @@
|
||||
.supplier-page-navigation .business-tab-link { flex:0 0 auto; padding:10px 0; font-size:0.75rem; color:var(--vip-content-muted, #595959); }
|
||||
.supplier-page-navigation .business-tab-link.is-active { color:var(--vip-content-accent-dark, #856632); }
|
||||
</style>
|
||||
@include('business.pages.supplier-payables.local-navigation')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user