386 lines
15 KiB
JavaScript
386 lines
15 KiB
JavaScript
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>`;
|
||
}
|