add:初次提交
This commit is contained in:
233
lj360/lj360.js
Normal file
233
lj360/lj360.js
Normal file
@@ -0,0 +1,233 @@
|
||||
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();
|
||||
});
|
||||
Reference in New Issue
Block a user