搜索镜像完善
This commit is contained in:
@@ -512,16 +512,70 @@
|
||||
prevButton.disabled = currentPage <= 1;
|
||||
nextButton.disabled = currentPage >= totalPages;
|
||||
|
||||
// 添加页码显示
|
||||
// 添加页码显示和快速跳转
|
||||
const paginationDiv = document.querySelector('.pagination');
|
||||
const pageInfo = document.getElementById('pageInfo');
|
||||
let pageInfo = document.getElementById('pageInfo');
|
||||
if (!pageInfo) {
|
||||
const infoSpan = document.createElement('span');
|
||||
infoSpan.id = 'pageInfo';
|
||||
infoSpan.style.margin = '0 10px';
|
||||
paginationDiv.insertBefore(infoSpan, nextButton);
|
||||
const container = document.createElement('div');
|
||||
container.id = 'pageInfo';
|
||||
container.style.margin = '0 10px';
|
||||
container.style.display = 'flex';
|
||||
container.style.alignItems = 'center';
|
||||
container.style.gap = '10px';
|
||||
|
||||
// 页码显示
|
||||
const pageText = document.createElement('span');
|
||||
pageText.id = 'pageText';
|
||||
|
||||
// 跳转输入框
|
||||
const jumpInput = document.createElement('input');
|
||||
jumpInput.type = 'number';
|
||||
jumpInput.min = '1';
|
||||
jumpInput.id = 'jumpPage';
|
||||
jumpInput.style.width = '60px';
|
||||
jumpInput.style.padding = '4px';
|
||||
jumpInput.style.borderRadius = '4px';
|
||||
jumpInput.style.border = '1px solid var(--border-color)';
|
||||
jumpInput.style.backgroundColor = 'var(--inputcolor)';
|
||||
jumpInput.style.color = 'var(--inputcolor-font)';
|
||||
|
||||
// 跳转按钮
|
||||
const jumpButton = document.createElement('button');
|
||||
jumpButton.textContent = '跳转';
|
||||
jumpButton.className = 'btn search-button';
|
||||
jumpButton.style.padding = '4px 8px';
|
||||
jumpButton.onclick = () => {
|
||||
const page = parseInt(jumpInput.value);
|
||||
if (page && page >= 1 && page <= totalPages) {
|
||||
currentPage = page;
|
||||
performSearch();
|
||||
} else {
|
||||
showToast('请输入有效的页码');
|
||||
}
|
||||
};
|
||||
|
||||
container.appendChild(pageText);
|
||||
container.appendChild(jumpInput);
|
||||
container.appendChild(jumpButton);
|
||||
|
||||
// 插入到分页区域
|
||||
paginationDiv.insertBefore(container, nextButton);
|
||||
pageInfo = container;
|
||||
}
|
||||
document.getElementById('pageInfo').textContent = `第 ${currentPage} / ${totalPages} 页`;
|
||||
|
||||
// 更新页码显示
|
||||
const pageText = document.getElementById('pageText');
|
||||
pageText.textContent = `第 ${currentPage} / ${totalPages || 1} 页 共 ${totalPages || 1} 页`;
|
||||
|
||||
// 更新跳转输入框
|
||||
const jumpInput = document.getElementById('jumpPage');
|
||||
if (jumpInput) {
|
||||
jumpInput.max = totalPages;
|
||||
jumpInput.value = currentPage;
|
||||
}
|
||||
|
||||
// 显示或隐藏分页区域
|
||||
paginationDiv.style.display = totalPages > 1 ? 'flex' : 'none';
|
||||
}
|
||||
|
||||
function showSearchResults() {
|
||||
@@ -560,11 +614,7 @@
|
||||
console.log('搜索响应:', data);
|
||||
|
||||
// 更新总页数和分页状态
|
||||
if (typeof data.count === 'number') {
|
||||
totalPages = Math.ceil(data.count / 25);
|
||||
} else {
|
||||
totalPages = data.results ? Math.ceil(data.results.length / 25) : 1;
|
||||
}
|
||||
totalPages = Math.ceil(data.count / 25);
|
||||
updatePagination();
|
||||
|
||||
displayResults(data.results);
|
||||
|
||||
@@ -223,18 +223,45 @@ func searchDockerHub(ctx context.Context, query string, page, pageSize int) (*Se
|
||||
var result *SearchResult
|
||||
var lastErr error
|
||||
|
||||
// 判断是否是用户/仓库格式的搜索
|
||||
isUserRepo := strings.Contains(query, "/")
|
||||
|
||||
for retries := 3; retries > 0; retries-- {
|
||||
result, lastErr = trySearchDockerHub(ctx, query, page, pageSize)
|
||||
if isUserRepo {
|
||||
// 对于用户/仓库格式,尝试精确搜索和模糊搜索
|
||||
parts := strings.Split(query, "/")
|
||||
if len(parts) == 2 {
|
||||
// 先尝试精确搜索
|
||||
result, lastErr = trySearchDockerHub(ctx, query, page, pageSize)
|
||||
if lastErr == nil && len(result.Results) == 0 {
|
||||
// 如果精确搜索没有结果,尝试模糊搜索
|
||||
result, lastErr = trySearchDockerHub(ctx, parts[1], page, pageSize)
|
||||
if lastErr == nil {
|
||||
// 过滤出属于指定用户的结果
|
||||
filteredResults := make([]Repository, 0)
|
||||
for _, repo := range result.Results {
|
||||
if strings.EqualFold(repo.Namespace, parts[0]) ||
|
||||
strings.EqualFold(repo.RepoOwner, parts[0]) {
|
||||
filteredResults = append(filteredResults, repo)
|
||||
}
|
||||
}
|
||||
result.Results = filteredResults
|
||||
result.Count = len(filteredResults)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result, lastErr = trySearchDockerHub(ctx, query, page, pageSize)
|
||||
}
|
||||
|
||||
if lastErr == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// 判断是否需要重试
|
||||
if !isRetryableError(lastErr) {
|
||||
return nil, fmt.Errorf("搜索失败: %v", lastErr)
|
||||
}
|
||||
|
||||
// 等待后重试
|
||||
time.Sleep(time.Second * time.Duration(4-retries))
|
||||
}
|
||||
|
||||
@@ -316,7 +343,6 @@ func trySearchDockerHub(ctx context.Context, query string, page, pageSize int) (
|
||||
|
||||
// 检查响应状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
// 特殊处理常见错误
|
||||
switch resp.StatusCode {
|
||||
case http.StatusTooManyRequests:
|
||||
return nil, fmt.Errorf("请求过于频繁,请稍后重试")
|
||||
@@ -342,7 +368,6 @@ func trySearchDockerHub(ctx context.Context, query string, page, pageSize int) (
|
||||
if !strings.Contains(result.Results[i].Name, "/") {
|
||||
result.Results[i].Name = "library/" + result.Results[i].Name
|
||||
}
|
||||
// 设置命名空间为 library
|
||||
result.Results[i].Namespace = "library"
|
||||
} else {
|
||||
// 从 repo_name 中提取 namespace
|
||||
@@ -350,7 +375,7 @@ func trySearchDockerHub(ctx context.Context, query string, page, pageSize int) (
|
||||
if len(parts) > 1 {
|
||||
result.Results[i].Namespace = parts[0]
|
||||
result.Results[i].Name = parts[1]
|
||||
} else {
|
||||
} else if result.Results[i].RepoOwner != "" {
|
||||
result.Results[i].Namespace = result.Results[i].RepoOwner
|
||||
}
|
||||
}
|
||||
@@ -452,11 +477,6 @@ func RegisterSearchRoute(r *gin.Engine) {
|
||||
fmt.Sscanf(ps, "%d", &pageSize)
|
||||
}
|
||||
|
||||
// 如果是搜索官方镜像
|
||||
if !strings.Contains(query, "/") {
|
||||
query = strings.ToLower(query)
|
||||
}
|
||||
|
||||
fmt.Printf("搜索请求: query=%s, page=%d, pageSize=%d\n", query, page, pageSize)
|
||||
|
||||
result, err := searchDockerHub(c.Request.Context(), query, page, pageSize)
|
||||
@@ -466,23 +486,6 @@ func RegisterSearchRoute(r *gin.Engine) {
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤搜索结果,只保留相关的镜像
|
||||
filteredResults := make([]Repository, 0)
|
||||
searchTerm := strings.ToLower(strings.TrimPrefix(query, "library/"))
|
||||
|
||||
for _, repo := range result.Results {
|
||||
repoName := strings.ToLower(repo.Name)
|
||||
// 如果是精确匹配或者以搜索词开头,或者包含 "searchTerm/searchTerm"
|
||||
if repoName == searchTerm ||
|
||||
strings.HasPrefix(repoName, searchTerm+"/") ||
|
||||
strings.Contains(repoName, "/"+searchTerm) {
|
||||
filteredResults = append(filteredResults, repo)
|
||||
}
|
||||
}
|
||||
|
||||
result.Results = filteredResults
|
||||
result.Count = len(filteredResults)
|
||||
|
||||
c.JSON(http.StatusOK, result)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user