修复前端api和后端http压缩BUG

This commit is contained in:
user123456
2025-06-12 13:10:39 +08:00
parent 8697a8dc29
commit 913ac6b738
5 changed files with 149 additions and 49 deletions
+9
View File
@@ -363,6 +363,15 @@
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* 黑夜模式下的Docker按钮样式 */
.dark .docker-button {
background: linear-gradient(135deg, #374151, #4b5563);
}
.dark .docker-button:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
/* 模态框设计 */
.modal {
position: fixed;
+27 -14
View File
@@ -855,14 +855,14 @@
elements.backToSearch.classList.remove('show');
try {
const response = await fetch(`/api/search?q=${encodeURIComponent(term)}&page=${page}`);
const response = await fetch(`/search?q=${encodeURIComponent(term)}&page=${page}`);
const data = await response.json();
if (data.success) {
if (data && data.results) {
searchResults = data.results;
displaySearchResults(data.results, data.total, page);
displaySearchResults(data.results, data.count, page);
} else {
showToast('搜索失败:' + (data.message || '未知错误'), 'error');
showToast('搜索失败:' + (data.error || '未知错误'), 'error');
}
} catch (error) {
console.error('搜索错误:', error);
@@ -894,7 +894,7 @@
function createResultCard(result) {
const card = document.createElement('div');
card.className = 'result-card';
card.onclick = () => viewImageTags(result.name);
card.onclick = () => viewImageTags(result.repo_name || result.name);
const badges = [];
if (result.is_official) badges.push('<span class="badge badge-official">官方</span>');
@@ -902,21 +902,21 @@
card.innerHTML = `
<div class="result-title">
🐳 ${result.name}
🐳 ${result.repo_name || result.name}
${badges.join('')}
</div>
<div class="result-description">
${result.description || '暂无描述'}
${result.short_description || result.description || '暂无描述'}
</div>
<div class="result-meta">
<div class="meta-stats">
<div class="meta-item">
<span>📈</span>
${formatUtils.formatNumber(result.star_count)} Stars
${formatUtils.formatNumber(result.star_count || 0)} Stars
</div>
<div class="meta-item">
<span>📥</span>
${formatUtils.formatNumber(result.pull_count)} Pulls
${formatUtils.formatNumber(result.pull_count || 0)} Pulls
</div>
</div>
</div>
@@ -934,15 +934,28 @@
elements.searchResults.classList.remove('show');
try {
const response = await fetch(`/api/tags?image=${encodeURIComponent(imageName)}`);
// 解析镜像名称
let namespace = 'library';
let repoName = imageName;
if (imageName.includes('/')) {
const parts = imageName.split('/');
namespace = parts[0];
repoName = parts[1];
} else {
// 官方镜像
namespace = 'library';
}
const response = await fetch(`/tags/${namespace}/${repoName}`);
const data = await response.json();
if (data.success) {
allTags = data.tags;
displayImageTags(imageName, data.tags);
if (Array.isArray(data)) {
allTags = data;
displayImageTags(imageName, data);
elements.backToSearch.classList.add('show');
} else {
showToast('获取标签失败:' + (data.message || '未知错误'), 'error');
showToast('获取标签失败:' + (data.error || '未知错误'), 'error');
}
} catch (error) {
console.error('获取标签错误:', error);
+54 -16
View File
@@ -364,6 +364,18 @@
transform: none;
}
.input-info {
padding: 0.75rem 1rem;
background-color: var(--muted);
border: 1px solid var(--border);
border-radius: var(--radius);
color: var(--muted-foreground);
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
/* 架构选择区域 */
.arch-buttons {
display: flex;
@@ -679,11 +691,9 @@
<div class="form-group">
<label class="form-label">输出格式</label>
<select class="select" id="formatSelect">
<option value="docker-archive">Docker Archive (.tar)</option>
<option value="oci-archive">OCI Archive (.tar)</option>
<option value="dir">目录格式</option>
</select>
<div class="input-info">
📦 系统自动使用 Docker Archive (.tar) 格式
</div>
</div>
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
@@ -767,7 +777,6 @@
const elements = {
imageListInput: document.getElementById('imageListInput'),
architectureInput: document.getElementById('architectureInput'),
formatSelect: document.getElementById('formatSelect'),
startDownload: document.getElementById('startDownload'),
pauseDownload: document.getElementById('pauseDownload'),
stopDownload: document.getElementById('stopDownload'),
@@ -898,7 +907,6 @@
async function startDownload() {
const imageList = parseImageList(elements.imageListInput.value);
const architecture = elements.architectureInput.value.trim();
const format = elements.formatSelect.value;
if (imageList.length === 0) {
showToast('请输入要下载的镜像列表', 'error');
@@ -915,7 +923,6 @@
id: index,
image: image,
architecture: architecture,
format: format,
status: 'pending'
}));
@@ -959,26 +966,26 @@
try {
// 调用后端API开始下载
const response = await fetch('/api/skopeo/download', {
const response = await fetch('/api/download', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
image: task.image,
architecture: task.architecture,
format: task.format
images: [task.image],
platform: task.architecture
})
});
const result = await response.json();
if (result.success) {
task.status = 'completed';
updateTaskStatus(currentTaskIndex, 'completed', '下载完成');
if (result.taskId) {
// 下载任务已创建,等待完成
task.taskId = result.taskId;
await waitForTaskCompletion(task);
} else {
task.status = 'failed';
updateTaskStatus(currentTaskIndex, 'failed', result.message || '下载失败');
updateTaskStatus(currentTaskIndex, 'failed', result.error || '下载失败');
}
} catch (error) {
console.error('下载错误:', error);
@@ -995,6 +1002,37 @@
}
}
// 等待任务完成
async function waitForTaskCompletion(task) {
return new Promise((resolve) => {
const checkStatus = async () => {
try {
const response = await fetch(`/api/task/${task.taskId}`);
const data = await response.json();
if (data.status === 'completed') {
task.status = 'completed';
updateTaskStatus(currentTaskIndex, 'completed', '下载完成');
resolve();
} else if (data.status === 'failed') {
task.status = 'failed';
updateTaskStatus(currentTaskIndex, 'failed', '下载失败');
resolve();
} else {
// 继续检查
setTimeout(checkStatus, 2000);
}
} catch (error) {
task.status = 'failed';
updateTaskStatus(currentTaskIndex, 'failed', '状态查询失败');
resolve();
}
};
checkStatus();
});
}
// 暂停下载
function pauseDownload() {
isDownloading = false;