|
|
@@ -621,6 +621,29 @@ html, body { width:100%; height:100%; overflow:auto; background:var(--bg-deep);
|
|
|
#chart-ring { width:100%; height:100%; }
|
|
|
#chart-pie-status { width:100%; flex:1; min-height:0; }
|
|
|
#chart-pie-usage { width:100%; flex:1; min-height:0; }
|
|
|
+
|
|
|
+/* ========== MONITOR TABS (3区) ========== */
|
|
|
+.monitor-tab-bar { display:flex; gap:10px; }
|
|
|
+.monitor-tab {
|
|
|
+ padding:12px 44px; border-radius:8px; cursor:pointer; outline:none;
|
|
|
+ background:var(--bg-card); border:1px solid var(--border);
|
|
|
+ color:var(--text-dim); font-size:28px; font-weight:600; letter-spacing:2px;
|
|
|
+ transition:all 0.25s; font-family:var(--font-main);
|
|
|
+}
|
|
|
+.monitor-tab.active {
|
|
|
+ border-color:var(--cyan); color:var(--cyan);
|
|
|
+ background:rgba(0,216,255,0.1); text-shadow:0 0 10px rgba(0,216,255,0.45);
|
|
|
+ box-shadow:0 0 14px rgba(0,216,255,0.18);
|
|
|
+}
|
|
|
+.monitor-tab:hover:not(.active) { border-color:rgba(30,144,255,0.6); color:var(--text); }
|
|
|
+.monitor-tab-content { display:none; flex:1; flex-direction:column; min-height:0; }
|
|
|
+.monitor-tab-content.active { display:flex; }
|
|
|
+
|
|
|
+/* 九宫格全屏摄像头网格 */
|
|
|
+#camera-grid-9 {
|
|
|
+ display:grid; grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(3,1fr);
|
|
|
+ gap:15px; flex:1; min-height:0; padding:15px;
|
|
|
+}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
@@ -1179,38 +1202,54 @@ html, body { width:100%; height:100%; overflow:auto; background:var(--bg-deep);
|
|
|
<!-- ======== 3区: 实时监控 ======== -->
|
|
|
<div class="center-col">
|
|
|
|
|
|
- <!-- 实时监控(常显) -->
|
|
|
+ <!-- 实时监控(含 九宫格/全部 两种视图) -->
|
|
|
<div id="view-monitor">
|
|
|
+
|
|
|
+ <!-- 标题栏 + 标签切换 -->
|
|
|
<div class="monitor-header">
|
|
|
<span style="font-size:32px;font-weight:600;color:var(--cyan);letter-spacing:2px">📹 实时监控</span>
|
|
|
<span style="font-size:28px;color:var(--text-dim);margin-left:10px">CCTV Live Feed</span>
|
|
|
- <div style="margin-left:auto;display:flex;align-items:center;gap:15px">
|
|
|
+ <div class="monitor-tab-bar" style="margin-left:auto;margin-right:20px">
|
|
|
+ <button class="monitor-tab active" onclick="switchMonitorTab('9grid',this)">默认</button>
|
|
|
+ <button class="monitor-tab" onclick="switchMonitorTab('all',this)">全部</button>
|
|
|
+ </div>
|
|
|
+ <div style="display:flex;align-items:center;gap:15px">
|
|
|
<div class="status-dot green"></div>
|
|
|
<span style="font-size:28px;color:var(--text-dim)">信号正常</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="monitor-inner">
|
|
|
- <div class="monitor-left">
|
|
|
- <div class="search-box"><span style="font-size:32px;color:var(--text-dim)">🔍</span><input type="text" placeholder="搜索楼栋 / 楼层 / 房间…"></div>
|
|
|
- <select class="filter-select">
|
|
|
- <option value="">全部二级单位</option>
|
|
|
- <option>化学研究所</option><option>物理研究所</option>
|
|
|
- <option>生物研究所</option><option>材料研究所</option><option>工程研究所</option>
|
|
|
- </select>
|
|
|
- <div class="tree-wrap" id="building-tree"></div>
|
|
|
- </div>
|
|
|
- <div class="monitor-right">
|
|
|
- <div class="camera-grid-header">
|
|
|
- <div class="camera-breadcrumb"><span>安科院主园区</span> › <span>综合实验楼A</span> › <span>3层</span></div>
|
|
|
- <div class="camera-pager">
|
|
|
- <button class="pager-btn">‹</button>
|
|
|
- <span class="pager-info">1 / 3 页</span>
|
|
|
- <button class="pager-btn">›</button>
|
|
|
+
|
|
|
+ <!-- 九宫格视图(默认) -->
|
|
|
+ <div id="tab-9grid" class="monitor-tab-content active">
|
|
|
+ <div id="camera-grid-9"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 全部视图(原监控页面内容不变) -->
|
|
|
+ <div id="tab-all" class="monitor-tab-content">
|
|
|
+ <div class="monitor-inner">
|
|
|
+ <div class="monitor-left">
|
|
|
+ <div class="search-box"><span style="font-size:32px;color:var(--text-dim)">🔍</span><input type="text" placeholder="搜索楼栋 / 楼层 / 房间…"></div>
|
|
|
+ <select class="filter-select">
|
|
|
+ <option value="">全部二级单位</option>
|
|
|
+ <option>化学研究所</option><option>物理研究所</option>
|
|
|
+ <option>生物研究所</option><option>材料研究所</option><option>工程研究所</option>
|
|
|
+ </select>
|
|
|
+ <div class="tree-wrap" id="building-tree"></div>
|
|
|
+ </div>
|
|
|
+ <div class="monitor-right">
|
|
|
+ <div class="camera-grid-header">
|
|
|
+ <div class="camera-breadcrumb"><span>安科院主园区</span> › <span>综合实验楼A</span> › <span>3层</span></div>
|
|
|
+ <div class="camera-pager">
|
|
|
+ <button class="pager-btn">‹</button>
|
|
|
+ <span class="pager-info">1 / 3 页</span>
|
|
|
+ <button class="pager-btn">›</button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ <div class="camera-grid" id="camera-grid"></div>
|
|
|
</div>
|
|
|
- <div class="camera-grid" id="camera-grid"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
</div>
|
|
|
|
|
|
</div><!-- /3区 -->
|
|
|
@@ -1815,7 +1854,11 @@ function renderT(node, depth) {
|
|
|
// ====================================================
|
|
|
const CAMS = ['A301 有机合成室','A302 核磁共振室','A303 质谱室','A301 走廊','A302 走廊','A303 走廊','A层公共区域','A层安全通道','A层出入口'];
|
|
|
function buildCameras() {
|
|
|
- const g = document.getElementById('camera-grid'); if (!g) return;
|
|
|
+ buildCameraGrid('camera-grid-9');
|
|
|
+ buildCameraGrid('camera-grid');
|
|
|
+}
|
|
|
+function buildCameraGrid(gridId) {
|
|
|
+ const g = document.getElementById(gridId); if (!g) return;
|
|
|
g.innerHTML = '';
|
|
|
for (let i = 0; i < 9; i++) {
|
|
|
const cell = document.createElement('div');
|
|
|
@@ -1835,6 +1878,12 @@ function buildCameras() {
|
|
|
setTimeout(() => drawFakeCam(cv, i), 150);
|
|
|
}
|
|
|
}
|
|
|
+function switchMonitorTab(tab, btn) {
|
|
|
+ document.querySelectorAll('.monitor-tab').forEach(b => b.classList.remove('active'));
|
|
|
+ document.querySelectorAll('.monitor-tab-content').forEach(c => c.classList.remove('active'));
|
|
|
+ btn.classList.add('active');
|
|
|
+ document.getElementById('tab-' + tab).classList.add('active');
|
|
|
+}
|
|
|
function drawFakeCam(canvas, idx) {
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
const par = canvas.parentElement;
|