224 lines
6.6 KiB
JavaScript
224 lines
6.6 KiB
JavaScript
/**
|
|
* app.js — 应用主控
|
|
* 路由调度、页面生命周期管理、WebSocket 数据分发
|
|
*/
|
|
var App = (function() {
|
|
var currentPage = null;
|
|
var currentHash = '';
|
|
var pages = {};
|
|
|
|
/* ---- 页面注册 ---- */
|
|
function registerPage(hash, page) {
|
|
pages[hash] = page;
|
|
}
|
|
|
|
/* ---- 侧边栏导航 ---- */
|
|
var navLinks = [
|
|
{ hash: '#dashboard', label: '🏠 功能导航' },
|
|
{ hash: '#out', label: '📡 注册 (out)' },
|
|
{ hash: '#in', label: '📊 链接注册 (in)' },
|
|
{ hash: '#yk', label: '⚡ 遥控 (yk)' },
|
|
{ hash: '#ao', label: '🔧 参数 (ao)' },
|
|
{ hash: '#param', label: '⚙ 定值 (param)' },
|
|
{ hash: '#monitor', label: '📋 数据监控' }
|
|
];
|
|
|
|
function buildNav() {
|
|
var nav = document.getElementById('nav-links');
|
|
if (!nav) return;
|
|
var html = '';
|
|
for (var i = 0; i < navLinks.length; i++) {
|
|
var link = navLinks[i];
|
|
html += '<a href="' + link.hash + '" data-hash="' + link.hash + '">' + link.label + '</a>';
|
|
}
|
|
nav.innerHTML = html;
|
|
}
|
|
|
|
function updateNavActive(hash) {
|
|
var links = document.querySelectorAll('#nav-links a');
|
|
for (var i = 0; i < links.length; i++) {
|
|
var linkHash = links[i].getAttribute('data-hash');
|
|
if (linkHash === hash) {
|
|
links[i].classList.add('active');
|
|
} else {
|
|
links[i].classList.remove('active');
|
|
}
|
|
}
|
|
}
|
|
|
|
function showSidebar(show) {
|
|
var sidebar = document.getElementById('nav-sidebar');
|
|
if (sidebar) {
|
|
sidebar.style.display = show ? 'flex' : 'none';
|
|
}
|
|
var main = document.getElementById('main-content');
|
|
if (main) {
|
|
main.style.marginLeft = show ? '220px' : '0';
|
|
}
|
|
}
|
|
|
|
/* ---- WS 状态更新 ---- */
|
|
function updateWsStatus(status) {
|
|
var dot = document.getElementById('nav-status-dot');
|
|
var text = document.getElementById('nav-status-text');
|
|
if (dot) {
|
|
dot.className = 'nav-status-dot ' + status;
|
|
}
|
|
if (text) {
|
|
var map = { connected: '已连接', disconnected: '已断开', connecting: '连接中...' };
|
|
text.textContent = map[status] || status;
|
|
}
|
|
}
|
|
|
|
/* ---- 路由调度 ---- */
|
|
function dispatch(hash) {
|
|
// 未登录 → 跳转到 login
|
|
if (hash !== '#login' && !localStorage.getItem('rtu_logged_in')) {
|
|
window.location.hash = '#login';
|
|
return;
|
|
}
|
|
|
|
// 已登录但访问 login → 跳转到 dashboard
|
|
if (hash === '#login' && localStorage.getItem('rtu_logged_in')) {
|
|
window.location.hash = '#dashboard';
|
|
return;
|
|
}
|
|
|
|
if (hash === currentHash && currentPage) return;
|
|
|
|
var container = document.getElementById('page-container');
|
|
if (!container) return;
|
|
|
|
// 离开旧页面
|
|
if (currentPage && currentPage.onLeave) {
|
|
currentPage.onLeave();
|
|
}
|
|
|
|
// 渲染新页面
|
|
var page = pages[hash];
|
|
if (!page) {
|
|
// 默认跳转到 login
|
|
window.location.hash = '#login';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = '';
|
|
page.render(container);
|
|
|
|
if (page.onEnter) {
|
|
page.onEnter();
|
|
}
|
|
|
|
// 页面进入后立即推送缓存数据(如有)
|
|
var stMap = { '#out': 'out', '#in': 'in', '#yk': 'yk', '#ao': 'ao', '#param': 'param' };
|
|
var st = stMap[hash];
|
|
if (st && page.onData && lastDataCache[st]) {
|
|
page.onData(lastDataCache[st]);
|
|
}
|
|
|
|
currentPage = page;
|
|
currentHash = hash;
|
|
|
|
// 更新导航
|
|
updateNavActive(hash);
|
|
|
|
// 登录页隐藏侧边栏
|
|
if (hash === '#login') {
|
|
showSidebar(false);
|
|
document.body.classList.add('login-page');
|
|
} else {
|
|
showSidebar(true);
|
|
document.body.classList.remove('login-page');
|
|
}
|
|
}
|
|
|
|
/* ---- 数据缓存:保留每种信号类型的最后数据,切换页面时立即恢复 ---- */
|
|
var lastDataCache = {};
|
|
|
|
/* ---- WS 下行数据分发 ---- */
|
|
function onWsMessage(data, raw) {
|
|
if (!data || typeof data !== 'object') return;
|
|
|
|
var signalTypes = ['out', 'in', 'yk', 'ao', 'param'];
|
|
for (var i = 0; i < signalTypes.length; i++) {
|
|
var st = signalTypes[i];
|
|
if (data[st]) {
|
|
lastDataCache[st] = data[st];
|
|
}
|
|
}
|
|
|
|
// 仅向当前页面推送对应类型的数据
|
|
var signalTypeMap = {
|
|
'#out': 'out',
|
|
'#in': 'in',
|
|
'#yk': 'yk',
|
|
'#ao': 'ao',
|
|
'#param': 'param'
|
|
};
|
|
|
|
var signalType = signalTypeMap[currentHash];
|
|
if (signalType && currentPage && currentPage.onData && data[signalType]) {
|
|
currentPage.onData(data[signalType]);
|
|
}
|
|
}
|
|
|
|
/* ---- 初始化 ---- */
|
|
function init() {
|
|
// 注册页面
|
|
registerPage('#login', LoginPage);
|
|
registerPage('#dashboard', DashboardPage);
|
|
registerPage('#out', OutPage);
|
|
registerPage('#in', InPage);
|
|
registerPage('#yk', YkPage);
|
|
registerPage('#ao', AoPage);
|
|
registerPage('#param', ParamPage);
|
|
registerPage('#monitor', MonitorPage);
|
|
|
|
// 构建导航
|
|
buildNav();
|
|
|
|
// 初始化 WebSocket
|
|
var wsUrl = (location.protocol === 'https:' ? 'wss:' : 'ws:') + '//' + location.host + '/ws';
|
|
WsClient.connect(wsUrl);
|
|
|
|
// 监听 WS 状态
|
|
WsClient.onStatusChange(function(status) {
|
|
updateWsStatus(status);
|
|
});
|
|
|
|
// 监听 WS 下行消息
|
|
WsClient.onMessage(function(data, raw) {
|
|
onWsMessage(data, raw);
|
|
});
|
|
|
|
// 路由变化
|
|
window.addEventListener('hashchange', function() {
|
|
var hash = window.location.hash || '#login';
|
|
dispatch(hash);
|
|
});
|
|
|
|
// 登出按钮
|
|
var logoutBtn = document.getElementById('nav-logout');
|
|
if (logoutBtn) {
|
|
logoutBtn.onclick = function() {
|
|
localStorage.removeItem('rtu_logged_in');
|
|
window.location.hash = '#login';
|
|
};
|
|
}
|
|
|
|
// 首次加载
|
|
var initHash = window.location.hash || '#login';
|
|
dispatch(initHash);
|
|
}
|
|
|
|
return {
|
|
init: init,
|
|
dispatch: dispatch
|
|
};
|
|
})();
|
|
|
|
// 页面加载完成后启动
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
App.init();
|
|
});
|