feat: 实现设备注册和精准控制功能,支持双屏管理;更新相关逻辑以优化设备状态跟踪

This commit is contained in:
Pine
2026-08-19 14:19:37 +08:00
parent 93b27cf227
commit e72442dae0
15 changed files with 264 additions and 53 deletions
+54 -15
View File
@@ -10,8 +10,46 @@
var fullscreen = !!init.fullscreen;
var autostart = !!init.autostart;
/* 目标屏(双屏独立控制):both | main | secondary */
var screenTarget = 'both';
/* 目标屏幕(按 MQTT 客户端精准控制):client_id + role */
var screenId = '';
var screenRole = '';
function applyScreenTarget(sel) {
sel = sel || document.getElementById('screenTarget');
if (!sel) return;
var v = sel.value || '';
screenId = v;
var opt = null;
if (v) { for (var i = 0; i < sel.options.length; i++) { if (sel.options[i].value === v) { opt = sel.options[i]; break; } } }
screenRole = opt ? (opt.getAttribute('data-role') || '') : '';
}
function loadScreens() {
fetch('/api/display/state', { cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (d) {
var sel = document.getElementById('screenTarget');
var cnt = document.getElementById('screenCount');
if (!sel) return;
var devices = (d && d.devices) || [];
if (cnt) cnt.textContent = '在线设备:' + (devices.length || 0) + ' 台';
var cur = sel.value;
sel.innerHTML = '<option value="">全部屏幕</option>';
devices.forEach(function (dev) {
var role = dev.role || '';
var name = role === 'main' ? '主屏' : role === 'secondary' ? '副屏' : (role || '屏幕');
var parent = (dev.role === 'secondary' && dev.parent_id) ? '·属于:' + String(dev.parent_id).slice(0, 8) : '';
var opt = document.createElement('option');
opt.value = dev.device_id;
opt.setAttribute('data-role', role);
opt.textContent = name + parent + ' · ' + String(dev.device_id).slice(0, 16);
sel.appendChild(opt);
});
if (cur) sel.value = cur;
applyScreenTarget(sel);
})
.catch(function () {});
}
/* ---------- Toast ---------- */
var toastContainer = document.getElementById('toastContainer');
@@ -82,6 +120,7 @@
setConn('api', true, '在线');
setConn('mqtt', !!d.mqtt_connected, d.mqtt_connected ? '已连接(' + (d.mqtt_host || '') + '' : '未连接');
setConn('screens', (d.screens_online || 0) > 0, (d.screens_online || 0) + ' 台');
loadScreens(); // 刷新目标屏幕下拉(按 MQTT 客户端)
var lc = d.last_command;
if (lc) {
var names = { navigate: '页面切换', play: '播放', pause: '暂停', next: '下一项', prev: '上一项',
@@ -98,6 +137,12 @@
});
}
if (connEls.api) { pollStatus(); setInterval(pollStatus, 3000); }
// 目标屏幕下拉:变更时记录目标 client_id + role;初始加载一次
var screenSel = document.getElementById('screenTarget');
if (screenSel) {
screenSel.addEventListener('change', function () { applyScreenTarget(screenSel); });
loadScreens();
}
/* =========================================================
事件委托:页面切换 / 播放控制 / 媒体操作
@@ -110,19 +155,10 @@
});
document.addEventListener('click', function (e) {
var btn = e.target.closest ? e.target.closest('[data-nav], [data-mqtt], [data-control], [data-action], .copy-btn, [data-preview], .screen-target, #mqttAiSend, #mqttAlertSend') : null;
var btn = e.target.closest ? e.target.closest('[data-nav], [data-mqtt], [data-control], [data-action], .copy-btn, [data-preview], #mqttAiSend, #mqttAlertSend') : null;
if (!btn) return;
e.stopPropagation();
// 目标屏选择(双屏独立控制)
if (btn.classList.contains('screen-target')) {
screenTarget = btn.getAttribute('data-screen') || 'both';
var btns = document.querySelectorAll('.screen-target');
for (var i = 0; i < btns.length; i++) btns[i].classList.toggle('active', btns[i] === btn);
toast('目标屏:' + ({ both: '全部(镜像)', main: '仅主屏', secondary: '仅副屏' }[screenTarget] || screenTarget));
return;
}
// 预览
if (btn.hasAttribute('data-preview')) { openPreview(btn.closest('.media-card')); return; }
@@ -141,10 +177,13 @@
if (btn.hasAttribute('data-mqtt')) {
var cmd = null;
try { cmd = JSON.parse(btn.getAttribute('data-mqtt')); } catch (err) { toast('指令 JSON 错误', 'error'); return; }
// 双屏独立控制:除「双屏开关」外,注入目标屏(main/secondary/both
if (cmd.action !== 'dual_screen') cmd.screen = screenTarget;
// 屏幕终端精准控制:除「双屏开关」外,注入目标 client_id + role;全空=全局广播
if (cmd.action !== 'dual_screen') { cmd.screen_id = screenId; cmd.screen_role = screenRole; }
var tgtTxt = screenId
? (cmd.screen_role === 'main' ? '主屏' : cmd.screen_role === 'secondary' ? '副屏' : '屏幕') + '·' + String(screenId).slice(0, 10)
: '全部';
post('/api/display/command', cmd, function (d) {
toast(d && d.ok !== false ? '指令已发送:' + (cmd.action || '') : '发送失败(MQTT 未连接?)',
toast(d && d.ok !== false ? ('指令已发送:' + (cmd.action || '') + ' → ' + tgtTxt) : '发送失败(MQTT 未连接?)',
d && d.ok !== false ? 'ok' : 'error');
});
return;