// API base URL - automatically detect from current location const API_BASE = `${window.location.protocol}//${window.location.host}/api/videos`; // Tab switching document.querySelectorAll('.tab-btn').forEach(btn => { btn.addEventListener('click', () => { const tab = btn.dataset.tab; switchTab(tab); }); }); function switchTab(tabName) { // Update buttons document.querySelectorAll('.tab-btn').forEach(btn => { btn.classList.remove('active'); if (btn.dataset.tab === tabName) { btn.classList.add('active'); } }); // Update content document.querySelectorAll('.tab-content').forEach(content => { content.classList.remove('active'); }); document.getElementById(`${tabName}-tab`).classList.add('active'); // Load data when switching tabs if (tabName === 'list') { loadVideos(); } else if (tabName === 'compare') { loadVideosForCompare(); } } // File upload const fileInput = document.getElementById('file-input'); const uploadArea = document.getElementById('upload-area'); fileInput.addEventListener('change', handleFileSelect); uploadArea.addEventListener('dragover', (e) => { e.preventDefault(); uploadArea.style.borderColor = '#764ba2'; }); uploadArea.addEventListener('dragleave', () => { uploadArea.style.borderColor = '#667eea'; }); uploadArea.addEventListener('drop', (e) => { e.preventDefault(); uploadArea.style.borderColor = '#667eea'; const files = e.dataTransfer.files; if (files.length > 0) { fileInput.files = files; handleFileSelect({ target: fileInput }); } }); function handleFileSelect(e) { const file = e.target.files[0]; if (!file) return; uploadFile(file); } function uploadFile(file) { const formData = new FormData(); formData.append('file', file); const progressDiv = document.getElementById('upload-progress'); const progressFill = document.getElementById('progress-fill'); const progressText = document.getElementById('progress-text'); const resultDiv = document.getElementById('upload-result'); // Show progress document.querySelector('.upload-placeholder').style.display = 'none'; progressDiv.style.display = 'block'; progressFill.style.width = '0%'; resultDiv.style.display = 'none'; // Upload using fetch fetch(`${API_BASE}/upload`, { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { progressFill.style.width = '100%'; progressText.textContent = '上传完成!'; setTimeout(() => { if (data.success) { showResult('upload-result', `视频上传成功!ID: ${data.data.video_id}`, 'success'); // Reset form fileInput.value = ''; document.querySelector('.upload-placeholder').style.display = 'block'; progressDiv.style.display = 'none'; } else { showResult('upload-result', data.message || '上传失败', 'error'); } }, 500); }) .catch(error => { showResult('upload-result', `上传失败: ${error.message}`, 'error'); progressDiv.style.display = 'none'; document.querySelector('.upload-placeholder').style.display = 'block'; }); } // Load videos list function loadVideos() { const videoList = document.getElementById('video-list'); videoList.innerHTML = '

加载中...

'; fetch(`${API_BASE}`) .then(response => response.json()) .then(data => { if (data.success && data.data.length > 0) { videoList.innerHTML = ''; data.data.forEach(video => { const videoItem = createVideoItem(video); videoList.appendChild(videoItem); }); } else { videoList.innerHTML = '

暂无视频

'; } }) .catch(error => { videoList.innerHTML = `

加载失败: ${error.message}

`; }); } function createVideoItem(video) { const div = document.createElement('div'); div.className = 'video-item'; const sizeMB = (video.file_size / (1024 * 1024)).toFixed(2); const uploadTime = new Date(video.upload_time).toLocaleString('zh-CN'); div.innerHTML = `
${video.filename}
${getStatusText(video.status)}
大小: ${sizeMB} MB | 上传时间: ${uploadTime}
`; return div; } function getStatusColor(status) { const colors = { 'uploaded': '#6c757d', 'analyzing': '#ffc107', 'analyzed': '#28a745', 'failed': '#dc3545' }; return colors[status] || '#6c757d'; } function getStatusText(status) { const texts = { 'uploaded': '已上传', 'analyzing': '分析中', 'analyzed': '已分析', 'failed': '失败' }; return texts[status] || status; } // Video details modal function viewVideoDetails(videoId) { fetch(`${API_BASE}/${videoId}`) .then(response => response.json()) .then(data => { if (data.success) { showVideoModal(data.data); } else { alert(data.message || '获取视频详情失败'); } }) .catch(error => { alert(`获取视频详情失败: ${error.message}`); }); } function showVideoModal(video) { const modal = document.getElementById('video-modal'); const modalTitle = document.getElementById('modal-title'); const modalBody = document.getElementById('modal-body'); modalTitle.textContent = video.filename; let html = `

基本信息

文件名: ${video.filename}

大小: ${(video.file_size / (1024 * 1024)).toFixed(2)} MB

状态: ${getStatusText(video.status)}

上传时间: ${new Date(video.upload_time).toLocaleString('zh-CN')}

`; if (video.analysis) { html += `

