⚡ 初始提交 - FutureOSS v1.0 插件化运行时框架
一切皆为插件的开发者工具运行时框架
🧩 核心特性:
- 插件热插拔 (importlib 动态加载)
- 依赖自动解析 (拓扑排序 + 循环检测)
- 企业级稳定 (熔断/降级/重试/隔离)
- 事件驱动 (发布/订阅事件总线)
- 完整配置 (YAML 配置 + 热重载)
This commit is contained in:
100
website/js/spa.js
Normal file
100
website/js/spa.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 极简软重定向 (SPA Router)
|
||||
* 拦截所有站内链接,使用 fetch + DOM 替换实现无刷新跳转
|
||||
*/
|
||||
(function() {
|
||||
document.addEventListener('click', function(e) {
|
||||
const link = e.target.closest('a');
|
||||
if (!link || link.target === '_blank' || link.href.startsWith('javascript:')) return;
|
||||
|
||||
const url = new URL(link.href);
|
||||
if (url.origin !== window.location.origin) return; // 仅拦截站内
|
||||
|
||||
e.preventDefault();
|
||||
navigate(url.pathname + url.search, true);
|
||||
});
|
||||
|
||||
window.addEventListener('popstate', function(e) {
|
||||
if (e.state && e.state.html) {
|
||||
document.title = e.state.title;
|
||||
document.querySelector('main').innerHTML = e.state.html;
|
||||
initPage();
|
||||
} else {
|
||||
navigate(window.location.pathname + window.location.search, false);
|
||||
}
|
||||
});
|
||||
|
||||
async function navigate(url, push) {
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) { window.location.href = url; return; }
|
||||
|
||||
const html = await res.text();
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
|
||||
// 1. 更新标题
|
||||
document.title = doc.title;
|
||||
|
||||
// 2. 替换 Main 内容
|
||||
const newMain = doc.querySelector('main');
|
||||
const oldMain = document.querySelector('main');
|
||||
if (newMain && oldMain) {
|
||||
oldMain.innerHTML = newMain.innerHTML;
|
||||
}
|
||||
|
||||
// 3. 更新 URL
|
||||
if (push) {
|
||||
history.pushState({
|
||||
url: url,
|
||||
html: newMain ? newMain.innerHTML : '',
|
||||
title: doc.title
|
||||
}, '', url);
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
// 4. 更新 Dock 高亮
|
||||
document.querySelectorAll('#dock .dock-item').forEach(el => {
|
||||
const href = el.getAttribute('href');
|
||||
el.classList.toggle('active', href && url.startsWith(href));
|
||||
});
|
||||
|
||||
// 5. 重新注入脚本/逻辑
|
||||
injectScripts(doc);
|
||||
initPage();
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
function injectScripts(doc) {
|
||||
doc.scripts.forEach(oldScript => {
|
||||
const newScript = document.createElement('script');
|
||||
Array.from(oldScript.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value));
|
||||
if (oldScript.src) {
|
||||
newScript.src = oldScript.src;
|
||||
document.body.appendChild(newScript);
|
||||
} else {
|
||||
newScript.textContent = oldScript.textContent;
|
||||
document.body.appendChild(newScript);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 通用页面初始化入口
|
||||
function initPage() {
|
||||
// 尝试调用社区模块初始化
|
||||
if (typeof initCommunity === 'function') {
|
||||
// 如果脚本已加载,直接调用
|
||||
initCommunity();
|
||||
} else {
|
||||
// 否则动态加载
|
||||
if (location.pathname.includes('/community/') || location.pathname.endsWith('/community/')) {
|
||||
const s = document.createElement('script');
|
||||
s.src = '/community/assets/js/community.js';
|
||||
document.body.appendChild(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user