guanghulab/channel-router.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

154 lines
4.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ================== 路由配置 ==================
const routes = {
'home': 'views/home.html',
'channel': 'views/channel.html',
'about': 'views/about.html'
};
// 动画时长
const ANIMATION_DURATION = 300;
// 获取当前 hash 中的路径(去掉 #/
function getHashPath() {
const hash = window.location.hash.slice(1) || '/';
const path = hash.startsWith('/') ? hash.slice(1) : hash;
return path || 'home';
}
// ================== 状态管理localStorage ==================
const STORAGE_KEY = 'm-channel-state';
// 保存状态
function saveState(path) {
// 获取已访问模块列表
let visited = JSON.parse(localStorage.getItem(STORAGE_KEY)) || { visitedModules: [] };
if (!visited.visitedModules.includes(path)) {
visited.visitedModules.push(path);
}
visited.lastRoute = path;
localStorage.setItem(STORAGE_KEY, JSON.stringify(visited));
console.log(`[state] save ${path}`, visited);
}
// 恢复状态(返回上次访问的路由,如果没有则返回 'home'
function restoreState() {
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY));
if (saved && saved.lastRoute) {
console.log(`[state] restore ${saved.lastRoute}`, saved);
return saved.lastRoute;
}
return 'home';
}
// ================== 加载视图(带动画+状态保存) ==================
async function loadView(path) {
const routerView = document.getElementById('router-view');
if (!routerView) return;
// 1. 开始离开动画
routerView.classList.add('fade-leave-active', 'fade-leave-to');
// 2. 稍等片刻让离开动画跑起来,再加载新内容
setTimeout(async () => {
routerView.innerHTML = '<div class="loader" style="margin: 2rem auto;"></div>';
try {
const viewFile = routes[path];
if (!viewFile) {
await load404(routerView);
return;
}
const response = await fetch(viewFile);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const html = await response.text();
routerView.innerHTML = html;
} catch (error) {
console.error('加载视图失败:', error);
routerView.innerHTML = `
<div class="error-message">
❌ 加载失败:${error.message}<br>
<small>请检查文件是否存在,或刷新重试</small>
</div>
`;
}
// 3. 移除离开动画类,添加入场动画类
routerView.classList.remove('fade-leave-active', 'fade-leave-to');
routerView.classList.add('fade-enter-active', 'fade-enter-from');
requestAnimationFrame(() => {
routerView.classList.remove('fade-enter-from');
});
setTimeout(() => {
routerView.classList.remove('fade-enter-active');
}, ANIMATION_DURATION);
// 4. 保存状态到 localStorage并打印日志
saveState(path);
// 5. 更新导航高亮和状态栏
updateActiveNav(path);
updateStatusBar(path);
}, 50);
}
// 加载 404 页面
async function load404(container) {
try {
const resp = await fetch('views/404.html');
if (resp.ok) {
container.innerHTML = await resp.text();
} else {
container.innerHTML = '<div class="error-message">⚠️ 404 - 页面未找到</div>';
}
} catch {
container.innerHTML = '<div class="error-message">⚠️ 404 - 页面未找到</div>';
}
}
// 更新导航高亮
function updateActiveNav(path) {
document.querySelectorAll('.nav-link').forEach(link => {
link.classList.remove('active');
const linkPath = link.getAttribute('href').slice(2);
if (linkPath === path) {
link.classList.add('active');
}
});
}
// 更新状态栏
function updateStatusBar(path) {
const statusEl = document.getElementById('current-route');
if (statusEl) {
statusEl.textContent = `当前路由:/${path}`;
}
}
// ================== 初始化:恢复上次访问的路由 ==================
function initRouter() {
// 先尝试从 localStorage 恢复上次路由
const lastRoute = restoreState();
// 如果当前 hash 为空或为默认,就跳转到上次路由
if (!window.location.hash || window.location.hash === '#/home') {
window.location.hash = `#/${lastRoute}`;
} else {
// 否则加载当前 hash 对应的路由
const path = getHashPath();
loadView(path);
}
}
// 监听 hash 变化
window.addEventListener('hashchange', () => {
const path = getHashPath();
loadView(path);
});
// 首次加载
window.addEventListener('DOMContentLoaded', initRouter);