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 = ``; else { const input = ``; control = unit ? `