Files
Ayay/SHH.CameraSdk/Htmls/Main.html
twice109 2ee25a4f7c 支持通过网页增加、删除、修改摄像头配置信息
支持摄像头配置信息中句柄的设置,并实测有效
2025-12-28 08:07:55 +08:00

148 lines
7.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>SHH 视频网关 - 控制底座</title>
<script src="https://cdn.staticfile.org/axios/1.5.0/axios.min.js"></script>
<link href="https://cdn.staticfile.org/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.staticfile.org/bootstrap-icons/1.10.0/font/bootstrap-icons.min.css" rel="stylesheet">
<style>
body, html { margin: 0; padding: 0; height: 100vh; overflow: hidden; background: #f4f6f9; }
.app-shell { display: flex; height: 100vh; }
.sidebar-container { width: 320px; border-right: 1px solid #ddd; background: #fff; flex-shrink: 0; }
.main-workarea { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.top-container { height: 110px; padding: 15px 15px 0 15px; flex-shrink: 0; }
.editor-container { flex: 1; padding: 15px; overflow: hidden; position: relative; }
.log-panel { height: 45px; border-top: 1px solid #333; transition: height 0.3s; background: #1e1e1e; }
.modal-body iframe { border: none; width: 100%; }
#frame-editor { width: 100%; height: 100%; border: none; background: #fff; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); }
</style>
</head>
<body>
<div class="app-shell">
<div class="sidebar-container">
<iframe id="frame-list" src="List.html" style="width:100%; height:100%; border:none;" name="list"></iframe>
</div>
<div class="main-workarea">
<div class="top-container">
<iframe id="frame-top" src="EditorTop.html" style="width:100%; height:100%; border:none;" name="top"></iframe>
</div>
<div class="editor-container">
<iframe id="frame-editor" src="Editor.html" name="editor"></iframe>
</div>
<div id="diag-wrapper" class="log-panel">
<iframe id="frame-diag" src="Diagnostic.html" style="width:100%; height:100%; border:none;" name="diag"></iframe>
</div>
</div>
</div>
<div class="modal fade" id="subModal" tabindex="-1"><div class="modal-dialog modal-lg modal-dialog-centered"><div class="modal-content shadow-lg"><div class="modal-body p-0"><iframe id="frame-sub" src="Subscription.html" style="height: 650px;" name="sub"></iframe></div></div></div></div>
<div class="modal fade" id="preModal" tabindex="-1"><div class="modal-dialog modal-md modal-dialog-centered"><div class="modal-content shadow-lg"><div class="modal-body p-0"><iframe id="frame-pre" src="Preprocessing.html" style="height: 580px;" name="pre"></iframe></div></div></div></div>
<div class="modal fade" id="ctrlModal" tabindex="-1"><div class="modal-dialog modal-dialog-centered"><div class="modal-content shadow-lg"><div class="modal-body p-0"><iframe id="frame-ctrl" src="CameraControl.html" style="height: 480px;" name="ctrl"></iframe></div></div></div></div>
<script src="https://cdn.staticfile.org/bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
<script>
const API_BASE = "http://localhost:5000";
let currentDeviceId = 0;
window.addEventListener('message', (event) => {
const msg = event.data;
if (!msg || !msg.type) return;
const frames = {
list: document.getElementById('frame-list').contentWindow,
top: document.getElementById('frame-top').contentWindow,
editor: document.getElementById('frame-editor').contentWindow,
diag: document.getElementById('frame-diag').contentWindow,
sub: document.getElementById('frame-sub').contentWindow,
pre: document.getElementById('frame-pre').contentWindow,
ctrl: document.getElementById('frame-ctrl').contentWindow
};
const editorIframe = document.getElementById('frame-editor');
const switchToDetail = () => {
editorIframe.src = "Editor.html";
editorIframe.onload = () => {
setTimeout(() => {
if(currentDeviceId) editorIframe.contentWindow.postMessage({ type: 'LOAD_DEVICE', deviceId: currentDeviceId }, '*');
}, 100);
};
};
switch(msg.type) {
case 'DEVICE_SELECTED':
currentDeviceId = msg.data.id;
// 如果当前不是Editor页面切回
if (!editorIframe.src.includes('Editor.html')) {
switchToDetail();
} else {
if(frames.top) frames.top.postMessage({ type: 'UPDATE_TOP_INFO', data: msg.data }, '*');
if(frames.editor) frames.editor.postMessage({ type: 'LOAD_DEVICE', deviceId: msg.data.id }, '*');
}
break;
case 'DEVICE_CONTROL':
const controlUrl = `${API_BASE}/api/Cameras/${msg.deviceId}/power?enabled=${msg.action === 'start'}`;
axios.post(controlUrl).then(() => {
frames.list.postMessage({ type: 'REFRESH_LIST' }, '*');
frames.diag.postMessage({ type: 'PUSH_LOG', log: { method: 'POST', url: controlUrl, status: 200, msg: `Device ${msg.action}` } }, '*');
}).catch(e => console.error(e));
break;
case 'API_LOG':
if(frames.diag) frames.diag.postMessage({ type: 'PUSH_LOG', log: msg.log }, '*');
break;
case 'UI_RESIZE_DIAG':
const diagEl = document.getElementById('diag-wrapper');
if(diagEl) diagEl.style.height = msg.expanded ? '350px' : '45px';
break;
// 弹窗逻辑
case 'OPEN_SUBSCRIPTION':
new bootstrap.Modal(document.getElementById('subModal')).show();
setTimeout(() => frames.sub.postMessage({ type: 'LOAD_SUBS_DATA', deviceId: msg.id }, '*'), 400);
break;
case 'OPEN_PREPROCESS':
editorIframe.src = "Preprocessing.html";
editorIframe.onload = () => {
editorIframe.contentWindow.postMessage({ type: 'LOAD_PREPROCESS_DATA', deviceId: msg.id, apiBase: API_BASE }, '*');
};
break;
case 'OPEN_CAMERA_CONTROL':
new bootstrap.Modal(document.getElementById('ctrlModal')).show();
setTimeout(() => frames.ctrl.postMessage({ type: 'LOAD_CTRL_DATA', deviceId: msg.id, apiBase: API_BASE }, '*'), 400);
break;
// --- 统一使用 CameraEdit.html ---
case 'OPEN_CAMERA_EDIT':
editorIframe.src = "CameraEdit.html";
editorIframe.onload = () => {
editorIframe.contentWindow.postMessage({ type: 'LOAD_EDIT_DATA', deviceId: msg.id, apiBase: API_BASE }, '*');
};
break;
case 'OPEN_CAMERA_ADD': // 新增也指向同一个文件
editorIframe.src = "CameraEdit.html";
editorIframe.onload = () => {
editorIframe.contentWindow.postMessage({ type: 'INIT_ADD_PAGE', apiBase: API_BASE }, '*');
};
break;
// 统一关闭逻辑
case 'CLOSE_EDIT_MODE':
case 'CLOSE_PREPROCESS_MODE':
case 'CLOSE_ADD_MODE':
switchToDetail();
if(msg.needRefresh) frames.list.postMessage({ type: 'REFRESH_LIST' }, '*');
break;
}
});
</script>
</body>
</html>