|
|
@@ -119,8 +119,16 @@ border-left:3px solid #e94560;padding:8px 10px;margin-bottom:8px;cursor:pointer}
|
|
|
.pill-on{background:#27ae60;color:#fff}
|
|
|
.pill-off{background:#e74c3c;color:#fff}
|
|
|
|
|
|
-/* ---------- 系统页 ---------- */
|
|
|
-.sys-wrap{max-width:640px;margin:0 auto;padding:24px}
|
|
|
+/* ---------- 系统页: 两列紧凑布局 ---------- */
|
|
|
+.sys-wrap{max-width:1040px;margin:0 auto;padding:12px;display:grid;grid-template-columns:1fr 1fr;gap:12px;align-content:start}
|
|
|
+.sys-wrap .card{margin-bottom:0;padding:12px}
|
|
|
+.sys-wrap .card h3{margin-bottom:8px;font-size:14px}
|
|
|
+.sys-wrap .form-group{margin-bottom:8px}
|
|
|
+.sys-wrap .form-group label{font-size:12px;margin-bottom:2px}
|
|
|
+.sys-wrap .form-group input,.sys-wrap .form-group select{padding:6px}
|
|
|
+.sys-wrap .btn-row{margin-top:8px}
|
|
|
+.sys-wrap .hint{font-size:12px;margin-bottom:6px}
|
|
|
+@media (max-width:760px){.sys-wrap{grid-template-columns:1fr}}
|
|
|
|
|
|
/* ---------- PiP ---------- */
|
|
|
|
|
|
@@ -312,64 +320,48 @@ border-left:3px solid #e94560;padding:8px 10px;margin-bottom:8px;cursor:pointer}
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
- <h3>系统配置</h3>
|
|
|
- <div style="display:flex;gap:10px;flex-wrap:wrap">
|
|
|
- <div class="form-group" style="flex:1;min-width:180px"><label><input type="checkbox" id="sysTargetEnabled"> 是否启用目标识别</label></div>
|
|
|
- <div class="form-group" style="flex:1;min-width:180px"><label><input type="checkbox" id="sysPoseEnabled"> 是否启用姿态识别</label></div>
|
|
|
+ <h3>识别与输出</h3>
|
|
|
+ <div style="display:flex;gap:14px;flex-wrap:wrap;margin-bottom:8px;font-size:13px">
|
|
|
+ <label style="display:flex;align-items:center;gap:5px;cursor:pointer"><input type="checkbox" id="sysTargetEnabled"> 目标识别</label>
|
|
|
+ <label style="display:flex;align-items:center;gap:5px;cursor:pointer"><input type="checkbox" id="sysPoseEnabled"> 姿态识别</label>
|
|
|
</div>
|
|
|
- <div style="display:flex;gap:10px;flex-wrap:wrap">
|
|
|
- <div class="form-group" style="flex:1;min-width:180px"><label>输出通道网格到显示器</label><select id="sysGridOutput"><option value="true">启用</option><option value="false">禁用</option></select></div>
|
|
|
- <div class="form-group" style="flex:1;min-width:180px"><label>输出钢包位到显示器</label><select id="sysSteelOutput"><option value="true">启用</option><option value="false">禁用</option></select></div>
|
|
|
- <div class="form-group" style="flex:1;min-width:180px"><label>Web视频推流(MJPEG)</label><select id="sysMjpegEnabled" onchange="toggleSystemMjpeg()"><option value="true">启用</option><option value="false">临时关闭(省CPU)</option></select></div>
|
|
|
+ <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px">
|
|
|
+ <div class="form-group" style="margin:0"><label>通道网格显示</label><select id="sysGridOutput"><option value="true">启用</option><option value="false">禁用</option></select></div>
|
|
|
+ <div class="form-group" style="margin:0"><label>钢包位显示</label><select id="sysSteelOutput"><option value="true">启用</option><option value="false">禁用</option></select></div>
|
|
|
+ <div class="form-group" style="margin:0"><label>Web推流</label><select id="sysMjpegEnabled" onchange="toggleSystemMjpeg()"><option value="true">启用</option><option value="false">关闭(省CPU)</option></select></div>
|
|
|
</div>
|
|
|
- <div class="btn-row" style="margin-top:0"><button class="btn btn-primary" onclick="saveSystemOptions()">保存系统配置</button></div>
|
|
|
+ <div class="btn-row"><button class="btn btn-primary" onclick="saveSystemOptions()">保存</button></div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
<h3>自动重启</h3>
|
|
|
- <div class="form-group" style="display:flex;align-items:center;gap:8px;margin-bottom:8px">
|
|
|
+ <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px">
|
|
|
<input type="checkbox" id="sysRebootEn">
|
|
|
- <label for="sysRebootEn" style="margin:0;font-weight:bold;color:#eee;cursor:pointer">启用自动重启</label>
|
|
|
+ <label for="sysRebootEn" style="margin:0;font-size:13px;color:#eee;cursor:pointer">启用自动重启</label>
|
|
|
</div>
|
|
|
- <div style="display:flex;gap:10px">
|
|
|
- <div class="form-group" style="flex:1"><label>重启周期(每N天)</label><input type="number" id="sysRebootCycle" min="1" max="365" value="1"></div>
|
|
|
- <div class="form-group" style="flex:1"><label>重启时间</label><input type="time" id="sysRebootTime" value="03:30"></div>
|
|
|
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
|
|
|
+ <div class="form-group" style="margin:0"><label>周期(每N天)</label><input type="number" id="sysRebootCycle" min="1" max="365" value="1"></div>
|
|
|
+ <div class="form-group" style="margin:0"><label>时间</label><input type="time" id="sysRebootTime" value="03:30"></div>
|
|
|
</div>
|
|
|
- <div class="btn-row" style="margin-top:0">
|
|
|
- <button class="btn btn-primary" onclick="saveSystemConfig()">保存自动重启</button>
|
|
|
+ <div class="btn-row">
|
|
|
+ <button class="btn btn-primary" onclick="saveSystemConfig()">保存</button>
|
|
|
+ <button class="btn btn-danger" onclick="rebootNow()">立即重启</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="card">
|
|
|
<h3>密码管理</h3>
|
|
|
- <div class="form-group">
|
|
|
- <label>原密码</label>
|
|
|
- <input type="password" id="pwdOld" autocomplete="current-password">
|
|
|
- </div>
|
|
|
- <div style="display:flex;gap:10px">
|
|
|
- <div class="form-group" style="flex:1"><label>新用户名(不改请留空)</label><input type="text" id="pwdNewUser" placeholder="留空保持不变"></div>
|
|
|
- <div class="form-group" style="flex:1"><label>新密码</label><input type="password" id="pwdNew1" autocomplete="new-password"></div>
|
|
|
- <div class="form-group" style="flex:1"><label>确认新密码</label><input type="password" id="pwdNew2" autocomplete="new-password"></div>
|
|
|
+ <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px">
|
|
|
+ <div class="form-group" style="margin:0;grid-column:1/-1"><label>原密码</label><input type="password" id="pwdOld" autocomplete="current-password"></div>
|
|
|
+ <div class="form-group" style="margin:0"><label>新用户名(可空)</label><input type="text" id="pwdNewUser" placeholder="留空不变"></div>
|
|
|
+ <div class="form-group" style="margin:0"><label>新密码</label><input type="password" id="pwdNew1" autocomplete="new-password"></div>
|
|
|
+ <div class="form-group" style="margin:0"><label>确认新密码</label><input type="password" id="pwdNew2" autocomplete="new-password"></div>
|
|
|
</div>
|
|
|
- <div class="btn-row" style="margin-top:0">
|
|
|
+ <div class="btn-row">
|
|
|
<button class="btn btn-primary" onclick="changePassword()">修改凭据</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="card">
|
|
|
- <h3>设备操作</h3>
|
|
|
- <div class="hint">重启期间视频流将中断约1-2分钟</div>
|
|
|
- <div class="btn-row" style="margin-top:0">
|
|
|
- <button class="btn btn-danger" onclick="rebootNow()">立即重启设备</button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
</div>
|
|
|
</section>
|
|
|
|
|
|
- <div id="pip">
|
|
|
- <img id="pipImg" alt="">
|
|
|
- <div class="pip-bar">
|
|
|
- <span>预览 <b id="pipLabel">-</b></span>
|
|
|
- <span><button onclick="pipPrev()">‹</button><button onclick="pipNext()">›</button><button onclick="pipRefresh()">↻</button></span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
</main>
|
|
|
</div>
|
|
|
|
|
|
@@ -437,13 +429,6 @@ function switchPage(p) {
|
|
|
} else {
|
|
|
stage.style.display = 'none';
|
|
|
}
|
|
|
- const pip = document.getElementById('pip');
|
|
|
- const showPip = (p !== 'monitor' && p !== 'fence');
|
|
|
- pip.style.display = showPip ? 'block' : 'none';
|
|
|
- if (showPip && pipCh < 0 && CHANNELS.length) {
|
|
|
- pipCh = CHANNELS[0].id;
|
|
|
- document.getElementById('pipLabel').textContent = 'CH' + pipCh;
|
|
|
- }
|
|
|
if (p === 'alarm') loadAlarms();
|
|
|
if (p === 'action') loadActions();
|
|
|
if (p === 'relay') { loadRelayStatus(); loadBindings(); }
|
|
|
@@ -468,7 +453,6 @@ let CHANNELS = [];
|
|
|
let curChannel = -1;
|
|
|
let cellSig = '', tabSig = '';
|
|
|
const desired = {};
|
|
|
-let pipCh = -1;
|
|
|
|
|
|
function chById(id) { return CHANNELS.find(c => c.id === id); }
|
|
|
|
|
|
@@ -595,35 +579,6 @@ function applyStreamPolicy() {
|
|
|
desired[c.id] = want;
|
|
|
if (want) connectStream(c.id); else disconnectStream(c.id);
|
|
|
});
|
|
|
- const pipOn = document.getElementById('pip').style.display === 'block';
|
|
|
- const pi = document.getElementById('pipImg');
|
|
|
- if (pipOn && pipCh >= 0 && chById(pipCh)) {
|
|
|
- if (pi.dataset.on !== '1') {
|
|
|
- pi.src = '/mjpeg/' + pipCh + '?t=' + Date.now();
|
|
|
- pi.dataset.on = '1';
|
|
|
- }
|
|
|
- } else if (pi.dataset.on === '1') {
|
|
|
- pi.removeAttribute('src');
|
|
|
- pi.dataset.on = '0';
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-function pipCycle(d) {
|
|
|
- if (!CHANNELS.length) return;
|
|
|
- let idx = CHANNELS.findIndex(c => c.id === pipCh);
|
|
|
- idx = idx < 0 ? 0 : (idx + d + CHANNELS.length) % CHANNELS.length;
|
|
|
- pipCh = CHANNELS[idx].id;
|
|
|
- document.getElementById('pipLabel').textContent = 'CH' + pipCh;
|
|
|
- const pi = document.getElementById('pipImg');
|
|
|
- pi.dataset.on = '0';
|
|
|
- applyStreamPolicy();
|
|
|
-}
|
|
|
-function pipNext() { pipCycle(1); }
|
|
|
-function pipPrev() { pipCycle(-1); }
|
|
|
-function pipRefresh() {
|
|
|
- const pi = document.getElementById('pipImg');
|
|
|
- pi.dataset.on = '0';
|
|
|
- applyStreamPolicy();
|
|
|
}
|
|
|
|
|
|
/* ================= 通道管理 ================= */
|