Files

386 lines
15 KiB
JavaScript
Raw Permalink Normal View History

import { state as appState } from "/assets/js/state.js";
import { tr } from "/assets/js/i18n.js";
import { esc } from "/assets/js/shared.js";
export const sectionMeta = {
plugins: ["硬件插件", "独立安装,按实际能力提供风扇、屏幕或灯光控制"],
hardware: ["硬件插件", "可选 Yahboom 散热板;未安装时保持关闭"],
device: ["设备标识", "自定义本机显示名称和稳定标识"],
hosts: ["机器列表", "登记需要聚合监控的其他节点"],
led: ["灯光设置", "正常灯效与告警颜色"],
alerts: ["告警阈值", "处理器、内存、温度、磁盘和 Wi-Fi"],
fan: ["风扇温控", "温度档位与降档回差"],
timing: ["刷新周期", "传感器、屏幕、网络和健康检查"],
display: ["屏幕布局", "OLED 四行文字位置"],
dark_mode: ["板载指示灯", "树莓派电源灯与活动灯"],
services: ["服务监控", "监控 systemd 服务"],
processes: ["进程监控", "监控普通进程关键字"],
api: ["API 设置", "API 开关、监听地址、端口和日志数量"],
bulk_sync: ["批量同步", "从当前配置机器复制所选配置项到目标机器"],
};
export const labels = {
"api.enabled": "启用远程管理 API",
"hardware.cooling_hat_enabled": "启用散热板(OLED、风扇、RGB)",
"led.alert_mode": "告警灯效模式",
"led.custom_min_hold_ms": "自定义闪烁最小保持时间",
"led.normal_mode": "正常状态灯效",
"led.normal_r": "红色通道",
"led.normal_g": "绿色通道",
"led.normal_b": "蓝色通道",
"led.normal_flash_on_ms": "亮灯时间",
"led.normal_flash_off_ms": "灭灯时间",
"led.normal_effect_speed": "内置效果速度",
"led.normal_effect_color": "内置效果颜色",
"led.warning_flash_on_ms": "普通告警亮灯",
"led.warning_flash_off_ms": "普通告警灭灯",
"led.critical_flash_on_ms": "严重告警亮灯",
"led.critical_flash_off_ms": "严重告警灭灯",
"led.emergency_flash_on_ms": "紧急告警亮灯",
"led.emergency_flash_off_ms": "紧急告警灭灯",
"led.write_delay_ms": "RGB 寄存器写入间隔",
"alerts.cpu_high": "处理器高负载阈值",
"alerts.cpu_recover": "处理器恢复阈值",
"alerts.cpu_high_seconds": "处理器持续时间",
"alerts.memory_high": "内存高占用阈值",
"alerts.memory_recover": "内存恢复阈值",
"alerts.memory_high_seconds": "内存持续时间",
"alerts.temp_high": "高温告警阈值",
"alerts.temp_critical": "严重高温阈值",
"alerts.disk_high": "磁盘高占用阈值",
"alerts.disk_critical": "磁盘严重阈值",
"alerts.wifi_weak": "Wi-Fi 弱信号阈值",
"alerts.wifi_recover": "Wi-Fi 恢复阈值",
"alerts.wifi_weak_seconds": "弱信号持续时间",
"alerts.ethernet_min_speed_mbps": "有线最低协商速率",
"alerts.ethernet_speed_seconds": "有线降速持续时间",
"fan.start": "风扇启动温度",
"fan.level2": "二档起始温度",
"fan.level3": "三档起始温度",
"fan.level4": "四档起始温度",
"fan.max": "全速起始温度",
"fan.hysteresis": "降档温度回差",
"timing.sensor_interval": "传感器采样周期",
"timing.oled_refresh_interval": "OLED 刷新周期",
"timing.page_interval": "OLED 页面轮播周期",
"timing.network_interval": "网络检查周期",
"timing.service_interval": "服务检查周期",
"timing.health_interval": "健康检查周期",
"display.row1_y": "第一行纵坐标",
"display.row2_y": "第二行纵坐标",
"display.row3_y": "第三行纵坐标",
"display.row4_y": "第四行纵坐标",
"dark_mode.pi_pwr_led": "树莓派电源灯",
"dark_mode.pi_act_led": "树莓派活动灯",
"api.bind": "监听地址",
"api.port": "监听端口",
"api.log_limit": "默认日志条数",
"device.identifier": "机器标识",
"device.name": "显示名称",
};
["cpu", "power", "memory", "storage", "network", "service"].forEach((g) =>
["r", "g", "b"].forEach(
(c) =>
(labels[`led.${g}_${c}`] = `${{ r: "红", g: "绿", b: "蓝" }[c]}色通道`),
),
);
export const hints = {
"hardware.cooling_hat_enabled":
"默认关闭;启用前运行安装器 --enable-cooling-hat 安装依赖。",
"led.alert_mode": "推荐内置呼吸;自定义闪烁仍可能异色或延迟。",
"led.custom_min_hold_ms": "范围 1500–60000 毫秒。实际亮灭时间不会低于此值。",
"led.normal_mode": "仅在没有当前告警时生效;告警会立即抢占。",
"led.normal_r": "范围 0–255。",
"led.normal_g": "范围 0–255。",
"led.normal_b": "范围 0–255。",
"led.normal_flash_on_ms": "范围 50–60000 毫秒。",
"led.normal_flash_off_ms": "范围 50–60000 毫秒。",
"led.normal_effect_speed": "MCU 内置速度档位。",
"led.normal_effect_color": "仅流水灯和呼吸灯使用。",
"led.write_delay_ms": "MCU 内置灯效参数写入间隔,通常保持 10 毫秒。",
"alerts.wifi_weak": "单位 dBm,数值越接近 0 信号越强。",
"alerts.wifi_recover": "单位 dBm,应高于弱信号阈值。",
"alerts.ethernet_min_speed_mbps":
"低于此协商速率并持续设定时间后告警;设为 0 关闭。",
"alerts.ethernet_speed_seconds": "过滤网线插拔或协商过程中的瞬时降速。",
"fan.hysteresis": "避免临界温度附近频繁切换档位。",
"api.bind": "0.0.0.0 允许局域网访问;127.0.0.1 仅本机。",
"api.port": "范围 1–65535;保存后 API 自动重启。",
"dark_mode.pi_pwr_led": "选择“关闭”时由程序熄灭板载灯。",
"dark_mode.pi_act_led": "选择“关闭”时由程序熄灭板载灯。",
};
["normal", "cpu", "power", "memory", "storage", "network", "service"].forEach(
(g) =>
["r", "g", "b"].forEach((c) => (hints[`led.${g}_${c}`] = "范围 0–255。")),
);
export const options = {
"api.enabled": [
["false", "关闭"],
["true", "开启"],
],
"hardware.cooling_hat_enabled": [
["false", "关闭"],
["true", "启用"],
],
"led.alert_mode": [
["breathe", "内置呼吸(推荐)"],
["flash", "自定义颜色闪烁(实验性)"],
],
"led.normal_mode": [
["off", "全灭"],
["solid", "自定义颜色常亮"],
["flash", "自定义颜色闪烁"],
["flow", "流水灯"],
["breathe", "呼吸灯"],
["marquee", "跑马灯"],
["rainbow", "彩虹灯"],
["colorful", "炫彩灯"],
],
"led.normal_effect_speed": [
["1", "慢速"],
["2", "中速"],
["3", "快速"],
],
"led.normal_effect_color": [
["red", "红色"],
["green", "绿色"],
["blue", "蓝色"],
["yellow", "黄色"],
["purple", "紫色"],
["cyan", "青色"],
["white", "白色"],
],
"dark_mode.pi_pwr_led": [
["off", "关闭"],
["on", "不干预"],
],
"dark_mode.pi_act_led": [
["off", "关闭"],
["on", "不干预"],
],
};
export const numberRules = {
"led.custom_min_hold_ms": [1500, 60000, 100],
"led.normal_r": [0, 255, 1],
"led.normal_g": [0, 255, 1],
"led.normal_b": [0, 255, 1],
"led.normal_flash_on_ms": [50, 60000, 10],
"led.normal_flash_off_ms": [50, 60000, 10],
"led.warning_flash_on_ms": [50, 60000, 10],
"led.warning_flash_off_ms": [50, 60000, 10],
"led.critical_flash_on_ms": [50, 60000, 10],
"led.critical_flash_off_ms": [50, 60000, 10],
"led.emergency_flash_on_ms": [50, 60000, 10],
"led.emergency_flash_off_ms": [50, 60000, 10],
"led.write_delay_ms": [1, 1000, 1],
"alerts.cpu_high": [0, 100, 1],
"alerts.cpu_recover": [0, 100, 1],
"alerts.cpu_high_seconds": [1, 86400, 1],
"alerts.memory_high": [0, 100, 1],
"alerts.memory_recover": [0, 100, 1],
"alerts.memory_high_seconds": [1, 86400, 1],
"alerts.temp_high": [0, 120, 0.1],
"alerts.temp_critical": [0, 120, 0.1],
"alerts.disk_high": [0, 100, 1],
"alerts.disk_critical": [0, 100, 1],
"alerts.wifi_weak": [-120, 0, 1],
"alerts.wifi_recover": [-120, 0, 1],
"alerts.wifi_weak_seconds": [1, 86400, 1],
"alerts.ethernet_min_speed_mbps": [0, 100000, 1],
"alerts.ethernet_speed_seconds": [1, 86400, 1],
"fan.start": [0, 100, 0.1],
"fan.level2": [0, 100, 0.1],
"fan.level3": [0, 100, 0.1],
"fan.level4": [0, 100, 0.1],
"fan.max": [0, 100, 0.1],
"fan.hysteresis": [0, 20, 0.1],
"timing.sensor_interval": [0.2, 3600, 0.1],
"timing.oled_refresh_interval": [0.2, 3600, 0.1],
"timing.page_interval": [1, 3600, 0.1],
"timing.network_interval": [1, 3600, 0.1],
"timing.service_interval": [1, 3600, 0.1],
"timing.health_interval": [0.2, 3600, 0.1],
"display.row1_y": [0, 31, 1],
"display.row2_y": [0, 31, 1],
"display.row3_y": [0, 31, 1],
"display.row4_y": [0, 31, 1],
"api.port": [1, 65535, 1],
"api.log_limit": [1, 1000, 1],
};
["cpu", "power", "memory", "storage", "network", "service"].forEach((g) =>
["r", "g", "b"].forEach((c) => (numberRules[`led.${g}_${c}`] = [0, 255, 1])),
);
export const units = {
"led.custom_min_hold_ms": "毫秒",
"led.normal_flash_on_ms": "毫秒",
"led.normal_flash_off_ms": "毫秒",
"led.warning_flash_on_ms": "毫秒",
"led.warning_flash_off_ms": "毫秒",
"led.critical_flash_on_ms": "毫秒",
"led.critical_flash_off_ms": "毫秒",
"led.emergency_flash_on_ms": "毫秒",
"led.emergency_flash_off_ms": "毫秒",
"led.write_delay_ms": "毫秒",
"alerts.cpu_high": "%",
"alerts.cpu_recover": "%",
"alerts.cpu_high_seconds": "秒",
"alerts.memory_high": "%",
"alerts.memory_recover": "%",
"alerts.memory_high_seconds": "秒",
"alerts.temp_high": "°C",
"alerts.temp_critical": "°C",
"alerts.disk_high": "%",
"alerts.disk_critical": "%",
"alerts.wifi_weak": "dBm",
"alerts.wifi_recover": "dBm",
"alerts.wifi_weak_seconds": "秒",
"alerts.ethernet_min_speed_mbps": "Mbps",
"alerts.ethernet_speed_seconds": "秒",
"fan.start": "°C",
"fan.level2": "°C",
"fan.level3": "°C",
"fan.level4": "°C",
"fan.max": "°C",
"fan.hysteresis": "°C",
"timing.sensor_interval": "秒",
"timing.oled_refresh_interval": "秒",
"timing.page_interval": "秒",
"timing.network_interval": "秒",
"timing.service_interval": "秒",
"timing.health_interval": "秒",
"display.row1_y": "像素",
"display.row2_y": "像素",
"display.row3_y": "像素",
"display.row4_y": "像素",
"api.port": "端口",
"api.log_limit": "条",
};
export const sectionOrder = [
"device",
"plugins",
"alerts",
"timing",
"dark_mode",
"services",
"processes",
"api",
],
bulkSections = sectionOrder.filter(
(s) => !["device", "hosts", "plugins"].includes(s),
),
alertColorGroups = [
["cpu", "处理器、温度与散热"],
["power", "供电与欠压"],
["memory", "内存"],
["storage", "存储"],
["network", "网络与 Wi-Fi"],
["service", "服务与进程"],
];
export const ownerNames = {
NORMAL_HOME: "正常主页",
ROOT_READONLY: "根文件系统只读",
TEMP_CRITICAL: "处理器温度严重",
POWER_UNDERVOLT: "供电欠压",
THROTTLED: "处理器降频",
FREQ_CAPPED: "频率受限",
NETWORK_DOWN: "网络断开",
INTERNET_DOWN: "互联网断开",
SERVICE_DOWN: "服务停止",
PROCESS_DOWN: "进程停止",
DISK_CRITICAL: "磁盘严重不足",
TEMP_HIGH: "处理器温度偏高",
CPU_HIGH: "处理器负载过高",
MEMORY_HIGH: "内存占用过高",
DISK_HIGH: "磁盘空间不足",
WIFI_WEAK: "Wi-Fi 信号弱",
ETHERNET_SPEED_LOW: "有线连接速率降低",
},
rgbNames = {
DISABLED: "未启用",
OFF: "全灭",
NORMAL_SOLID: "正常 · 自定义常亮",
NORMAL_FLASH: "正常 · 自定义闪烁",
NORMAL_FLOW: "正常 · 流水灯",
NORMAL_BREATHE: "正常 · 呼吸灯",
NORMAL_MARQUEE: "正常 · 跑马灯",
NORMAL_RAINBOW: "正常 · 彩虹灯",
NORMAL_COLORFUL: "正常 · 炫彩灯",
},
eventNames = {
HARDWARE_ENABLED: "硬件插件已启用",
HARDWARE_DISABLED: "硬件插件已关闭",
HARDWARE_UNAVAILABLE: "硬件插件不可用",
FAN_LEVEL: "风扇档位变化",
START: "程序启动",
STOP: "程序停止",
ALERT_ACTIVE: "告警出现",
ALERT_RECOVERED: "告警恢复",
DISPLAY_OWNER: "显示对象切换",
INTERNET_DOWN: "互联网断开",
INTERNET_RECOVERED: "互联网恢复",
NET_SWITCH: "网络接口切换",
ETHERNET_SPEED_LOW: "有线连接速率降低",
ETHERNET_SPEED_RECOVERED: "有线连接速率恢复",
NETWORK_DOWN: "网络断开",
NETWORK_RECOVERED: "网络恢复",
POWER_LOW: "供电欠压",
POWER_RECOVERED: "供电恢复",
POWER_HISTORY: "历史电源状态",
HISTORY_FLAG: "历史电源状态",
ROOT_READONLY: "根文件系统只读",
RGB_ERROR: "RGB 控制错误",
RGB_MODE: "RGB 模式切换",
RGB_RECOVERED: "RGB 控制恢复",
SYSTEM: "系统事件",
WATCH_DOWN: "监控对象停止",
WATCH_RECOVERED: "监控对象恢复",
};
export function ownerName(id) {
const [type, suffix] = String(id || "").split("|", 2),
name = ownerNames[type] || type;
return tr(name) + (suffix ? ` · ${suffix}` : "");
}
export function rgbName(mode) {
if (rgbNames[mode]) return tr(rgbNames[mode]);
const p = String(mode || "").split("_"),
groups = {
CPU: "处理器",
POWER: "供电",
MEMORY: "内存",
STORAGE: "存储",
NETWORK: "网络",
SERVICE: "服务",
},
levels = {
WARNING: "普通告警",
CRITICAL: "严重告警",
EMERGENCY: "紧急告警",
};
return `${tr(groups[p[0]] || p[0])} · ${tr(levels[p[1]] || p[1])}${p[2] === "BREATHE" ? (appState.LANG === "zh" ? "呼吸" : " breathing") : appState.LANG === "zh" ? "闪烁" : " flash"}`;
}
export function eventName(id) {
return tr(
eventNames[id] ||
(appState.LANG === "zh"
? `未知事件(${id})`
: String(id).toLowerCase().replaceAll("_", " ")),
);
}
export function field(section, key, value, extra = "") {
const id = `${section}.${key}`,
opts = options[id],
rule = numberRules[id],
label = tr(labels[id] || key),
help = tr(hints[id] || ""),
unit = tr(units[id] || "");
let control;
if (opts)
control = `<select data-section="${esc(section)}" data-key="${esc(key)}">${opts.map(([v, l]) => `<option value="${v}" ${String(value) === v ? "selected" : ""}>${tr(l)}</option>`).join("")}</select>`;
else {
const input = `<input ${rule ? 'type="number"' : ""} ${rule ? `min="${rule[0]}" max="${rule[1]}" step="${rule[2]}"` : ""} data-section="${esc(section)}" data-key="${esc(key)}" value="${esc(value)}">`;
control = unit
? `<div class="input-unit">${input}<span class="unit">${unit}</span></div>`
: input;
}
return `<div class="field ${extra}"><label>${esc(label)}${control}</label>${help ? `<div class="hint">${esc(help)}</div>` : ""}</div>`;
}