This commit is contained in:
biss committed 2026-09-08 20:01:03 +08:00
commit 645c461d2a
12 files changed
+886

No files matched your search

@@ -0,0 +1,150 @@
'use strict';
'require view';
'require form';
'require fs';
'require ui';
'require uci';
function validateTime(section_id, value) {
if (!/^\d{2}:\d{2}$/.test(value))
return _('时间格式必须为 HH:MM,例如 23:00');
var parts = value.split(':');
var hour = Number(parts[0]);
var minute = Number(parts[1]);
if (hour < 0 || hour > 23 || minute < 0 || minute > 59)
return _('请输入有效时间,例如 07:30');
return true;
}
function showTimedNotification(message, style, timeout) {
var content = E('p', {}, message);
/*
* OpenWrt 25.12 LuCI provides addTimeLimitedNotification().
* Keep a fallback for older/custom FriendlyWrt builds.
*/
if (typeof ui.addTimeLimitedNotification === 'function')
return ui.addTimeLimitedNotification(null, content, timeout, style);
var node = ui.addNotification(null, content, style);
window.setTimeout(function() {
if (!node || !node.parentNode)
return;
node.classList.add('fade-out');
node.classList.remove('fade-in');
window.setTimeout(function() {
if (node.parentNode)
node.parentNode.removeChild(node);
}, 300);
}, timeout);
return node;
}
function runControl(action, successMessage) {
return fs.exec('/usr/bin/led-control', [ action ]).then(function(res) {
if (!res || res.code !== 0) {
var message = (res && res.stderr) ? res.stderr.trim() : _('未知错误');
throw new Error(message || _('命令执行失败'));
}
showTimedNotification(successMessage, 'info', 3000);
}).catch(function(err) {
showTimedNotification(
_('操作失败:%s').format(err.message || String(err)),
'error',
6000
);
});
}
return view.extend({
load: function() {
return Promise.all([ uci.load('system'), uci.load('led-scheduler') ]);
},
render: function() {
var m, s, o;
var leds = [];
uci.sections('system', 'led', function(section) {
if (!section.sysfs) return;
leds.push({
name: section.name || section.sysfs,
sysfs: section.sysfs,
trigger: section.trigger || _('未指定')
});
});
leds.sort(function(a, b) { return a.name.localeCompare(b.name); });
m = new form.Map('led-scheduler', _('LED 定时'),
_('这里只负责“什么时候关灯、什么时候恢复”。LED 平时的触发器、网口联动等行为仍由“系统 → LED 配置”管理。'));
s = m.section(form.NamedSection, 'main', 'scheduler', _('定时设置'));
s.addremove = false;
o = s.option(form.Flag, 'enabled', _('启用 LED 定时'));
o.default = '0'; o.rmempty = false;
o.description = _('关闭此开关并保存应用后,会立即恢复 OpenWrt 原生 LED 配置。');
o = s.option(form.Value, 'off_time', _('关闭时间'));
o.default = '23:00'; o.placeholder = '23:00'; o.rmempty = false; o.validate = validateTime;
o = s.option(form.Value, 'on_time', _('恢复时间'));
o.default = '07:00'; o.placeholder = '07:00'; o.rmempty = false; o.validate = validateTime;
o.description = _('支持跨午夜,例如 23:00 关闭、07:00 恢复。');
o = s.option(form.Flag, 'all_system_leds', _('控制“系统 → LED 配置”中的全部 LED'));
o.default = '1'; o.rmempty = false;
o = s.option(form.MultiValue, 'led', _('控制对象'));
o.depends('all_system_leds', '0'); o.rmempty = true;
if (leds.length) {
leds.forEach(function(led) {
o.value(led.sysfs, _('%s(%s,触发器:%s)').format(led.name, led.sysfs, led.trigger));
});
o.description = _('这些项目直接读取自 /etc/config/system,不会复制或修改原有 LED 行为。');
} else {
o.description = _('当前没有从“系统 → LED 配置”中读取到 LED 项目。');
}
s = m.section(form.NamedSection, 'main', 'scheduler', _('手动控制'));
s.addremove = false;
o = s.option(form.Button, '_off_now', _('立即关闭'));
o.inputstyle = 'remove';
o.description = _('临时将所选 LED 的 trigger 设为 none,并将亮度设为 0。');
o.onclick = function() { return runControl('off', _('所选 LED 已关闭。')); };
o = s.option(form.Button, '_on_now', _('立即恢复'));
o.inputstyle = 'apply';
o.description = _('重新加载 OpenWrt 原生 LED 配置,恢复 WAN/LAN 等原有触发方式。');
o.onclick = function() { return runControl('on', _('OpenWrt 原生 LED 配置已恢复。')); };
o = s.option(form.Button, '_apply_now', _('按当前时间应用'));
o.inputstyle = 'action';
o.onclick = function() { return runControl('apply', _('已按当前时间应用 LED 状态。')); };
o = s.option(form.Button, '_sync_cron', _('重新同步定时任务'));
o.inputstyle = 'action';
o.description = _('正常情况下保存并应用会自动同步,无需手动点击。');
o.onclick = function() { return runControl('sync', _('定时任务已同步。')); };
s = m.section(form.TypedSection, '_native_led_info', _('已读取的系统 LED'));
s.anonymous = true; s.addremove = false;
o = s.option(form.DummyValue, '_info');
o.rawhtml = true;
o.cfgvalue = function() {
if (!leds.length) return '<em>' + _('没有检测到系统 LED 配置。') + '</em>';
function esc(v) { return String(v).replace(/[&<>"']/g, function(c) { return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]; }); }
var rows = leds.map(function(led) {
return '<tr><td>' + esc(led.name) + '</td><td><code>' + esc(led.sysfs) + '</code></td><td>' + esc(led.trigger) + '</td></tr>';
}).join('');
return '<table class="table"><tr class="tr table-titles"><th>' + _('名称') + '</th><th>' + _('LED 名称') + '</th><th>' + _('触发器') + '</th></tr>' + rows + '</table>';
};
return m.render();
}
});