mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-03-14 01:34:47 +08:00
feat: 容器镜像列表增加是否使用标签 (#2364)
Refs #2300 
This commit is contained in:
parent
695f3278c3
commit
12d6c2c3df
@ -5,6 +5,7 @@ import "time"
|
|||||||
type ImageInfo struct {
|
type ImageInfo struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
|
IsUsed bool `json:"isUsed"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
Size string `json:"size"`
|
Size string `json:"size"`
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
return 0, nil, err
|
||||||
}
|
}
|
||||||
|
containers, _ := client.ContainerList(context.Background(), types.ContainerListOptions{All: true})
|
||||||
if len(req.Info) != 0 {
|
if len(req.Info) != 0 {
|
||||||
length, count := len(list), 0
|
length, count := len(list), 0
|
||||||
for count < length {
|
for count < length {
|
||||||
@ -77,6 +78,7 @@ func (u *ImageService) Page(req dto.SearchWithPage) (int64, interface{}, error)
|
|||||||
records = append(records, dto.ImageInfo{
|
records = append(records, dto.ImageInfo{
|
||||||
ID: image.ID,
|
ID: image.ID,
|
||||||
Tags: image.RepoTags,
|
Tags: image.RepoTags,
|
||||||
|
IsUsed: checkUsed(image.ID, containers),
|
||||||
CreatedAt: time.Unix(image.Created, 0),
|
CreatedAt: time.Unix(image.Created, 0),
|
||||||
Size: size,
|
Size: size,
|
||||||
})
|
})
|
||||||
@ -415,3 +417,12 @@ func formatFileSize(fileSize int64) (size string) {
|
|||||||
return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
|
return fmt.Sprintf("%.2fEB", float64(fileSize)/float64(1024*1024*1024*1024*1024))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkUsed(imageID string, containers []types.Container) bool {
|
||||||
|
for _, container := range containers {
|
||||||
|
if container.ImageID == imageID {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -224,6 +224,8 @@ const message = {
|
|||||||
rebuilding: 'ReBuilding',
|
rebuilding: 'ReBuilding',
|
||||||
deny: 'Denied',
|
deny: 'Denied',
|
||||||
accept: 'Accepted',
|
accept: 'Accepted',
|
||||||
|
used: 'Used',
|
||||||
|
unUsed: 'Unused',
|
||||||
},
|
},
|
||||||
units: {
|
units: {
|
||||||
second: 'Second',
|
second: 'Second',
|
||||||
@ -493,9 +495,9 @@ const message = {
|
|||||||
containerPruneHelper3: 'This operation cannot be rolled back. Do you want to continue?',
|
containerPruneHelper3: 'This operation cannot be rolled back. Do you want to continue?',
|
||||||
imagePrune: 'Image prune',
|
imagePrune: 'Image prune',
|
||||||
imagePruneSome: 'Clean unlabeled',
|
imagePruneSome: 'Clean unlabeled',
|
||||||
imagePruneSomeHelper: 'Remove all unused and unlabeled container images。',
|
imagePruneSomeHelper: 'Clean the images with the tag "none" that are not used by any containers.',
|
||||||
imagePruneAll: 'Clean unused',
|
imagePruneAll: 'Clean unused',
|
||||||
imagePruneAllHelper: 'Remove all unused images, not just unlabeled',
|
imagePruneAllHelper: 'Clean the images that are not used by any containers.',
|
||||||
networkPrune: 'Network prune',
|
networkPrune: 'Network prune',
|
||||||
networkPruneHelper: 'Remove all unused networks. Do you want to continue?',
|
networkPruneHelper: 'Remove all unused networks. Do you want to continue?',
|
||||||
volumePrune: 'Volume prune',
|
volumePrune: 'Volume prune',
|
||||||
|
@ -222,6 +222,8 @@ const message = {
|
|||||||
rebuilding: '重建中',
|
rebuilding: '重建中',
|
||||||
deny: '已屏蔽',
|
deny: '已屏蔽',
|
||||||
accept: '已放行',
|
accept: '已放行',
|
||||||
|
used: '已使用',
|
||||||
|
unUsed: '未使用',
|
||||||
},
|
},
|
||||||
units: {
|
units: {
|
||||||
second: '秒',
|
second: '秒',
|
||||||
@ -481,9 +483,9 @@ const message = {
|
|||||||
containerPruneHelper3: '該操作無法回滾,是否繼續?',
|
containerPruneHelper3: '該操作無法回滾,是否繼續?',
|
||||||
imagePrune: '清理鏡像',
|
imagePrune: '清理鏡像',
|
||||||
imagePruneSome: '未標簽鏡像',
|
imagePruneSome: '未標簽鏡像',
|
||||||
imagePruneSomeHelper: '清理標簽為 none 且未被任何容器使用的鏡像。',
|
imagePruneSomeHelper: '清理下列標簽為 none 且未被任何容器使用的鏡像。',
|
||||||
imagePruneAll: '未使用鏡像',
|
imagePruneAll: '未使用鏡像',
|
||||||
imagePruneAllHelper: '清理所有未被任何容器使用的鏡像。',
|
imagePruneAllHelper: '清理下列未被任何容器使用的鏡像。',
|
||||||
networkPrune: '清理網絡',
|
networkPrune: '清理網絡',
|
||||||
networkPruneHelper: '清理網絡 將刪除所有未被使用的網絡,該操作無法回滾,是否繼續?',
|
networkPruneHelper: '清理網絡 將刪除所有未被使用的網絡,該操作無法回滾,是否繼續?',
|
||||||
volumePrune: '清理存儲卷',
|
volumePrune: '清理存儲卷',
|
||||||
|
@ -222,6 +222,8 @@ const message = {
|
|||||||
rebuilding: '重建中',
|
rebuilding: '重建中',
|
||||||
deny: '已屏蔽',
|
deny: '已屏蔽',
|
||||||
accept: '已放行',
|
accept: '已放行',
|
||||||
|
used: '已使用',
|
||||||
|
unUsed: '未使用',
|
||||||
},
|
},
|
||||||
units: {
|
units: {
|
||||||
second: '秒',
|
second: '秒',
|
||||||
@ -481,9 +483,9 @@ const message = {
|
|||||||
containerPruneHelper3: '该操作无法回滚,是否继续?',
|
containerPruneHelper3: '该操作无法回滚,是否继续?',
|
||||||
imagePrune: '清理镜像',
|
imagePrune: '清理镜像',
|
||||||
imagePruneSome: '未标签镜像',
|
imagePruneSome: '未标签镜像',
|
||||||
imagePruneSomeHelper: '清理标签为 none 且未被任何容器使用的镜像。',
|
imagePruneSomeHelper: '清理下列标签为 none 且未被任何容器使用的镜像。',
|
||||||
imagePruneAll: '未使用镜像',
|
imagePruneAll: '未使用镜像',
|
||||||
imagePruneAllHelper: '清理所有未被任何容器使用的镜像。',
|
imagePruneAllHelper: '清理下列未被任何容器使用的镜像。',
|
||||||
networkPrune: '清理网络',
|
networkPrune: '清理网络',
|
||||||
networkPruneHelper: '清理网络 将删除所有未被使用的网络,该操作无法回滚,是否继续?',
|
networkPruneHelper: '清理网络 将删除所有未被使用的网络,该操作无法回滚,是否继续?',
|
||||||
volumePrune: '清理存储卷',
|
volumePrune: '清理存储卷',
|
||||||
|
@ -46,6 +46,16 @@
|
|||||||
<span>{{ row.id.replaceAll('sha256:', '').substring(0, 12) }}</span>
|
<span>{{ row.id.replaceAll('sha256:', '').substring(0, 12) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column :label="$t('commons.table.status')" prop="isUsed" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag icon="Select" v-if="row.isUsed" type="success">
|
||||||
|
{{ $t('commons.status.used') }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="info">
|
||||||
|
{{ $t('commons.status.unUsed') }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
:label="$t('container.tag')"
|
:label="$t('container.tag')"
|
||||||
prop="tags"
|
prop="tags"
|
||||||
@ -186,7 +196,7 @@ const onOpenBuild = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onOpenPrune = () => {
|
const onOpenPrune = () => {
|
||||||
dialogPruneRef.value!.acceptParams();
|
dialogPruneRef.value!.acceptParams({ list: data.value });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onOpenload = () => {
|
const onOpenload = () => {
|
||||||
|
@ -11,10 +11,22 @@
|
|||||||
<el-radio :label="false">{{ $t('container.imagePruneSome') }}</el-radio>
|
<el-radio :label="false">{{ $t('container.imagePruneSome') }}</el-radio>
|
||||||
<el-radio :label="true">{{ $t('container.imagePruneAll') }}</el-radio>
|
<el-radio :label="true">{{ $t('container.imagePruneAll') }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<span class="input-help">
|
|
||||||
{{ withTagAll ? $t('container.imagePruneAllHelper') : $t('container.imagePruneSomeHelper') }}
|
|
||||||
</span>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<span>
|
||||||
|
{{ withTagAll ? $t('container.imagePruneAllHelper') : $t('container.imagePruneSomeHelper') }}
|
||||||
|
</span>
|
||||||
|
<div v-if="!withTagAll">
|
||||||
|
<ul v-for="(item, index) in imageList" :key="index">
|
||||||
|
<li v-if="item.tags.length === 1 && item.tags[0].indexOf(':<none>') !== -1">
|
||||||
|
{{ item.tags[0] }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<ul v-for="(item, index) in imageList" :key="index">
|
||||||
|
<li v-if="!item.isUsed">{{ item.tags.join(', ') }}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
@ -30,6 +42,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { Container } from '@/api/interface/container';
|
||||||
import { containerPrune } from '@/api/modules/container';
|
import { containerPrune } from '@/api/modules/container';
|
||||||
import i18n from '@/lang';
|
import i18n from '@/lang';
|
||||||
import { MsgSuccess } from '@/utils/message';
|
import { MsgSuccess } from '@/utils/message';
|
||||||
@ -39,8 +52,13 @@ import { ref } from 'vue';
|
|||||||
const dialogVisiable = ref(false);
|
const dialogVisiable = ref(false);
|
||||||
const withTagAll = ref(false);
|
const withTagAll = ref(false);
|
||||||
const loading = ref();
|
const loading = ref();
|
||||||
|
const imageList = ref();
|
||||||
|
|
||||||
const acceptParams = (): void => {
|
interface DialogProps {
|
||||||
|
list: Array<Container.ImageInfo>;
|
||||||
|
}
|
||||||
|
const acceptParams = (params: DialogProps): void => {
|
||||||
|
imageList.value = params.list;
|
||||||
dialogVisiable.value = true;
|
dialogVisiable.value = true;
|
||||||
withTagAll.value = false;
|
withTagAll.value = false;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user