Files
2025-01-12 05:13:22 +00:00

461 lines
18 KiB
JavaScript

const API_ENDPOINT = 'https://dev.obscura.work/v1';
// 确保 selectedLang 在 module.js 中可用
if (typeof selectedLang === 'undefined') {
selectedLang = 'zh'; // 如果未定义,设置默认值
}
async function showFeature() {
try {
const userInfo = await fetchUserInfo();
if (!userInfo) {
alert(lang[selectedLang].pleaseLogin);
window.location.href = 'login.html';
return;
}
// 检查邮箱验证状态
const emailVerified = userInfo.email_verified === 'True' || userInfo.email_verified === true;
console.log('Email Verified:', emailVerified); // 打印邮箱验证状态
if (!emailVerified ) {
alert(lang[selectedLang].pleaseVerifyEmail);
showUserCenterSection('profile');
return;
}
// 如果用户已登录且邮箱已验证,继续显示功能
const chatContent = document.getElementById('chatContent');
const dashboardContent = document.getElementById('dashboardContent');
const usersContent = document.getElementById('usersContent');
const pageTitle = document.getElementById('pageTitle');
const featureContent = document.getElementById('featureContent');
const userCenterContent = document.getElementById('userCenterContent');
const apiKeyInput = document.getElementById('apiKeyInput');
const showApiDocs = document.getElementById('showApiDocs');
const apiDocsContent = document.getElementById('apiDocsContent');
if (apiDocsContent) apiDocsContent.style.display = 'none';
if (featureContent) featureContent.style.display = 'flex';
if (chatContent) chatContent.style.display = 'none';
if (dashboardContent) dashboardContent.style.display = 'none';
if (usersContent) usersContent.style.display = 'none';
if (userCenterContent) userCenterContent.style.display = 'none';
if (showApiDocs) showApiDocs.style.display = 'none';
if (pageTitle) pageTitle.innerText = lang[selectedLang].featureDemo;
} catch (error) {
console.error('Error in showFeature:', error);
alert(lang[selectedLang].errorGettingUserInfo);
}
}
function displayTokenUsage(data) {
console.log(lang[selectedLang].tokenUsage, data);
}
document.addEventListener('DOMContentLoaded', function() {
// 首先声明所有需要的变量
const aiInput = document.getElementById('aiInput');
const fileInput = document.getElementById('fileInput');
const fileInputButton = document.getElementById('fileInputButton');
const takePictureButton = document.getElementById('takePictureButton');
const recordVideoButton = document.getElementById('recordVideoButton');
const clearButton = document.getElementById('clearButton');
const stopRecordingButton = document.getElementById('stopRecordingButton');
const previewArea = document.getElementById('previewArea');
const resultArea = document.getElementById('resultArea');
const loadingIndicator = document.getElementById('loadingIndicator');
const poseButton = document.getElementById('poseButton');
const fallButton = document.getElementById('fallButton');
const cpmButton = document.getElementById('cpmButton');
const objectButton = document.getElementById('objectButton');
const faceButton = document.getElementById('faceButton');
const compareButton = document.getElementById('compareButton');
const mediapipeButton = document.getElementById('mediapipeButton');
const qwenvlButton = document.getElementById('qwenvlButton');
const cpmanalyzeButton = document.getElementById('cpmanalyzeButton');
const qwenvlanalyzeButton = document.getElementById('qwenvlanalyzeButton');
let mediaRecorder;
let recordedChunks = [];
// 定义任务类型
const TASK_TYPES = {
POSE: 'pose',
CPM: 'cpm',
QWENVL: 'qwenvl',
YOLO: 'yolo',
FALL: 'fall',
FACE: 'face',
MEDIAPIPE: 'mediapipe',
COMPARE: 'compare',
CPM_ANALYZE: 'cpm_analyze',
QWENVL_ANALYZE: 'qwenvl_analyze'
};
// 然后添加事件监听器
if (fileInput) {
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
previewArea.innerHTML = '';
if (file.type.startsWith('image/')) {
const img = document.createElement('img');
img.src = e.target.result;
previewArea.appendChild(img);
} else if (file.type.startsWith('video/')) {
const video = document.createElement('video');
video.src = e.target.result;
video.controls = true;
previewArea.appendChild(video);
}
}
reader.readAsDataURL(file);
}
});
}
if (fileInputButton) {
fileInputButton.addEventListener('click', function() {
fileInput.click();
});
}
function uploadFile(taskType) {
const file = fileInput.files[0];
console.log("Selected file:", file);
const apiKey = apiKeyInput.value.trim();
console.log("API Key:", apiKey);
if (!file) {
alert(lang[selectedLang].pleaseSelectFile);
return;
}
if (!apiKey) {
alert(lang[selectedLang].pleaseEnterApiKey);
return;
}
loadingIndicator.style.display = 'block';
disableAllButtons();
const formData = new FormData();
formData.append('file', file);
console.log(`Sending request to: ${API_ENDPOINT}/${taskType}`);
fetch(`${API_ENDPOINT}/${taskType}`, {
method: 'POST',
body: formData,
headers: {
'Authorization': `Bearer ${apiKey}`
}
})
.then(response => response.json())
.then(data => {
console.log('Upload response:', data);
if (data.task_id) {
pollResult(data.task_id, apiKey, taskType);
displayTokenUsage(data);
}
})
.catch(error => {
console.error('Error:', error);
alert(lang[selectedLang].errorUploadingFile);
loadingIndicator.style.display = 'none';
enableAllButtons();
});
}
// 新的轮询函数
function pollResult(taskId, apiKey, taskType) {
const pollInterval = setInterval(() => {
fetch(`${API_ENDPOINT}/result/${taskId}`, {
headers: {
'Authorization': `Bearer ${apiKey}`
}
})
.then(response => response.json())
.then(data => {
console.log('Poll response:', data);
if (data.status === 'completed') {
clearInterval(pollInterval);
addResultCard(getAnalysisTitle(taskType), data);
if (taskType !== 'cpm' && taskType !== 'qwenvl' && taskType !== 'qwenvl_analyze' && taskType !== 'cpm_analyze') {
fetchAnnotatedFile(API_ENDPOINT, taskId, apiKey);
}
loadingIndicator.style.display = 'none';
enableAllButtons();
} else if (data.status === 'failed') {
clearInterval(pollInterval);
alert(lang[selectedLang].processingFailed);
loadingIndicator.style.display = 'none';
enableAllButtons();
}
})
.catch(error => {
console.error('Error:', error);
clearInterval(pollInterval);
alert(lang[selectedLang].errorGettingResults);
loadingIndicator.style.display = 'none';
enableAllButtons();
});
}, 2000); // 每2秒轮询一次
}
// 辅助函数
function getAnalysisTitle(analysisType) {
switch(analysisType) {
case 'pose': return '姿态分析';
case 'fall': return '跌倒检测';
case 'cpm': return 'MiniCPM内容分析';
case 'object': return '目标检测';
case 'face': return '人脸检测';
case 'compare': return '面部特征提取';
case 'mediapipe': return 'mediapipe面部识别';
case 'qwenvl': return 'Qwen内容分析';
case 'qwenvl_analyze': return 'qwenvl_OCR分析';
case 'cpm_analyze': return 'cpm_OCR分析';
default: return '分析结果';
}
}
function fetchAnnotatedFile(apiEndpoint, taskId, apiKey) {
fetch(`${apiEndpoint}/annotated/${taskId}`, {
headers: {
'Authorization': `Bearer ${apiKey}`
}
})
.then(response => {
if (response.ok) {
return response.blob();
}
if (response.status === 404) {
throw new Error(lang[selectedLang].resultImageNotFound);
}
throw new Error('Network response was not ok.');
})
.then(blob => {
const url = URL.createObjectURL(blob);
updatePreviewWithAnnotated(url, `result_${taskId}.png`);
})
.catch(error => {
console.error('Error:', error);
if (error.message === lang[selectedLang].resultImageNotFound) {
alert(lang[selectedLang].resultImageNotFound);
} else {
alert(lang[selectedLang].errorGettingResultImage);
}
});
}
function addResultCard(title, data) {
const card = document.createElement('div');
card.className = 'result-card';
card.innerHTML = `
<h3>${title}</h3>
<pre>${JSON.stringify(data, null, 2)}</pre>
`;
resultArea.innerHTML = `<h3>${lang[selectedLang].detectionResult}</h3>`; // 保留标题
resultArea.appendChild(card);
}
function updatePreviewWithAnnotated(url, filename) {
previewArea.innerHTML = '';
const isImage = filename.match(/\.(jpg|jpeg|png|gif)$/i);
if (isImage) {
const img = document.createElement('img');
img.src = url;
img.alt = "Annotated Image";
img.style.maxWidth = "100%";
previewArea.appendChild(img);
} else {
const video = document.createElement('video');
video.src = url;
video.controls = true;
video.style.maxWidth = "100%";
previewArea.appendChild(video);
}
}
function clearAll() {
aiInput.value = '';
fileInput.value = '';
previewArea.innerHTML = '<p>请输入图片URL或上传图片</p>';
resultArea.innerHTML = '<h3>检测结果</h3>';
loadingIndicator.style.display = 'none';
enableAllButtons();
}
function disableAllButtons() {
poseButton.disabled = true;
fallButton.disabled = true;
cpmButton.disabled = true;
objectButton.disabled = true;
faceButton.disabled = true;
qwenvlButton.disabled = true;
mediapipeButton.disabled = true;
takePictureButton.disabled = true;
recordVideoButton.disabled = true;
compareButton.disabled = true;
qwenvlanalyzeButton.disabled =true;
cpmanalyzeButton.disabled = true
}
function enableAllButtons() {
poseButton.disabled = false;
fallButton.disabled = false;
cpmButton.disabled = false;
objectButton.disabled = false;
faceButton.disabled = false;
qwenvlButton.disabled = false;
mediapipeButton.disabled = false;
takePictureButton.disabled = false;
recordVideoButton.disabled = false;
compareButton.disabled = false;
qwenvlanalyzeButton.disabled =false;
cpmanalyzeButton.disabled = false
}
function takePicture() {
navigator.mediaDevices.getUserMedia({ video: true })
.then(function(stream) {
const video = document.createElement('video');
video.srcObject = stream;
video.play();
video.onloadedmetadata = function(e) {
const canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
stream.getTracks().forEach(track => track.stop());
previewArea.innerHTML = '';
const img = document.createElement('img');
img.src = canvas.toDataURL('image/jpeg');
previewArea.appendChild(img);
canvas.toBlob(function(blob) {
const file = new File([blob], "camera_photo.jpg", { type: "image/jpeg" });
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
fileInput.files = dataTransfer.files;
}, 'image/jpeg');
};
})
.catch(function(err) {
console.error(lang[selectedLang].cameraAccessFailed, err);
alert(lang[selectedLang].cameraPermissionDenied);
});
}
function startRecording() {
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(function(stream) {
previewArea.innerHTML = '<video id="liveVideo" autoplay muted></video>';
const liveVideo = document.getElementById('liveVideo');
liveVideo.srcObject = stream;
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
};
mediaRecorder.onstop = function() {
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const videoURL = URL.createObjectURL(blob);
previewArea.innerHTML = '<video id="recordedVideo" controls></video>';
const recordedVideo = document.getElementById('recordedVideo');
recordedVideo.src = videoURL;
const file = new File([blob], "camera_video.webm", { type: "video/webm" });
const dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
fileInput.files = dataTransfer.files;
stream.getTracks().forEach(track => track.stop());
};
mediaRecorder.start();
recordVideoButton.style.display = 'none';
stopRecordingButton.style.display = 'block';
setTimeout(() => {
if (mediaRecorder.state === 'recording') {
stopRecording();
}
}, 15000);
})
.catch(function(err) {
console.error(lang[selectedLang].cameraAccessFailed, err);
alert(lang[selectedLang].cameraPermissionDenied);
});
}
function stopRecording() {
if (mediaRecorder && mediaRecorder.state === 'recording') {
mediaRecorder.stop();
recordVideoButton.style.display = 'block';
stopRecordingButton.style.display = 'none';
}
}
// 最后添加其他按钮的事件监听器
if (recordVideoButton) recordVideoButton.addEventListener('click', startRecording);
if (stopRecordingButton) stopRecordingButton.addEventListener('click', stopRecording);
if (clearButton) clearButton.addEventListener('click', clearAll);
if (takePictureButton) takePictureButton.addEventListener('click', takePicture);
if (poseButton) poseButton.addEventListener('click', () => uploadFile(TASK_TYPES.POSE));
if (fallButton) fallButton.addEventListener('click', () => uploadFile(TASK_TYPES.FALL));
if (objectButton) objectButton.addEventListener('click', () => uploadFile(TASK_TYPES.YOLO));
if (faceButton) faceButton.addEventListener('click', () => uploadFile(TASK_TYPES.FACE));
if (compareButton) compareButton.addEventListener('click', () => uploadFile(TASK_TYPES.COMPARE));
if (mediapipeButton) mediapipeButton.addEventListener('click', () => uploadFile(TASK_TYPES.MEDIAPIPE));
if (cpmButton) cpmButton.addEventListener('click', () => uploadFile(TASK_TYPES.CPM));
if (qwenvlButton) qwenvlButton.addEventListener('click', () => uploadFile(TASK_TYPES.QWENVL));
if (qwenvlanalyzeButton) qwenvlanalyzeButton.addEventListener('click', () => uploadFile(TASK_TYPES.QWENVL_ANALYZE));
if (cpmanalyzeButton) cpmanalyzeButton.addEventListener('click', () => uploadFile(TASK_TYPES.CPM_ANALYZE));
});
// 获取用户信息的函数
async function fetchUserInfo() {
try {
const token = localStorage.getItem('access_token');
if (!token) {
console.error('No access token found');
return null;
}
const response = await fetch(`${BASE_URL}/me`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
throw new Error('Failed to fetch user info');
}
const userInfo = await response.json();
return userInfo;
} catch (error) {
console.error('Error fetching user info:', error);
// 可以在这里处理错误,比如清除 token 并重定向到登录页面
localStorage.removeItem('access_token');
window.location.href = 'login.html'; // 重定向到登录页面
return null;
}
}