feat(admin): 管理后台加入「大屏控制(MQTT 指令)」面板,覆盖全部前端命令

- routers.py:_VALID_DISPLAY_ACTIONS 扩展为全命令白名单
  (navigate/navigate_rel/vision_set/ai_input/ai_preset/ai_company/ai_zone/
   voice_start/voice_stop/voice_refresh/play/pause/next/prev/set_mode/play_target/
   alert/show_card/minimize/settings_changed/playlist_changed)
- admin.html:新增控制面板(页面导航含/voice+左右、视觉开关、AI 提问/预设/企业/分区、
  语音启停/刷新、媒体控制、全局通知)
- admin.js:data-mqtt 按钮(完整指令 JSON)→ /api/display/command;
  AI 提问/通知输入框回车发送
This commit is contained in:
Pine
2026-08-18 02:32:27 +08:00
parent 7e6c1a09c0
commit 66b6a7fbbd
4 changed files with 149 additions and 4 deletions
+17
View File
@@ -1241,3 +1241,20 @@ button { font-family: "Poppins", "PingFang SC", sans-serif; cursor: pointer; tra
overflow: hidden;
text-overflow: ellipsis;
}
/* ============ 大屏控制(MQTT 指令)面板 ============ */
.mqtt-group { margin: 10px 0 4px; }
.mqtt-group-title {
font-size: 12px; font-weight: 600; color: #5a6b8c;
margin-bottom: 6px; letter-spacing: 0.04em;
}
.mqtt-row {
display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
margin-bottom: 6px;
}
.mqtt-input {
flex: 1; min-width: 180px;
padding: 6px 10px; border: 1px solid #d7e1f0; border-radius: 8px;
font-size: 13px; color: #1d2c44; outline: none;
}
.mqtt-input:focus { border-color: #2f6bff; }
+39 -1
View File
@@ -99,8 +99,15 @@
/* =========================================================
事件委托:页面切换 / 播放控制 / 媒体操作
========================================================= */
// 输入框回车提交
document.addEventListener('keydown', function (e) {
if (e.key !== 'Enter') return;
if (e.target && e.target.id === 'mqttAiInput') { document.getElementById('mqttAiSend').click(); }
else if (e.target && e.target.id === 'mqttAlertText') { document.getElementById('mqttAlertSend').click(); }
});
document.addEventListener('click', function (e) {
var btn = e.target.closest ? e.target.closest('[data-nav], [data-control], [data-action], .copy-btn, [data-preview]') : 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();
@@ -118,6 +125,37 @@
return;
}
// 大屏 MQTT 指令(data-mqtt 携带完整 {action, params} JSON
if (btn.hasAttribute('data-mqtt')) {
var cmd = null;
try { cmd = JSON.parse(btn.getAttribute('data-mqtt')); } catch (err) { toast('指令 JSON 错误', 'error'); return; }
post('/api/display/command', cmd, function (d) {
toast(d && d.ok !== false ? '指令已发送:' + (cmd.action || '') : '发送失败(MQTT 未连接?)',
d && d.ok !== false ? 'ok' : 'error');
});
return;
}
// AI 提问输入框
if (btn.id === 'mqttAiSend') {
var text = (document.getElementById('mqttAiInput').value || '').trim();
if (!text) { toast('请输入问题', 'error'); return; }
post('/api/display/command', { action: 'ai_input', params: { text: text } }, function () {
toast('已发送问题到大屏 AI 页');
});
return;
}
// 通知输入框
if (btn.id === 'mqttAlertSend') {
var alertText = (document.getElementById('mqttAlertText').value || '').trim();
if (!alertText) { toast('请输入通知内容', 'error'); return; }
post('/api/display/command', { action: 'alert', params: { text: alertText } }, function () {
toast('通知已广播');
});
return;
}
// 页面切换
if (btn.hasAttribute('data-nav')) {
var page = btn.getAttribute('data-nav');