分析结果

${video.analysis.content}

FPS: ${video.analysis.fps} | 创建时间: ${new Date(video.analysis.created_at).toLocaleString('zh-CN')}

`; } if (video.summary) { html += `

视频总结

${video.summary.summary_text}

创建时间: ${new Date(video.summary.created_at).toLocaleString('zh-CN')}

`; } modalBody.innerHTML = html; modal.style.display = 'block'; } function closeModal() { document.getElementById('video-modal').style.display = 'none'; } window.onclick = function(event) { const modal = document.getElementById('video-modal'); if (event.target === modal) { closeModal(); } } // Analyze video function analyzeVideo(videoId) { if (!confirm('确定要分析这个视频吗?这可能需要一些时间。')) { return; } // Show loading message const loadingMsg = document.createElement('div'); loadingMsg.id = 'analysis-loading'; loadingMsg.style.cssText = 'position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); z-index: 10000;'; loadingMsg.innerHTML = '

正在分析视频,请稍候...

'; document.body.appendChild(loadingMsg); fetch(`${API_BASE}/${videoId}/analyze`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }) .then(response => response.json()) .then(data => { // Remove loading message const loadingEl = document.getElementById('analysis-loading'); if (loadingEl) { loadingEl.remove(); } if (data.success) { // Refresh video list first loadVideos(); // Then automatically open video details to show the analysis setTimeout(() => { viewVideoDetails(videoId); }, 500); } else { alert(data.message || '分析失败'); } }) .catch(error => { // Remove loading message const loadingEl = document.getElementById('analysis-loading'); if (loadingEl) { loadingEl.remove(); } alert(`分析失败: ${error.message}`); }); } // Summarize video function summarizeVideo(videoId) { if (!confirm('确定要生成视频总结吗?这可能需要一些时间。')) { return; } // Show loading message const loadingMsg = document.createElement('div'); loadingMsg.id = 'summary-loading'; loadingMsg.style.cssText = 'position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); z-index: 10000;'; loadingMsg.innerHTML = '

正在生成视频总结,请稍候...

'; document.body.appendChild(loadingMsg); fetch(`${API_BASE}/${videoId}/summarize`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }) .then(response => response.json()) .then(data => { // Remove loading message const loadingEl = document.getElementById('summary-loading'); if (loadingEl) { loadingEl.remove(); } if (data.success) { // Refresh video list first loadVideos(); // Then automatically open video details to show the summary setTimeout(() => { viewVideoDetails(videoId); }, 500); } else { alert(data.message || '总结生成失败'); } }) .catch(error => { // Remove loading message const loadingEl = document.getElementById('summary-loading'); if (loadingEl) { loadingEl.remove(); } alert(`总结生成失败: ${error.message}`); }); } // Compare videos function loadVideosForCompare() { const compareList = document.getElementById('compare-video-list'); compareList.innerHTML = '

加载中...

'; fetch(`${API_BASE}`) .then(response => response.json()) .then(data => { if (data.success && data.data.length > 0) { compareList.innerHTML = ''; data.data.forEach(video => { const checkbox = document.createElement('div'); checkbox.className = 'video-checkbox-item'; checkbox.innerHTML = ` `; compareList.appendChild(checkbox); }); } else { compareList.innerHTML = '

暂无视频,请先上传视频

'; } }) .catch(error => { compareList.innerHTML = `

加载失败: ${error.message}

`; }); } function updateCompareButton() { const checked = document.querySelectorAll('#compare-video-list input[type="checkbox"]:checked'); const compareBtn = document.getElementById('compare-btn'); compareBtn.disabled = checked.length < 2; } function compareVideos() { const checked = document.querySelectorAll('#compare-video-list input[type="checkbox"]:checked'); if (checked.length < 2) { alert('请至少选择2个视频进行对比'); return; } if (!confirm(`确定要对比这 ${checked.length} 个视频吗?这可能需要一些时间。`)) { return; } const videoIds = Array.from(checked).map(cb => cb.value); const resultDiv = document.getElementById('compare-result'); resultDiv.innerHTML = '

对比中,请稍候...

'; resultDiv.className = 'result-message'; resultDiv.style.display = 'block'; fetch(`${API_BASE}/compare`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ video_ids: videoIds }) }) .then(response => response.json()) .then(data => { if (data.success) { resultDiv.className = 'result-message success'; resultDiv.innerHTML = `

对比结果

${data.data.comparison_result}
`; } else { resultDiv.className = 'result-message error'; resultDiv.textContent = data.message || '对比失败'; } }) .catch(error => { resultDiv.className = 'result-message error'; resultDiv.textContent = `对比失败: ${error.message}`; }); } function showResult(elementId, message, type) { const element = document.getElementById(elementId); element.textContent = message; element.className = `result-message ${type}`; element.style.display = 'block'; } // Initialize document.addEventListener('DOMContentLoaded', () => { loadVideos(); });