75 lines
5.7 KiB
JavaScript
75 lines
5.7 KiB
JavaScript
/* meowpanel.js — MeowPanel 前端入口(应用入口/路由/启动)。
|
|
* 由 mp_shared.js + mp_pages.js 组合;在两者之后作为经典脚本加载。 */
|
|
(function () {
|
|
'use strict';
|
|
var MP = window.MP;
|
|
const { $, $$, LOG_GROUP_NAME, SPARK_MAX, api, apiDownload, applyTheme, authMode, authRequired, barHtml, bindLogin, bindPwDlg, bindSlider, bindThemeUi, browserMode, confirmDlg, dbPct, dbg, dbgErr, debounce, deciToDb, devStyleLabel, devThemeLabel, doLogin, drawSpark, emptyState, errText, esc, fmtBytes, fmtDb, fmtTime, fmtUptime, hideLogin, homeCard, homeKv, homeUnavailable, initTheme, isAvail, levelMeterHtml, loginErr, modePill, passwordDlg, pct, pushSpark, refreshAuthGate, resetSpark, resolveMode, resolveStyle, saveSetting, setConn, showLogin, slur, sparkPeak, sparkRms, sparklineHtml, sparklinePoints, stat, state, storageDel, storageGet, storageSet, storedMode, storedStyle, toast, toastTimer, updateLevelMeter, volTimer, absFor, appInfo, appStatePill, appUninstall, applyScreenDeltaDom, audioCard, audioCtlHtml, audioFlowHtml, audioPortName, audioRouteLabel, batteryCard, batteryCardBody, bindApps, bindAudio, bindFiles, bindFonts, bindHome, bindLogs, bindNet, bindNotif, bindPin, bindPower, bindProc, bindScreen, bindSettings, bindSystem, breakdownCardBody, btCard, createImgFromBlob, crumbHtml, deviceCard, doDownload, ensureScreenCanvas, escSafeAttr, estimateCardBody, eventsBar, fetchAudioOnce, fetchHomeLevel, fetchHomeSystem, fetchNetConns, fetchNetLog, fetchNetOnce, fetchOverviewOnce, fetchPerfOnce, fetchPowerOnce, fetchProcOnce, fetchScreen, fmtDur, fmtFrames, groupName, handleRemoteGesture, healthCard, importFont, importFontPage, installFromFile, installFromPath, joinRel, loadFonts, loadFontsPage, loadPinStatus, logsCrashCard, mkdirFile, navFiles, netBadge, netBannerErr, netCard, netConnsBody, netDnsBody, netIfaceCards, netPolicyCard, netStateCls, netStatusCards, newestStdout, perfCard, pinEdit, pinEditDlg, powerEventsCard, powerHistoryCard, powerPolicyCard, powerProfileLabel, powerSummaryCard, pubBytesCard, remoteBtn, remotePadHtml, remotePointerDown, remotePointerUp, removeFile, renameFile, renderApps, renderAudio, renderBright, renderFiles, renderFontsPage, renderHome, renderHomeCards, renderLogs, renderLogsFiles, renderNet, renderNotif, renderPerf, renderPerfData, renderPower, renderPowerBody, renderProc, renderProcBody, renderScreen, renderSettings, renderSystem, restartScreenPoll, row, screenTap, seedScreenCanvas, segments, sendKey, sendKeyLabel, sendKeyRepeat, sendTheme, setBrightCtl, setPanelPassword, settingControl, srcPill, stopAudio, stopHome, stopNet, stopPerf, stopPower, stopProc, stopScreenPoll, storageCard, svcStatePill, uploadFiles, viewAppStdout, viewLogsCrashTail, volSteps } = MP;
|
|
|
|
const ROUTES = {
|
|
home: { title: '首页仪表盘', render: renderHome, bind: bindHome },
|
|
perf: { title: '实时性能', render: renderPerf, bind: null },
|
|
bright: { title: '亮度 · 音量', render: renderBright, bind: null },
|
|
audio: { title: '音频状态', render: renderAudio, bind: bindAudio },
|
|
net: { title: '网络管理', render: renderNet, bind: bindNet },
|
|
files: { title: '文件管理', render: renderFiles, bind: bindFiles },
|
|
apps: { title: 'MeowAPPs 管理', render: renderApps, bind: bindApps },
|
|
fonts: { title: '字体管理', render: renderFontsPage, bind: bindFonts },
|
|
settings: { title: '设置镜像', render: renderSettings, bind: bindSettings },
|
|
screen: { title: '屏幕 · 遥控', render: renderScreen, bind: bindScreen },
|
|
system: { title: '系统信息 / 升级', render: renderSystem, bind: bindSystem },
|
|
logs: { title: '系统日志', render: renderLogs, bind: bindLogs },
|
|
notif: { title: '通知中心', render: renderNotif, bind: bindNotif },
|
|
power: { title: '电源 / 功耗', render: renderPower, bind: bindPower },
|
|
proc: { title: '进程 / 服务', render: renderProc, bind: bindProc }
|
|
};
|
|
let started = false;
|
|
|
|
function bindNav() {
|
|
$$('.nav-item').forEach(b => b.addEventListener('click', () => { location.hash = '#/' + b.dataset.route; }));
|
|
$('#menu-btn').addEventListener('click', () => $('#sidebar').classList.toggle('open'));
|
|
}
|
|
|
|
async function init() {
|
|
bindNav();
|
|
bindThemeUi();
|
|
bindSlider();
|
|
bindFiles(); bindApps(); bindFonts(); bindSettings(); bindScreen(); bindSystem(); bindLogs(); bindNotif(); bindNet(); bindHome(); bindProc(); bindPin(); bindAudio();
|
|
bindLogin();
|
|
bindPwDlg();
|
|
// 首次进入:访问级 PIN 鉴权——已登录直接进;未设 PIN(且无旧密码)→ 首次设置流程;已设 → 登录
|
|
let st = null;
|
|
try { st = await api('GET', '/api/auth/status'); } catch (e) { st = null; }
|
|
if (st && st.session) { startApp(); return; }
|
|
if (st && !st.pin_set && !st.legacy) { showLogin('setup'); return; }
|
|
if (st) { showLogin('login'); return; }
|
|
startApp(); // 后端不可达:仍启动(显示离线横幅)
|
|
}
|
|
|
|
function route() {
|
|
if (state.unauth) { showLogin(MP.authMode); return; } // 未认证 → 登录页(保持当前设置/登录态)
|
|
const id = (location.hash || '#/home').replace('#/', '').split('?')[0] || 'home';
|
|
const r = ROUTES[id] || ROUTES.home;
|
|
state.route = id;
|
|
dbg('route →', id);
|
|
stopPerf();
|
|
stopAudio();
|
|
stopNet();
|
|
stopScreenPoll();
|
|
stopHome();
|
|
stopPower();
|
|
stopProc();
|
|
$$('.nav-item').forEach(b => b.classList.toggle('active', b.dataset.route === id));
|
|
$('#page-title').textContent = r.title;
|
|
r.render();
|
|
}
|
|
|
|
function startApp() {
|
|
if (started) { route(); return; }
|
|
started = true;
|
|
initTheme();
|
|
window.addEventListener('hashchange', route);
|
|
route();
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
})(); |