From 222181bafff259348bf32b6cbd78414317d630cf Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Fri, 10 Oct 2025 17:23:59 +0800 Subject: [PATCH] feat: Support batch operations for image tags (#10597) --- agent/app/dto/image.go | 4 +- agent/app/service/image.go | 32 +++++++- frontend/src/api/interface/container.ts | 2 +- frontend/src/lang/modules/en.ts | 2 +- frontend/src/lang/modules/es-es.ts | 3 +- frontend/src/lang/modules/ja.ts | 2 +- frontend/src/lang/modules/ko.ts | 2 +- frontend/src/lang/modules/ms.ts | 3 +- frontend/src/lang/modules/pt-br.ts | 3 +- frontend/src/lang/modules/ru.ts | 3 +- frontend/src/lang/modules/tr.ts | 3 +- frontend/src/lang/modules/zh-Hant.ts | 2 +- frontend/src/lang/modules/zh.ts | 2 +- .../src/views/container/image/tag/index.vue | 81 ++++++++++++------- 14 files changed, 101 insertions(+), 43 deletions(-) diff --git a/agent/app/dto/image.go b/agent/app/dto/image.go index 211157bd7..7838bd0c8 100644 --- a/agent/app/dto/image.go +++ b/agent/app/dto/image.go @@ -36,8 +36,8 @@ type ImagePull struct { } type ImageTag struct { - SourceID string `json:"sourceID" validate:"required"` - TargetName string `json:"targetName" validate:"required"` + SourceID string `json:"sourceID" validate:"required"` + Tags []string `json:"tags" validate:"required"` } type ImagePush struct { diff --git a/agent/app/service/image.go b/agent/app/service/image.go index 03e6d5c96..f3f88f547 100644 --- a/agent/app/service/image.go +++ b/agent/app/service/image.go @@ -363,9 +363,39 @@ func (u *ImageService) ImageTag(req dto.ImageTag) error { } defer client.Close() - if err := client.ImageTag(context.TODO(), req.SourceID, req.TargetName); err != nil { + imageItem, err := client.ImageInspect(context.Background(), req.SourceID) + if err != nil { return err } + + for _, tag := range req.Tags { + isNew := true + for _, tagOld := range imageItem.RepoTags { + if tag == tagOld { + isNew = false + break + } + } + if isNew { + if err := client.ImageTag(context.TODO(), req.SourceID, tag); err != nil { + return err + } + } + } + for _, tagOld := range imageItem.RepoTags { + isDel := true + for _, tag := range req.Tags { + if tag == tagOld { + isDel = false + break + } + } + if isDel { + if _, err := client.ImageRemove(context.TODO(), tagOld, image.RemoveOptions{}); err != nil { + return err + } + } + } return nil } diff --git a/frontend/src/api/interface/container.ts b/frontend/src/api/interface/container.ts index 20bd13ec5..ee84e69fb 100644 --- a/frontend/src/api/interface/container.ts +++ b/frontend/src/api/interface/container.ts @@ -191,7 +191,7 @@ export namespace Container { } export interface ImageTag { sourceID: string; - targetName: string; + tags: Array; } export interface ImagePush { taskID: string; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 2b07fab86..a8c0f9151 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -882,7 +882,6 @@ const message = { imagePushHelper: 'Detected that this image has multiple tags. Please confirm that the image name used for pushing is: {0}', imageDelete: 'Image delete', - imageTagDeleteHelper: 'Remove other tags associated with this image ID', repoName: 'Container registry', imageName: 'Image name', pull: 'Pull', @@ -893,6 +892,7 @@ const message = { pathSelect: 'Path', label: 'Label', imageTag: 'Image tag', + imageTagHelper: 'Supports setting multiple image tags, press Enter after entering each tag to continue', push: 'Push', fileName: 'Filename', export: 'Export', diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 08c175a25..2fdcfb0cf 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -884,7 +884,6 @@ const message = { imagePushHelper: 'Detected that this image has multiple tags. Please confirm that the image name used for pushing is: {0}', imageDelete: 'Eliminar imagen', - imageTagDeleteHelper: 'Eliminar otras etiquetas asociadas con este ID de imagen', repoName: 'Repositorio de contenedores', imageName: 'Nombre de la imagen', pull: 'Descargar', @@ -895,6 +894,8 @@ const message = { pathSelect: 'Ruta', label: 'Etiqueta', imageTag: 'Etiqueta de imagen', + imageTagHelper: + 'Admite configurar múltiples etiquetas de imagen, presione Enter después de ingresar cada etiqueta para continuar', push: 'Subir', fileName: 'Nombre de archivo', export: 'Exportar', diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index 765093284..4f6e85601 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -858,7 +858,6 @@ const message = { imagePushHelper: 'このイメージに複数のタグが存在することが検出されました。プッシュ時に使用するイメージ名が以下であることを確認してください:{0}', imageDelete: '画像削除', - imageTagDeleteHelper: 'この画像IDに関連付けられた他のタグを削除します', repoName: 'コンテナレジストリ', imageName: '画像名', pull: '引く', @@ -869,6 +868,7 @@ const message = { pathSelect: 'パス', label: 'ラベル', imageTag: '画像タグ', + imageTagHelper: '複数のイメージタグの設定をサポートし、各タグ入力後にEnterキーを押して続行します', push: '押す', fileName: 'ファイル名', export: '輸出', diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index 3dc1c16a9..80a89e177 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -850,7 +850,6 @@ const message = { imagePushHelper: '이 이미지에 여러 태그가 있는 것으로 감지되었습니다. 푸시 시 사용할 이미지 이름이 다음인지 확인하세요: {0}', imageDelete: '이미지 삭제', - imageTagDeleteHelper: '이 이미지 ID와 관련된 다른 태그를 제거합니다.', repoName: '컨테이너 저장소 이름', imageName: '이미지 이름', pull: '풀', @@ -861,6 +860,7 @@ const message = { pathSelect: '경로', label: '레이블', imageTag: '이미지 태그', + imageTagHelper: '여러 이미지 태그 설정을 지원하며, 각 태그 입력 후 Enter 키를 눌러 계속합니다', push: '푸시', fileName: '파일 이름', export: '내보내기', diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index 20c5c5e91..75499eb38 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -875,7 +875,6 @@ const message = { imagePushHelper: 'Terdapat pengesahan bahawa imej ini mempunyai beberapa tag. Sila pastikan nama imej yang digunakan untuk menolak adalah: {0}', imageDelete: 'Padam imej', - imageTagDeleteHelper: 'Buang tag lain yang berkaitan dengan ID imej ini', repoName: 'Pendaftaran kontena', imageName: 'Nama imej', pull: 'Tarik', @@ -886,6 +885,8 @@ const message = { pathSelect: 'Laluan', label: 'Label', imageTag: 'Tag imej', + imageTagHelper: + 'Menyokong penetapan berbilang tag imej, tekan Enter selepas memasukkan setiap tag untuk teruskan', push: 'Tekan', fileName: 'Nama fail', export: 'Eksport', diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index fcb0f3681..18df3a874 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -870,7 +870,6 @@ const message = { imagePushHelper: 'Detectado que esta imagem possui múltiplas tags. Por favor, confirme que o nome da imagem usada para push é: {0}', imageDelete: 'Excluir imagem', - imageTagDeleteHelper: 'Remover outras tags associadas a este ID de imagem', repoName: 'Registro de contêiner', imageName: 'Nome da imagem', pull: 'Puxar', @@ -881,6 +880,8 @@ const message = { pathSelect: 'Caminho', label: 'Etiqueta', imageTag: 'Tag de imagem', + imageTagHelper: + 'Suporta definir múltiplas tags de imagem, pressione Enter após inserir cada tag para continuar', push: 'Enviar', fileName: 'Nome do arquivo', export: 'Exportar', diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index 98021a08a..4f053c943 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -873,7 +873,6 @@ const message = { imagePushHelper: 'Обнаружено, что у этого образа несколько тегов. Подтвердите, что имя образа, используемое для отправки: {0}', imageDelete: 'Удалить образ', - imageTagDeleteHelper: 'Удалить другие теги, связанные с этим ID образа', repoName: 'Реестр контейнеров', imageName: 'Имя образа', pull: 'Загрузить', @@ -884,6 +883,8 @@ const message = { pathSelect: 'Путь', label: 'Метка', imageTag: 'Тег образа', + imageTagHelper: + 'Поддерживает установку нескольких тегов образов, нажмите Enter после ввода каждого тега для продолжения', push: 'Отправить', fileName: 'Имя файла', export: 'Экспорт', diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index 3cac9be32..9948da4f4 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -891,7 +891,6 @@ const message = { imagePushHelper: 'Bu imgenin birden fazla etiketi olduğu tespit edildi. Lütfen gönderimde kullanılan imge adının şu olduğunu onaylayın: {0}', imageDelete: 'İmaj sil', - imageTagDeleteHelper: 'Bu imaj IDsi ile ilişkili diğer etiketleri kaldır', repoName: 'Konteyner kayıt defteri', imageName: 'İmaj adı', pull: 'Çek', @@ -902,6 +901,8 @@ const message = { pathSelect: 'Yol', label: 'Etiket', imageTag: 'İmaj etiketi', + imageTagHelper: + "Birden fazla görüntü etiketi ayarlamayı destekler, her etiket girdikten sonra Enter'a basarak devam edin", push: 'Gönder', fileName: 'Dosya adı', export: 'Dışa aktar', diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index 5c33a2230..3dba86894 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -845,7 +845,6 @@ const message = { imagePush: '推送鏡像', imagePushHelper: '檢測到該映像存在多個標籤,請確認推送時使用的映像名稱為:{0}', imageDelete: '刪除鏡像', - imageTagDeleteHelper: '移除與該映像 ID 相關聯的其他標籤', repoName: '倉庫名', imageName: '鏡像名', httpRepo: 'http 倉庫新增授信需要重啟 docker 服務', @@ -859,6 +858,7 @@ const message = { pathSelect: '路徑選擇', label: '標籤', imageTag: '鏡像標籤', + imageTagHelper: '支援設定多個映像標籤,輸入一個標籤後回車繼續', push: '推送', fileName: '檔案名', export: '匯出', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index f502ba7a0..39ed7c00c 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -844,7 +844,6 @@ const message = { imagePush: '推送镜像', imagePushHelper: '检测到该镜像存在多个标签,请确认推送时使用的镜像名称为:{0}', imageDelete: '删除镜像', - imageTagDeleteHelper: '移除与该镜像 ID 相关联的其他标签', repoName: '仓库名', imageName: '镜像名', httpRepo: 'http 仓库添加授信需要重启 docker 服务', @@ -858,6 +857,7 @@ const message = { pathSelect: '路径选择', label: '标签', imageTag: '镜像标签', + imageTagHelper: '支持设置多个镜像 tag,输入一个 tag 后回车继续', push: '推送', fileName: '文件名', export: '导出', diff --git a/frontend/src/views/container/image/tag/index.vue b/frontend/src/views/container/image/tag/index.vue index 2410386d1..87a66526d 100644 --- a/frontend/src/views/container/image/tag/index.vue +++ b/frontend/src/views/container/image/tag/index.vue @@ -1,6 +1,6 @@