Files
cockpit_avm/lj360/lj360.js
2026-04-21 15:38:57 +08:00

233 lines
8.4 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 SCRIPT = "/home/ztl/LJ360/bash/video_tool.sh";
const SERVICE = "lj360_camera";
const LOG_FILE = "/home/ztl/LJ360/lj360_camera_keepalive.log";
const WEBPY = "/home/ztl/LJ360/web.py";
// DOM 元素
let statusIcon, statusText, outputBox, autostartSwitch;
function initElements() {
statusIcon = document.getElementById("status-icon");
statusText = document.getElementById("status-text");
outputBox = document.getElementById("output");
autostartSwitch = document.getElementById("autostart-switch");
}
function setOutput(text) {
if (outputBox) {
outputBox.textContent = text;
outputBox.scrollTop = outputBox.scrollHeight;
}
}
function setStatus(text, isActive) {
if (statusText) {
statusText.textContent = text;
}
const panel = document.getElementById("status-panel");
if (panel) {
// 移除现有状态类
panel.classList.remove("status-success", "status-danger", "status-warning");
if (isActive === true) {
panel.classList.add("status-success");
} else if (isActive === false) {
panel.classList.add("status-danger");
} else if (isActive === undefined) {
panel.classList.add("status-warning");
}
}
if (statusIcon) {
if (isActive === true) {
statusIcon.innerHTML = '<i class="fa fa-check-circle" style="color:#3f9c35"></i>';
} else if (isActive === false) {
statusIcon.innerHTML = '<i class="fa fa-exclamation-circle" style="color:#c00"></i>';
} else {
statusIcon.innerHTML = '<i class="fa fa-refresh fa-spin"></i>';
}
}
}
function runCommand(args, callback) {
const proc = cockpit.spawn(args, { superuser: "require", err: "out" });
let output = "";
proc.stream(data => { output += data; });
proc.then(() => callback(output, null));
proc.catch(err => callback(output, err));
}
// 获取服务状态和开机自启状态
function refreshStatus() {
setStatus("正在获取服务状态...", undefined);
setOutput("⏳ 正在刷新状态...");
// 获取服务运行状态
runCommand(["systemctl", "is-active", SERVICE + ".service"], (outActive, errActive) => {
const isRunning = (outActive.trim() === "active");
// 获取开机自启状态
runCommand(["systemctl", "is-enabled", SERVICE + ".service"], (outEnabled, errEnabled) => {
let isEnabled = false;
if (!errEnabled) {
const enabledOut = outEnabled.trim();
isEnabled = (enabledOut === "enabled" || enabledOut === "static");
}
// 更新开关状态不触发change事件
if (autostartSwitch) {
autostartSwitch.checked = isEnabled;
}
// 更新状态文本
if (isRunning) {
setStatus("服务正在运行" + (isEnabled ? " (开机自启已启用)" : " (开机自启未启用)"), true);
} else {
setStatus("服务未运行" + (isEnabled ? " (开机自启已启用但未运行)" : " (开机自启未启用)"), false);
}
// 获取详细状态输出
runCommand(["systemctl", "status", SERVICE + ".service", "--no-pager", "-l"], (outDetail) => {
setOutput(outDetail || "无状态信息");
});
});
});
}
// 设置开机自启(通过开关)
function setAutostart(enabled) {
setOutput("⏳ " + (enabled ? "正在启用开机自启..." : "正在禁用开机自启..."));
const action = enabled ? "enable_autostart" : "disable_autostart";
runCommand(["bash", SCRIPT, action], (out, err) => {
if (err) {
setOutput("❌ 错误: " + (err.message || err) + "\n" + (out || ""));
// 恢复开关状态
setTimeout(() => refreshStatus(), 500);
} else {
setOutput((enabled ? "✅ 开机自启已启用" : "✅ 开机自启已禁用") + "\n" + (out || ""));
setTimeout(() => refreshStatus(), 300);
}
});
}
// 启动服务
function startService() {
setOutput("⏳ 正在启动服务...");
runCommand(["systemctl", "start", SERVICE + ".service"], (out, err) => {
if (err) {
setOutput("❌ 启动失败: " + (err.message || err) + "\n" + out);
} else {
setOutput("✅ 服务已启动\n" + out);
}
setTimeout(() => refreshStatus(), 500);
});
}
// 停止服务
function stopService() {
setOutput("⏳ 正在停止服务...");
runCommand(["systemctl", "stop", SERVICE + ".service"], (out, err) => {
if (err) {
setOutput("❌ 停止失败: " + (err.message || err) + "\n" + out);
} else {
setOutput("✅ 服务已停止\n" + out);
}
setTimeout(() => refreshStatus(), 500);
});
}
// 重启服务
function restartService() {
setOutput("⏳ 正在重启服务...");
runCommand(["systemctl", "restart", SERVICE + ".service"], (out, err) => {
if (err) {
setOutput("❌ 重启失败: " + (err.message || err) + "\n" + out);
} else {
setOutput("✅ 服务已重启\n" + out);
}
setTimeout(() => refreshStatus(), 800);
});
}
// 查看日志
function viewLog() {
setOutput("⏳ 读取日志文件...");
runCommand(["tail", "-n", "80", LOG_FILE], (out, err) => {
if (err) {
setOutput("❌ 无法读取日志: " + (err.message || err) + "\n尝试查看服务日志...");
// 备用:查看 journalctl
runCommand(["journalctl", "-u", SERVICE + ".service", "-n", "50", "--no-pager"], (out2, err2) => {
if (err2) {
setOutput("📭 日志为空或无法读取\n" + (out2 || ""));
} else {
setOutput("📋 系统日志 (journalctl):\n" + (out2 || "无日志"));
}
});
} else {
setOutput("📋 服务日志 (最近80行):\n" + (out || "日志为空"));
}
});
}
// 单独启动 web.py
function startWebPy() {
setOutput("⏳ 正在启动 web.py...");
runCommand([
"bash", "-c",
"export DISPLAY=:0 && cd /home/ztl/LJ360 && sudo -u ztl python3 /home/ztl/LJ360/web.py >> /home/ztl/LJ360/web.log 2>&1 &"
], (out, err) => {
if (err) {
setOutput("❌ 启动 web.py 失败: " + (err.message || err));
} else {
setOutput("✅ web.py 已在后台启动\n可通过 'ps aux | grep web.py' 查看进程");
}
});
}
// 停止 web.py
function stopWebPy() {
setOutput("⏳ 正在关闭 web.py...");
runCommand(["bash", "-c", "pkill -f /home/ztl/LJ360/web.py"], (out, err) => {
if (err) {
// pkill 没有找到进程也会返回错误,这是正常的
if (err.message && err.message.includes("exit code 1")) {
setOutput("⚠️ 未找到运行中的 web.py 进程");
} else {
setOutput("❌ 关闭失败: " + (err.message || err));
}
} else {
setOutput("✅ web.py 已关闭");
}
});
}
// 事件绑定
function bindEvents() {
const btnStart = document.getElementById("btn-start");
const btnStop = document.getElementById("btn-stop");
const btnRestart = document.getElementById("btn-restart");
const btnStatus = document.getElementById("btn-status");
const btnLog = document.getElementById("btn-log");
const btnPyon = document.getElementById("btn-pyon");
const btnPyoff = document.getElementById("btn-pyoff");
if (btnStart) btnStart.addEventListener("click", startService);
if (btnStop) btnStop.addEventListener("click", stopService);
if (btnRestart) btnRestart.addEventListener("click", restartService);
if (btnStatus) btnStatus.addEventListener("click", refreshStatus);
if (btnLog) btnLog.addEventListener("click", viewLog);
if (btnPyon) btnPyon.addEventListener("click", startWebPy);
if (btnPyoff) btnPyoff.addEventListener("click", stopWebPy);
// 开关事件:开机自启变更
if (autostartSwitch) {
autostartSwitch.addEventListener("change", function(e) {
setAutostart(e.target.checked);
});
}
}
// 页面初始化
document.addEventListener("DOMContentLoaded", function() {
initElements();
bindEvents();
refreshStatus();
});