RTU/test/web_root/js/app.js

288 lines
9.2 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: '#datacenter', label: '📊 数据中心' },
{ hash: '#plc_debug', label: '🔌 PLC调试' },
{ hash: '#plc_config', label: '🧮 PLC逻辑配置' },
{ hash: '#monitor', label: '📋 数据监控' },
{ hash: '#terminal', 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', '#datacenter': 'dc_data', '#plc_debug': 'out', '#terminal': 'cmd_list' };
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 (raw instanceof ArrayBuffer) {
var decoder = new TextDecoder('utf-8');
var text = decoder.decode(raw);
try {
var parsed = JSON.parse(text);
if (parsed && parsed.type === 'dc_data') {
var cache = lastDataCache['dc_data'] || {};
if (parsed.out) cache.out = parsed.out;
if (parsed.in) cache.in = parsed.in;
if (parsed.yk) cache.yk = parsed.yk;
if (parsed.ao) cache.ao = parsed.ao;
if (parsed.param) cache.param = parsed.param;
lastDataCache['dc_data'] = cache;
if (currentHash === '#datacenter' && currentPage && currentPage.onData) {
currentPage.onData(parsed);
}
return;
}
} catch(e) {}
if (currentPage && currentPage.onBinary) {
currentPage.onBinary(raw);
}
return;
}
if (!data || typeof data !== 'object') return;
if (data.type === 'cmd_rsp' && currentPage && currentPage.onData) {
currentPage.onData(data.data);
return;
}
if (data.type === 'cmd_list') {
lastDataCache['cmd_list'] = data;
if (currentHash === '#terminal' && currentPage && currentPage.onData) {
currentPage.onData(data);
}
return;
}
if (data.type === 'dc_data') {
lastDataCache['dc_data'] = data;
if (currentPage && currentPage.onData && currentHash === '#datacenter') {
currentPage.onData(data);
}
return;
}
// file_content / file_saved — 转发给当前页面
if ((data.type === 'file_content' || data.type === 'file_saved') && currentPage && currentPage.onData) {
currentPage.onData(data);
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',
'#plc_debug': 'out'
};
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('#datacenter', DatacenterPage);
registerPage('#plc_debug', PlcDebugPage);
registerPage('#plc_config', PlcConfigPage);
registerPage('#monitor', MonitorPage);
registerPage('#terminal', TerminalPage);
// 构建导航
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,
getSignalData: function(type) {
return lastDataCache[type];
}
};
})();
// 页面加载完成后启动
document.addEventListener('DOMContentLoaded', function() {
App.init();
});