/** * 摄像头管理器 - 优先通过API获取摄像头列表 * 支持降级到流列表显示 */ class CameraManager { constructor() { this.cameras = []; this.streams = []; this.loadingIndicator = document.getElementById('loading-indicator'); this.cameraContainer = document.getElementById('camera-list-container'); this.streamContainer = document.getElementById('stream-list-container'); this.init(); } async init() { try { // 优先尝试获取摄像头列表 await this.loadCameras(); } catch (error) { console.warn('摄像头API不可用,降级到流列表:', error); // 降级到流列表 await this.loadStreams(); } } async loadCameras() { try { const response = await fetch('/cameras'); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); if (data.cameras && data.cameras.length > 0) { this.cameras = data.cameras; this.renderCameras(); this.updateTitle(`摄像头 (${this.cameras.length})`); } else { throw new Error('摄像头列表为空'); } } catch (error) { console.error('加载摄像头失败:', error); throw error; } } async loadStreams() { try { const response = await fetch('/streams'); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); if (data.status === 1 && data.payload) { this.streams = Object.entries(data.payload).map(([key, value]) => ({ id: key, ...value })); this.showStreamFallback(); this.updateTitle(`视频流 (${this.streams.length})`); } else { this.showEmptyState(); } } catch (error) { console.error('加载流列表失败:', error); this.showEmptyState(); } } renderCameras() { this.hideLoading(); this.cameraContainer.style.display = 'flex'; this.cameraContainer.innerHTML = ''; this.cameras.forEach(camera => { const cameraCard = this.createCameraCard(camera); this.cameraContainer.appendChild(cameraCard); }); } createCameraCard(camera) { const col = document.createElement('div'); col.className = 'col-12 col-sm-6 col-md-3'; col.id = `camera-${camera.id || camera.camera_id}`; const statusClass = camera.status === 'online' ? 'badge-success' : 'badge-secondary'; const statusText = camera.status === 'online' ? '在线' : '离线'; const enabledBadge = camera.enabled ? '已启用' : '已禁用'; // 构建播放按钮 const playButtons = this.createPlayButtons(camera); col.innerHTML = `

${camera.name || camera.camera_name || '未命名摄像头'}

${statusText} ${enabledBadge}
${camera.name || camera.camera_name}
IP: ${camera.ip}
类型: ${camera.device_type || '网络摄像头'}
${camera.unit_code ? `单位: ${camera.unit_code}
` : ''}
${playButtons} 管理 ${camera.enabled ? ` 预览 ` : '已禁用' }
`; return col; } createPlayButtons(camera) { if (!camera.enabled || camera.status !== 'online') { return '离线'; } const cameraId = camera.id || camera.camera_id; return ` MSE HLS WebRTC ALL `; } showStreamFallback() { this.hideLoading(); this.streamContainer.style.display = 'flex'; console.info('使用流列表降级方案'); } showEmptyState() { this.hideLoading(); this.cameraContainer.style.display = 'flex'; this.cameraContainer.innerHTML = `
暂无可用的摄像头或视频流

添加摄像头 添加流
`; } hideLoading() { if (this.loadingIndicator) { this.loadingIndicator.style.display = 'none'; } } updateTitle(title) { const titleElement = document.querySelector('h5.mt-4.mb-2'); if (titleElement) { titleElement.textContent = title; } } // 刷新摄像头列表 async refresh() { this.showLoading(); await this.init(); } showLoading() { this.cameraContainer.style.display = 'none'; this.streamContainer.style.display = 'none'; this.loadingIndicator.style.display = 'flex'; } } // 页面加载完成后初始化 document.addEventListener('DOMContentLoaded', function() { // 确保在其他脚本加载后再初始化 setTimeout(() => { window.cameraManager = new CameraManager(); }, 100); }); // 为Java项目集成提供的全局API window.RTSPtoWebAPI = { // 获取摄像头列表 async getCameras() { const response = await fetch('/cameras'); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 获取流列表 async getStreams() { const response = await fetch('/streams'); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 获取特定摄像头信息 async getCamera(cameraId) { const response = await fetch(`/camera/${cameraId}`); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 添加摄像头 async addCamera(cameraData) { const response = await fetch('/camera/add', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(cameraData) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 更新摄像头 async updateCamera(cameraId, cameraData) { const response = await fetch(`/camera/${cameraId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(cameraData) }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 删除摄像头 async deleteCamera(cameraId) { const response = await fetch(`/camera/${cameraId}`, { method: 'DELETE' }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 刷新摄像头状态 async refreshCameras() { const response = await fetch('/cameras/refresh', { method: 'POST' }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } return await response.json(); }, // 获取播放URL getPlayUrl(cameraId, channel = 0, type = 'hls') { const baseUrl = window.location.origin; switch (type.toLowerCase()) { case 'hls': return `${baseUrl}/stream/${cameraId}/channel/${channel}/hls/live/index.m3u8`; case 'webrtc': return `${baseUrl}/pages/player/webrtc/${cameraId}/${channel}`; case 'mse': return `${baseUrl}/pages/player/mse/${cameraId}/${channel}`; default: return `${baseUrl}/pages/player/all/${cameraId}/${channel}`; } } };