ERP/frontend/js/router.js
2026-05-14 16:55:55 +08:00

121 lines
3.7 KiB
JavaScript
Executable File

const Router = (() => {
const routes = {};
const beforeEachHooks = [];
const afterEachHooks = [];
function register(path, render) {
routes[path] = render;
}
function onBeforeEach(fn) { beforeEachHooks.push(fn); }
function onAfterEach(fn) { afterEachHooks.push(fn); }
async function navigate(path) {
for (const h of beforeEachHooks) await h(path);
const view = document.getElementById('view');
view.classList.add('fade-enter');
const render = routes[path] || routes['/404'];
const html = await render();
view.innerHTML = html;
requestAnimationFrame(() => {
view.classList.add('fade-enter-active');
view.classList.remove('fade-enter');
setTimeout(() => view.classList.remove('fade-enter-active'), 220);
});
for (const h of afterEachHooks) await h(path);
}
async function init() {
window.addEventListener('hashchange', () => {
const path = location.hash.replace('#', '') || '/dashboard';
navigate(path);
highlightActive(path);
updateBreadcrumb(path);
});
const path = location.hash.replace('#', '') || '/dashboard';
navigate(path);
highlightActive(path);
updateBreadcrumb(path);
}
function highlightActive(path) {
document.querySelectorAll('.nav-item, .nav-child').forEach(el => el.classList.remove('active'));
const target = document.querySelector(`[data-route="${routeKey(path)}"]`);
if (target) target.classList.add('active');
}
function routeKey(path) {
return path
.replace('/', '')
.replaceAll('/', '-')
|| 'dashboard';
}
function updateBreadcrumb(path) {
const bc = document.getElementById('breadcrumb');
if (!bc) return; // 元素不存在时直接返回
const parts = path.split('/').filter(Boolean);
let acc = '#';
bc.innerHTML = parts.map((p, i) => {
acc += '/' + p;
const last = i === parts.length - 1;
return `<a href="${acc}" style="color:${last ? 'var(--text)' : 'var(--text-2)'};text-decoration:none">${label(p)}</a>`;
}).join(' / ');
}
function label(key) {
const map = {
dashboard: '仪表盘',
login: '登录',
upload: '上传',
mac: 'MAC与批次',
stats: '良/不良统计',
defects: '不良明细',
repairs: '返修记录',
'repairs-history': '返修历史',
shipments: '发货',
sop: 'SOP',
query: '详细记录查询',
summary: '汇总信息查询',
devices: '设备状态',
environment: '环境参数',
personnel: '人员信息',
qa: '质检报告',
production: '时间记录',
'production-mgmt': '生产管理',
'work-order': '生产工单下发中心',
'plan-mgmt': '计划管理',
'bom': 'BOM物料清单',
'initial-stock': '期初库存',
'purchase-demand': '采购需求清单',
'customer-order': '客户订单',
'reconciliation': '对账单',
export: '导出',
settings: '设置',
finance: '财务管理',
'customer-rec': '客户对账',
'supplier-rec': '供应商对账',
invoice: '发票管理',
outsoucing: '委外管理',
'outsourcing-mgmt': '委外管理',
'outsourcing-orders': '委外工单',
'material-issue': '委外发料',
'finished-goods-receipt': '成品入库',
'wip-stock': '委外在制库存',
collect: '采集',
test: '测试',
meituan: '美团测试',
system: '系统',
'operations-log': '操作日志',
'material-purchase': '物料采购',
'ai-report': 'AI报表',
warehouse: '仓库管理',
borrow: '借出单',
return: '借出还入单'
};
return map[key] || key;
}
return { register, init, onBeforeEach, onAfterEach };
})();