This commit is contained in:
CN-JS-HuiBai
2026-04-02 19:32:36 +08:00
parent f991125923
commit 1580b589c0
4 changed files with 248 additions and 39 deletions

View File

@@ -3,8 +3,13 @@ document.addEventListener('DOMContentLoaded', () => {
const loadingSpinner = document.getElementById('loading-spinner');
const refreshBtn = document.getElementById('refresh-btn');
const resetCacheBtn = document.getElementById('reset-cache-btn');
const usernameInput = document.getElementById('s3-username');
const passwordInput = document.getElementById('s3-password');
const bucketSelect = document.getElementById('bucket-select');
const loginScreen = document.getElementById('login-screen');
const appContainer = document.getElementById('app-container');
const loginUsernameInput = document.getElementById('login-username');
const loginPasswordInput = document.getElementById('login-password');
const loginBtn = document.getElementById('login-btn');
const loginError = document.getElementById('login-error');
const codecSelect = document.getElementById('codec-select');
const encoderSelect = document.getElementById('encoder-select');
const playerOverlay = document.getElementById('player-overlay');
@@ -20,11 +25,13 @@ document.addEventListener('DOMContentLoaded', () => {
const topBanner = document.getElementById('top-banner');
let currentPollInterval = null;
let selectedBucket = null;
let selectedKey = null;
let ws = null;
let wsConnected = false;
let subscribedKey = null;
let currentVideoKey = null;
let s3AuthHeaders = {};
const sendWsMessage = (message) => {
if (ws && ws.readyState === WebSocket.OPEN) {
@@ -108,19 +115,86 @@ document.addEventListener('DOMContentLoaded', () => {
progressFill.style.width = '0%';
};
const getS3AuthHeaders = () => {
const headers = {};
const username = usernameInput?.value?.trim();
const password = passwordInput?.value || '';
if (username) headers['X-S3-Username'] = username;
if (password) headers['X-S3-Password'] = password;
return headers;
const setAuthHeaders = (username, password) => {
s3AuthHeaders = {};
if (username) s3AuthHeaders['X-S3-Username'] = username;
if (password) s3AuthHeaders['X-S3-Password'] = password;
};
const getS3AuthPayload = () => ({
username: usernameInput?.value?.trim() || '',
password: passwordInput?.value || ''
});
const showLogin = () => {
if (loginScreen) loginScreen.classList.remove('hidden');
if (appContainer) appContainer.classList.add('hidden');
};
const showApp = () => {
if (loginScreen) loginScreen.classList.add('hidden');
if (appContainer) appContainer.classList.remove('hidden');
};
const renderBuckets = (buckets) => {
if (!bucketSelect) return;
bucketSelect.innerHTML = '<option value="" disabled selected>Choose a bucket</option>';
buckets.forEach(bucket => {
const option = document.createElement('option');
option.value = bucket.Name;
option.textContent = bucket.Name;
bucketSelect.appendChild(option);
});
};
const showLoginError = (message) => {
if (!loginError) return;
loginError.textContent = message;
loginError.classList.remove('hidden');
};
const clearLoginError = () => {
if (!loginError) return;
loginError.textContent = '';
loginError.classList.add('hidden');
};
const login = async () => {
if (!loginUsernameInput || !loginPasswordInput) return;
const username = loginUsernameInput.value.trim();
const password = loginPasswordInput.value;
if (!username || !password) {
showLoginError('Please enter both access key and secret key.');
return;
}
loginBtn.disabled = true;
loginBtn.textContent = 'Logging in...';
clearLoginError();
try {
setAuthHeaders(username, password);
const res = await fetch('/api/buckets', { headers: s3AuthHeaders });
if (!res.ok) {
const data = await res.json().catch(() => ({}));
throw new Error(data.error || 'Login failed');
}
const data = await res.json();
if (!Array.isArray(data.buckets) || data.buckets.length === 0) {
throw new Error('No buckets available for this account');
}
renderBuckets(data.buckets);
showApp();
selectedBucket = data.buckets[0].Name;
if (bucketSelect) bucketSelect.value = selectedBucket;
loadConfig();
connectWebSocket();
await fetchVideos(selectedBucket);
} catch (err) {
console.error('Login error:', err);
showLoginError(err.message);
setAuthHeaders('', '');
} finally {
if (loginBtn) {
loginBtn.disabled = false;
loginBtn.textContent = 'Login';
}
}
};
const resetCache = async () => {
if (!resetCacheBtn) return;
@@ -175,13 +249,16 @@ document.addEventListener('DOMContentLoaded', () => {
}
// Fetch list of videos from the backend
const fetchVideos = async () => {
const fetchVideos = async (bucket) => {
if (!bucket) {
return;
}
videoListEl.classList.add('hidden');
loadingSpinner.classList.remove('hidden');
videoListEl.innerHTML = '';
try {
const res = await fetch('/api/videos', { headers: getS3AuthHeaders() });
const res = await fetch(`/api/videos?bucket=${encodeURIComponent(bucket)}`, { headers: s3AuthHeaders });
if (!res.ok) throw new Error('Failed to fetch videos. Check S3 Config.');
const data = await res.json();
@@ -328,11 +405,11 @@ document.addEventListener('DOMContentLoaded', () => {
try {
const codec = codecSelect?.value || 'h264';
const encoder = encoderSelect?.value || 'software';
const authPayload = getS3AuthPayload();
if (!selectedBucket) throw new Error('No bucket selected');
const res = await fetch('/api/transcode', {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...getS3AuthHeaders() },
body: JSON.stringify({ key: selectedKey, codec, encoder, ...authPayload })
headers: { 'Content-Type': 'application/json', ...s3AuthHeaders },
body: JSON.stringify({ bucket: selectedBucket, key: selectedKey, codec, encoder })
});
const data = await res.json();
@@ -403,10 +480,17 @@ document.addEventListener('DOMContentLoaded', () => {
};
// Bind events
refreshBtn.addEventListener('click', fetchVideos);
refreshBtn.addEventListener('click', () => fetchVideos(selectedBucket));
if (loginBtn) {
loginBtn.addEventListener('click', login);
}
if (bucketSelect) {
bucketSelect.addEventListener('change', async (event) => {
selectedBucket = event.target.value;
await fetchVideos(selectedBucket);
});
}
// Connect WebSocket and initial load
connectWebSocket();
loadConfig();
fetchVideos();
// Initial state: require login before loading data
showLogin();
});