优化页面布局,修复故障视频拉动进度条的故障

This commit is contained in:
CN-JS-HuiBai
2026-04-04 13:58:12 +08:00
parent b8bd8a8d76
commit a6af3765a8
3 changed files with 87 additions and 102 deletions

View File

@@ -47,8 +47,6 @@
</label>
<div class="banner-actions">
<button id="refresh-btn" class="action-btn" title="刷新列表">刷新列表</button>
<button id="clear-download-cache-btn" class="action-btn" title="清空下载缓存">清空下载缓存</button>
<button id="clear-transcode-cache-btn" class="action-btn" title="清空转码缓存">清空转码缓存</button>
</div>
<div class="user-info">
<button id="logout-btn" class="action-btn danger">退出登录</button>

View File

@@ -2,8 +2,6 @@ document.addEventListener('DOMContentLoaded', () => {
const videoListEl = document.getElementById('video-list');
const loadingSpinner = document.getElementById('loading-spinner');
const refreshBtn = document.getElementById('refresh-btn');
const clearDownloadCacheBtn = document.getElementById('clear-download-cache-btn');
const clearTranscodeCacheBtn = document.getElementById('clear-transcode-cache-btn');
const bucketSelect = document.getElementById('bucket-select');
const loginScreen = document.getElementById('login-screen');
const appContainer = document.getElementById('app-container');
@@ -675,26 +673,7 @@ document.addEventListener('DOMContentLoaded', () => {
}
};
const clearDownloadCache = async () => {
if (!clearDownloadCacheBtn) return;
clearDownloadCacheBtn.disabled = true;
clearDownloadCacheBtn.textContent = '清空中...';
try {
const res = await fetch('/api/clear-download-cache', { method: 'POST' });
if (!res.ok) {
const data = await res.json().catch(() => ({}));
throw new Error(data.error || '清空下载缓存失败');
}
alert('下载缓存已清空');
} catch (err) {
console.error('Clear download cache failed:', err);
alert(`清空下载缓存失败: ${err.message}`);
} finally {
clearDownloadCacheBtn.disabled = false;
clearDownloadCacheBtn.textContent = '清空下载缓存';
}
};
if (transcodeBtn) {
transcodeBtn.addEventListener('click', () => {
@@ -734,7 +713,8 @@ document.addEventListener('DOMContentLoaded', () => {
// Build a tree structure from S3 keys
const tree = {};
data.videos.forEach(key => {
data.videos.forEach(vid => {
const key = vid.key;
const parts = key.split('/');
let current = tree;
parts.forEach((part, index) => {
@@ -743,15 +723,22 @@ document.addEventListener('DOMContentLoaded', () => {
}
if (index === parts.length - 1) {
current[part].__file = key;
current[part].__hasTranscodeCache = vid.hasTranscodeCache;
}
current = current[part];
});
});
const createFileItem = (name, key) => {
const createFileItem = (name, key, hasTranscodeCache) => {
const li = document.createElement('li');
li.className = 'video-item file-item';
const ext = name.split('.').pop().toUpperCase();
let cacheButtonHtml = '';
if (hasTranscodeCache) {
cacheButtonHtml = `<button class="action-btn danger clear-video-cache-btn" data-key="${key}" style="padding: 0.3rem 0.6rem; font-size: 0.75rem; margin-left: auto;" title="清空转码缓存">清空转码缓存</button>`;
}
li.innerHTML = `
<div class="video-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 8-6 4 6 4V8Z"/><rect width="14" height="12" x="2" y="6" rx="2" ry="2"/></svg>
@@ -760,19 +747,44 @@ document.addEventListener('DOMContentLoaded', () => {
<div class="video-title" title="${key}">${name}</div>
<div class="video-meta">Video / ${ext}</div>
</div>
${cacheButtonHtml}
`;
li.addEventListener('click', (e) => {
e.stopPropagation();
selectVideo(key, li);
});
const clearBtn = li.querySelector('.clear-video-cache-btn');
if (clearBtn) {
clearBtn.addEventListener('click', async (e) => {
e.stopPropagation();
clearBtn.disabled = true;
clearBtn.textContent = '清空中...';
try {
const res = await fetch('/api/clear-video-transcode-cache', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ bucket: selectedBucket, key: key })
});
if (!res.ok) throw new Error('Failed to clear cache');
fetchVideos(selectedBucket);
} catch (err) {
console.error(err);
alert('清空转码缓存失败: ' + err.message);
clearBtn.disabled = false;
clearBtn.textContent = '清空转码缓存';
}
});
}
return li;
};
const renderTree = (node, container) => {
for (const [name, value] of Object.entries(node)) {
if (name === '__file') continue;
if (name === '__file' || name === '__hasTranscodeCache') continue;
const childKeys = Object.keys(value).filter(key => key !== '__file');
const childKeys = Object.keys(value).filter(k => k !== '__file' && k !== '__hasTranscodeCache');
const hasChildren = childKeys.length > 0;
const isFile = typeof value.__file === 'string';
@@ -803,13 +815,13 @@ document.addEventListener('DOMContentLoaded', () => {
li.appendChild(folderHeader);
if (isFile) {
subListContainer.appendChild(createFileItem(name, value.__file));
subListContainer.appendChild(createFileItem(name, value.__file, value.__hasTranscodeCache));
}
renderTree(value, subListContainer);
li.appendChild(subListContainer);
container.appendChild(li);
} else if (isFile) {
container.appendChild(createFileItem(name, value.__file));
container.appendChild(createFileItem(name, value.__file, value.__hasTranscodeCache));
}
}
};
@@ -1100,29 +1112,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Bind events
refreshBtn.addEventListener('click', () => fetchVideos(selectedBucket));
if (clearDownloadCacheBtn) {
clearDownloadCacheBtn.addEventListener('click', clearDownloadCache);
}
if (clearTranscodeCacheBtn) {
clearTranscodeCacheBtn.addEventListener('click', async () => {
clearTranscodeCacheBtn.disabled = true;
clearTranscodeCacheBtn.textContent = '清空中...';
try {
const res = await fetch('/api/clear-transcode-cache', { method: 'POST' });
if (!res.ok) {
const data = await res.json().catch(() => ({}));
throw new Error(data.error || '清空转码缓存失败');
}
alert('转码缓存已清空');
} catch (err) {
console.error('Clear transcode cache failed:', err);
alert(`清空转码缓存失败: ${err.message}`);
} finally {
clearTranscodeCacheBtn.disabled = false;
clearTranscodeCacheBtn.textContent = '清空转码缓存';
}
});
}
if (stopTranscodeBtn) {
stopTranscodeBtn.addEventListener('click', stopTranscode);
}