2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-05 00:39:32 +08:00
Files
panel/web/src/views/container/ImageView.vue
2024-11-03 16:46:05 +08:00

242 lines
5.5 KiB
Vue

<script setup lang="ts">
import { NButton, NDataTable, NFlex, NInput, NPopconfirm, NTag } from 'naive-ui'
import container from '@/api/panel/container'
import { formatDateTime } from '@/utils'
import type { ImageList } from '@/views/container/types'
const pullModel = ref({
name: '',
auth: false,
username: '',
password: ''
})
const pullModal = ref(false)
const loading = ref(false)
const data = ref<ImageList[]>([] as ImageList[])
const selectedRowKeys = ref<any>([])
const onChecked = (rowKeys: any) => {
selectedRowKeys.value = rowKeys
}
const columns: any = [
{ type: 'selection', fixed: 'left' },
{
title: 'ID',
key: 'id',
minWidth: 400,
resizable: true,
ellipsis: { tooltip: true }
},
{
title: '容器数',
key: 'containers',
width: 100,
resizable: true,
ellipsis: { tooltip: true }
},
{
title: '镜像',
key: 'repo_tags',
minWidth: 200,
resizable: true,
ellipsis: { tooltip: true },
render(row: any): any {
return h(NFlex, null, {
default: () =>
row.repo_tags.map((tag: any) =>
h(NTag, null, {
default: () => tag
})
)
})
}
},
{
title: '大小',
key: 'size',
width: 150,
resizable: true,
ellipsis: { tooltip: true }
},
{
title: '创建时间',
key: 'created_at',
width: 200,
resizable: true,
render(row: any) {
return formatDateTime(row.created_at)
}
},
{
title: '操作',
key: 'actions',
width: 120,
align: 'center',
hideInExcel: true,
render(row: any) {
return [
h(
NPopconfirm,
{
onPositiveClick: async () => {
await handleDelete(row)
}
},
{
default: () => {
return '确定删除吗?'
},
trigger: () => {
return h(
NButton,
{
size: 'small',
type: 'error'
},
{
default: () => '删除'
}
)
}
}
)
]
}
}
]
const pagination = reactive({
page: 1,
pageCount: 1,
pageSize: 20,
itemCount: 0,
showQuickJumper: true,
showSizePicker: true,
pageSizes: [20, 50, 100, 200]
})
const onPageChange = (page: number) => {
pagination.page = page
getImageList(page, pagination.pageSize).then((res) => {
data.value = res.items
pagination.itemCount = res.total
pagination.pageCount = res.total / pagination.pageSize + 1
})
}
const onPageSizeChange = (pageSize: number) => {
pagination.pageSize = pageSize
onPageChange(1)
}
const getImageList = async (page: number, pageSize: number) => {
const { data } = await container.imageList(page, pageSize)
return data
}
const handleDelete = async (row: any) => {
container.imageRemove(row.id).then(() => {
window.$message.success('删除成功')
onPageChange(pagination.page)
})
}
const handlePrune = () => {
container.imagePrune().then(() => {
window.$message.success('清理成功')
onPageChange(pagination.page)
})
}
const handlePull = () => {
loading.value = true
container
.imagePull(pullModel.value)
.then(() => {
window.$message.success('拉取成功')
onPageChange(pagination.page)
})
.finally(() => {
loading.value = false
pullModal.value = false
})
}
onMounted(() => {
onPageChange(pagination.page)
})
</script>
<template>
<n-space vertical size="large">
<n-card rounded-10>
<n-space>
<n-button type="primary" @click="pullModal = true">拉取镜像</n-button>
<n-button type="primary" @click="handlePrune" ghost>清理镜像</n-button>
</n-space>
</n-card>
<n-card rounded-10>
<n-data-table
striped
remote
:scroll-x="1000"
:data="data"
:columns="columns"
:row-key="(row: any) => row.id"
:pagination="pagination"
:bordered="false"
:loading="false"
@update:page="onPageChange"
@update:page-size="onPageSizeChange"
@update:checked-row-keys="onChecked"
/>
</n-card>
</n-space>
<n-modal
v-model:show="pullModal"
preset="card"
title="拉取镜像"
style="width: 60vw"
size="huge"
:bordered="false"
:segmented="false"
>
<n-form :model="pullModel">
<n-form-item path="name" label="镜像名">
<n-input
v-model:value="pullModel.name"
type="text"
@keydown.enter.prevent
placeholder="docker.io/php:8.3-fpm"
/>
</n-form-item>
<n-form-item path="auth" label="验证">
<n-switch v-model:value="pullModel.auth" />
</n-form-item>
<n-form-item v-if="pullModel.auth" path="username" label="用户名">
<n-input
v-model:value="pullModel.username"
type="text"
@keydown.enter.prevent
placeholder="输入用户名"
/>
</n-form-item>
<n-form-item v-if="pullModel.auth" path="password" label="密码">
<n-input
v-model:value="pullModel.password"
type="password"
show-password-on="click"
@keydown.enter.prevent
placeholder="输入密码"
/>
</n-form-item>
</n-form>
<n-button type="info" block :loading="loading" :disabled="loading" @click="handlePull">
提交
</n-button>
</n-modal>
</template>