修复布局

This commit is contained in:
CN-JS-HuiBai
2026-04-02 23:01:20 +08:00
parent 52c8466ddd
commit 47246061b2
3 changed files with 74 additions and 15 deletions

View File

@@ -616,7 +616,8 @@ header p {
position: relative; position: relative;
z-index: 12; z-index: 12;
margin: -5.75rem 1rem 0; margin: -5.75rem 1rem 0;
padding: 0.9rem 1rem; width: calc(100% - 2rem);
padding: 0.7rem 0.8rem;
border-radius: 14px; border-radius: 14px;
border: 1px solid var(--panel-border); border: 1px solid var(--panel-border);
background: linear-gradient(180deg, rgba(15, 23, 42, 0.18), rgba(15, 23, 42, 0.86)); background: linear-gradient(180deg, rgba(15, 23, 42, 0.18), rgba(15, 23, 42, 0.86));
@@ -642,7 +643,7 @@ header p {
.controls-right { .controls-right {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.75rem; gap: 0.5rem;
flex-wrap: nowrap; flex-wrap: nowrap;
flex: 0 0 auto; flex: 0 0 auto;
} }
@@ -708,12 +709,25 @@ header p {
background: rgba(30, 41, 59, 0.9); background: rgba(30, 41, 59, 0.9);
color: #f8fafc; color: #f8fafc;
border-radius: 999px; border-radius: 999px;
padding: 0.65rem 1rem; padding: 0.45rem 0.7rem;
font-size: 0.82rem;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease; transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
} }
.icon-btn {
min-width: 2rem;
width: 2rem;
height: 2rem;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 0.95rem;
line-height: 1;
}
.control-btn:hover { .control-btn:hover {
transform: translateY(-1px); transform: translateY(-1px);
background: rgba(51, 65, 85, 0.95); background: rgba(51, 65, 85, 0.95);
@@ -729,29 +743,42 @@ header p {
.volume-control { .volume-control {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.65rem; gap: 0.45rem;
min-width: 180px; min-width: 132px;
} }
.volume-slider { .volume-slider {
width: 96px; width: 72px;
accent-color: #60a5fa; accent-color: #60a5fa;
cursor: pointer; cursor: pointer;
} }
.volume-value { .volume-value {
min-width: 3.5rem; min-width: 2.7rem;
color: rgba(226, 232, 240, 0.88); color: rgba(226, 232, 240, 0.88);
font-size: 0.9rem; font-size: 0.8rem;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
.progress-chip {
display: inline-flex;
align-items: center;
padding: 0.34rem 0.55rem;
border-radius: 999px;
background: rgba(15, 23, 42, 0.7);
border: 1px solid rgba(148, 163, 184, 0.16);
color: rgba(226, 232, 240, 0.92);
font-size: 0.76rem;
font-weight: 600;
white-space: nowrap;
}
.speed-control { .speed-control {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
gap: 0.55rem; gap: 0.4rem;
color: rgba(226, 232, 240, 0.88); color: rgba(226, 232, 240, 0.88);
font-size: 0.9rem; font-size: 0.8rem;
font-weight: 600; font-weight: 600;
} }
@@ -760,7 +787,8 @@ header p {
border: 1px solid rgba(148, 163, 184, 0.24); border: 1px solid rgba(148, 163, 184, 0.24);
background: rgba(30, 41, 59, 0.9); background: rgba(30, 41, 59, 0.9);
color: #f8fafc; color: #f8fafc;
padding: 0.55rem 0.85rem; padding: 0.42rem 0.65rem;
font-size: 0.8rem;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
} }
@@ -997,6 +1025,7 @@ header p {
.custom-controls { .custom-controls {
align-items: center; align-items: center;
margin: -6.25rem 0.75rem 0; margin: -6.25rem 0.75rem 0;
width: calc(100% - 1.5rem);
} }
.controls-left, .controls-left,
@@ -1015,12 +1044,12 @@ header p {
.volume-control { .volume-control {
width: auto; width: auto;
min-width: 150px; min-width: 112px;
} }
.volume-slider { .volume-slider {
flex: 0 0 auto; flex: 0 0 auto;
width: 84px; width: 64px;
} }
.control-seek { .control-seek {

View File

@@ -127,11 +127,13 @@
</div> </div>
<div id="custom-controls" class="custom-controls hidden"> <div id="custom-controls" class="custom-controls hidden">
<div class="controls-left"> <div class="controls-left">
<button id="control-play-toggle" class="control-btn icon-btn" type="button" aria-label="Play">></button>
<div id="playback-status" class="playback-status paused"> <div id="playback-status" class="playback-status paused">
<span class="status-dot"></span> <span class="status-dot"></span>
<span id="playback-status-text">Paused</span> <span id="playback-status-text">Paused</span>
</div> </div>
<button id="control-play-toggle" class="control-btn" type="button">Play</button> <div id="transcode-progress-chip" class="progress-chip">Transcode 0%</div>
<div id="playback-progress-chip" class="progress-chip">Play 0%</div>
<button id="control-mute-toggle" class="control-btn" type="button">Mute</button> <button id="control-mute-toggle" class="control-btn" type="button">Mute</button>
<div class="volume-control"> <div class="volume-control">
<input id="volume-slider" class="volume-slider" type="range" min="0" max="1" step="0.05" value="1" /> <input id="volume-slider" class="volume-slider" type="range" min="0" max="1" step="0.05" value="1" />

View File

@@ -31,6 +31,8 @@ document.addEventListener('DOMContentLoaded', () => {
const playbackStatus = document.getElementById('playback-status'); const playbackStatus = document.getElementById('playback-status');
const playbackStatusText = document.getElementById('playback-status-text'); const playbackStatusText = document.getElementById('playback-status-text');
const playbackSpeed = document.getElementById('playback-speed'); const playbackSpeed = document.getElementById('playback-speed');
const transcodeProgressChip = document.getElementById('transcode-progress-chip');
const playbackProgressChip = document.getElementById('playback-progress-chip');
// Download phase elements // Download phase elements
const downloadPhase = document.getElementById('download-phase'); const downloadPhase = document.getElementById('download-phase');
@@ -127,7 +129,8 @@ document.addEventListener('DOMContentLoaded', () => {
const updatePlayControls = () => { const updatePlayControls = () => {
if (controlPlayToggle) { if (controlPlayToggle) {
controlPlayToggle.textContent = videoPlayer.paused ? 'Play' : 'Pause'; controlPlayToggle.textContent = videoPlayer.paused ? '>' : '||';
controlPlayToggle.setAttribute('aria-label', videoPlayer.paused ? 'Play' : 'Pause');
} }
if (playbackStatus) { if (playbackStatus) {
playbackStatus.classList.remove('playing', 'paused', 'seeking'); playbackStatus.classList.remove('playing', 'paused', 'seeking');
@@ -166,6 +169,19 @@ document.addEventListener('DOMContentLoaded', () => {
} }
}; };
const updatePlaybackProgressChip = (absoluteTime = 0) => {
if (!playbackProgressChip) return;
const safeDuration = videoDuration > 0 ? videoDuration : 0;
const percent = safeDuration > 0 ? Math.min(Math.max(Math.round((absoluteTime / safeDuration) * 100), 0), 100) : 0;
playbackProgressChip.textContent = `Play ${percent}%`;
};
const updateTranscodeProgressChip = (percent = 0, label = 'Transcode') => {
if (!transcodeProgressChip) return;
const safePercent = Math.min(Math.max(Math.round(percent || 0), 0), 100);
transcodeProgressChip.textContent = `${label} ${safePercent}%`;
};
const showCustomControls = () => { const showCustomControls = () => {
if (customControls) { if (customControls) {
customControls.classList.remove('hidden'); customControls.classList.remove('hidden');
@@ -238,6 +254,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (seekTotalTime) seekTotalTime.textContent = formatTime(videoDuration); if (seekTotalTime) seekTotalTime.textContent = formatTime(videoDuration);
showSeekBar(); showSeekBar();
updateSeekBarPosition(seekOffset + (videoPlayer.currentTime || 0)); updateSeekBarPosition(seekOffset + (videoPlayer.currentTime || 0));
updatePlaybackProgressChip(seekOffset + (videoPlayer.currentTime || 0));
} }
if (message.type === 'progress') { if (message.type === 'progress') {
handleProgress(message.progress); handleProgress(message.progress);
@@ -258,6 +275,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (status === 'downloading') { if (status === 'downloading') {
showDownloadPhase(); showDownloadPhase();
const percent = Math.min(Math.max(Math.round(progress.percent || 0), 0), 100); const percent = Math.min(Math.max(Math.round(progress.percent || 0), 0), 100);
updateTranscodeProgressChip(percent, 'Download');
const downloaded = formatBytes(progress.downloadedBytes || 0); const downloaded = formatBytes(progress.downloadedBytes || 0);
const total = formatBytes(progress.totalBytes || 0); const total = formatBytes(progress.totalBytes || 0);
downloadSizeText.textContent = `${downloaded} / ${total}`; downloadSizeText.textContent = `${downloaded} / ${total}`;
@@ -265,6 +283,7 @@ document.addEventListener('DOMContentLoaded', () => {
downloadProgressFill.style.width = `${percent}%`; downloadProgressFill.style.width = `${percent}%`;
} else if (status === 'downloaded') { } else if (status === 'downloaded') {
showDownloadPhase(); showDownloadPhase();
updateTranscodeProgressChip(100, 'Download');
const downloaded = formatBytes(progress.downloadedBytes || progress.totalBytes || 0); const downloaded = formatBytes(progress.downloadedBytes || progress.totalBytes || 0);
const total = formatBytes(progress.totalBytes || 0); const total = formatBytes(progress.totalBytes || 0);
downloadSizeText.textContent = `${downloaded} / ${total} — 下载完成`; downloadSizeText.textContent = `${downloaded} / ${total} — 下载完成`;
@@ -276,6 +295,7 @@ document.addEventListener('DOMContentLoaded', () => {
} else if (status === 'transcoding') { } else if (status === 'transcoding') {
showTranscodePhase(); showTranscodePhase();
const percent = Math.min(Math.max(Math.round(progress.percent || 0), 0), 100); const percent = Math.min(Math.max(Math.round(progress.percent || 0), 0), 100);
updateTranscodeProgressChip(percent, 'Transcode');
transcodeProgressText.textContent = `${percent}%`; transcodeProgressText.textContent = `${percent}%`;
transcodeProgressFill.style.width = `${percent}%`; transcodeProgressFill.style.width = `${percent}%`;
transcodeDetailText.textContent = progress.details || 'FFmpeg 转码中...'; transcodeDetailText.textContent = progress.details || 'FFmpeg 转码中...';
@@ -288,13 +308,16 @@ document.addEventListener('DOMContentLoaded', () => {
} }
} else if (status === 'finished') { } else if (status === 'finished') {
showTranscodePhase(); showTranscodePhase();
updateTranscodeProgressChip(100, 'Transcode');
transcodeProgressText.textContent = '100%'; transcodeProgressText.textContent = '100%';
transcodeProgressFill.style.width = '100%'; transcodeProgressFill.style.width = '100%';
transcodeDetailText.textContent = '转码完成'; transcodeDetailText.textContent = '转码完成';
} else if (status === 'failed') { } else if (status === 'failed') {
updateTranscodeProgressChip(progress.percent || 0, 'Failed');
transcodeDetailText.textContent = `失败: ${progress.details || '未知错误'}`; transcodeDetailText.textContent = `失败: ${progress.details || '未知错误'}`;
transcodeProgressFill.style.background = 'linear-gradient(90deg, #dc2626, #b91c1c)'; transcodeProgressFill.style.background = 'linear-gradient(90deg, #dc2626, #b91c1c)';
} else if (status === 'cancelled') { } else if (status === 'cancelled') {
updateTranscodeProgressChip(0, 'Stopped');
transcodeDetailText.textContent = '已取消'; transcodeDetailText.textContent = '已取消';
transcodeProgressFill.style.width = '0%'; transcodeProgressFill.style.width = '0%';
} }
@@ -327,6 +350,8 @@ document.addEventListener('DOMContentLoaded', () => {
if (statFps) statFps.textContent = ''; if (statFps) statFps.textContent = '';
if (statBitrate) statBitrate.textContent = ''; if (statBitrate) statBitrate.textContent = '';
if (statTime) statTime.textContent = ''; if (statTime) statTime.textContent = '';
updateTranscodeProgressChip(0, 'Transcode');
updatePlaybackProgressChip(0);
if (stopTranscodeBtn) { if (stopTranscodeBtn) {
stopTranscodeBtn.classList.add('hidden'); stopTranscodeBtn.classList.add('hidden');
@@ -352,6 +377,7 @@ document.addEventListener('DOMContentLoaded', () => {
seekBarProgress.style.width = `${ratio * 100}%`; seekBarProgress.style.width = `${ratio * 100}%`;
seekBarHandle.style.left = `${ratio * 100}%`; seekBarHandle.style.left = `${ratio * 100}%`;
seekCurrentTime.textContent = formatTime(absoluteTime); seekCurrentTime.textContent = formatTime(absoluteTime);
updatePlaybackProgressChip(absoluteTime);
}; };
// Track playback position in the custom seek bar // Track playback position in the custom seek bar
@@ -1077,6 +1103,8 @@ document.addEventListener('DOMContentLoaded', () => {
updatePlayControls(); updatePlayControls();
updateVolumeControls(); updateVolumeControls();
updateFullscreenControls(); updateFullscreenControls();
updateTranscodeProgressChip(0, 'Transcode');
updatePlaybackProgressChip(0);
// Bind events // Bind events
refreshBtn.addEventListener('click', () => fetchVideos(selectedBucket)); refreshBtn.addEventListener('click', () => fetchVideos(selectedBucket));