mirror of
https://github.com/acepanel/panel.git
synced 2026-02-07 05:47:21 +08:00
feat: 提交部分前端翻译
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NCheckbox, NDataTable, NFlex, NInput, NPopconfirm, NTag } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import container from '@/api/panel/container'
|
||||
import { useFileStore } from '@/store'
|
||||
import { formatDateTime } from '@/utils'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const fileStore = useFileStore()
|
||||
const router = useRouter()
|
||||
|
||||
@@ -26,14 +28,14 @@ const updateModal = ref(false)
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: '名称',
|
||||
title: $gettext('Name'),
|
||||
key: 'name',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '目录',
|
||||
title: $gettext('Directory'),
|
||||
key: 'path',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
@@ -53,14 +55,14 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
title: $gettext('Status'),
|
||||
key: 'status',
|
||||
width: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
title: $gettext('Creation Time'),
|
||||
key: 'created_at',
|
||||
width: 200,
|
||||
resizable: true,
|
||||
@@ -69,7 +71,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: $gettext('Actions'),
|
||||
key: 'actions',
|
||||
width: 280,
|
||||
align: 'center',
|
||||
@@ -92,7 +94,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => '编辑'
|
||||
default: () => $gettext('Edit')
|
||||
}
|
||||
),
|
||||
h(
|
||||
@@ -100,14 +102,14 @@ const columns: any = [
|
||||
{
|
||||
showIcon: false,
|
||||
onPositiveClick: () => {
|
||||
const messageReactive = window.$message.loading('启动中...', {
|
||||
const messageReactive = window.$message.loading($gettext('Starting...'), {
|
||||
duration: 0
|
||||
})
|
||||
useRequest(container.composeUp(row.name, forcePush.value))
|
||||
.onSuccess(() => {
|
||||
refresh()
|
||||
forcePush.value = false
|
||||
window.$message.success('启动成功')
|
||||
window.$message.success($gettext('Start successful'))
|
||||
})
|
||||
.onComplete(() => {
|
||||
messageReactive?.destroy()
|
||||
@@ -123,14 +125,14 @@ const columns: any = [
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
h('strong', {}, { default: () => `确定启动编排 ${row.name} 吗?` }),
|
||||
h('strong', {}, { default: () => $gettext(`Are you sure you want to start compose %{ name }?`, { name: row.name }) }),
|
||||
h(
|
||||
NCheckbox,
|
||||
{
|
||||
checked: forcePush.value,
|
||||
onUpdateChecked: (v) => (forcePush.value = v)
|
||||
},
|
||||
{ default: () => '强制拉取镜像' }
|
||||
{ default: () => $gettext('Force pull images') }
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -145,7 +147,7 @@ const columns: any = [
|
||||
type: 'success'
|
||||
},
|
||||
{
|
||||
default: () => '启动'
|
||||
default: () => $gettext('Start')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -157,13 +159,13 @@ const columns: any = [
|
||||
onPositiveClick: () => {
|
||||
useRequest(container.composeDown(row.name)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('停止成功')
|
||||
window.$message.success($gettext('Stop successful'))
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return `确定停止编排 ${row.name} 吗?`
|
||||
return $gettext(`Are you sure you want to stop compose %{ name }?`, { name: row.name })
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
@@ -174,7 +176,7 @@ const columns: any = [
|
||||
type: 'warning'
|
||||
},
|
||||
{
|
||||
default: () => '停止'
|
||||
default: () => $gettext('Stop')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -186,13 +188,13 @@ const columns: any = [
|
||||
onPositiveClick: () => {
|
||||
useRequest(container.composeRemove(row.name)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
window.$message.success($gettext('Delete successful'))
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return `确定删除编排 ${row.name} 吗?`
|
||||
return $gettext(`Are you sure you want to delete compose %{ name }?`, { name: row.name })
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
@@ -203,7 +205,7 @@ const columns: any = [
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除'
|
||||
default: () => $gettext('Delete')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -229,7 +231,7 @@ const handleCreate = () => {
|
||||
useRequest(container.composeCreate(createModel.value))
|
||||
.onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('创建成功')
|
||||
window.$message.success($gettext('Created successfully'))
|
||||
})
|
||||
.onComplete(() => {
|
||||
loading.value = false
|
||||
@@ -247,7 +249,7 @@ const handleUpdate = () => {
|
||||
useRequest(container.composeUpdate(updateModel.value.name, updateModel.value))
|
||||
.onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('更新成功')
|
||||
window.$message.success($gettext('Update successful'))
|
||||
})
|
||||
.onComplete(() => {
|
||||
loading.value = false
|
||||
@@ -268,7 +270,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="createModal = true">创建编排</n-button>
|
||||
<n-button type="primary" @click="createModal = true">{{ $gettext('Create Compose') }}</n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
striped
|
||||
@@ -294,64 +296,64 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="createModal"
|
||||
preset="card"
|
||||
title="创建编排"
|
||||
:title="$gettext('Create Compose')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item path="name" label="编排名">
|
||||
<n-form-item path="name" :label="$gettext('Compose Name')">
|
||||
<n-input v-model:value="createModel.name" type="text" />
|
||||
</n-form-item>
|
||||
<n-form-item path="compose" label="编排">
|
||||
<n-form-item path="compose" :label="$gettext('Compose')">
|
||||
<n-input
|
||||
v-model:value="createModel.compose"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 10, maxRows: 20 }"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="envs" label="环境变量">
|
||||
<n-form-item path="envs" :label="$gettext('Environment Variables')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.envs"
|
||||
preset="pair"
|
||||
key-placeholder="变量名"
|
||||
value-placeholder="变量值"
|
||||
:key-placeholder="$gettext('Variable Name')"
|
||||
:value-placeholder="$gettext('Variable Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block :loading="loading" :disabled="loading" @click="handleCreate">
|
||||
提交
|
||||
{{ $gettext('Submit') }}
|
||||
</n-button>
|
||||
</n-modal>
|
||||
<n-modal
|
||||
v-model:show="updateModal"
|
||||
preset="card"
|
||||
title="编辑编排"
|
||||
:title="$gettext('Edit Compose')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-form :model="updateModel">
|
||||
<n-form-item path="compose" label="编排">
|
||||
<n-form-item path="compose" :label="$gettext('Compose')">
|
||||
<n-input
|
||||
v-model:value="updateModel.compose"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 10, maxRows: 20 }"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="envs" label="环境变量">
|
||||
<n-form-item path="envs" :label="$gettext('Environment Variables')">
|
||||
<n-dynamic-input
|
||||
v-model:value="updateModel.envs"
|
||||
preset="pair"
|
||||
key-placeholder="变量名"
|
||||
value-placeholder="变量值"
|
||||
:key-placeholder="$gettext('Variable Name')"
|
||||
:value-placeholder="$gettext('Variable Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block :loading="loading" :disabled="loading" @click="handleUpdate">
|
||||
提交
|
||||
{{ $gettext('Submit') }}
|
||||
</n-button>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import container from '@/api/panel/container'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const props = defineProps({
|
||||
show: {
|
||||
@@ -49,10 +52,10 @@ const createModel = reactive({
|
||||
const networks = ref<any>({})
|
||||
|
||||
const restartPolicyOptions = [
|
||||
{ label: '无', value: 'no' },
|
||||
{ label: '始终', value: 'always' },
|
||||
{ label: '失败时(默认重启 5 次)', value: 'on-failure' },
|
||||
{ label: '未手动停止则重启', value: 'unless-stopped' }
|
||||
{ label: $gettext('None'), value: 'no' },
|
||||
{ label: $gettext('Always'), value: 'always' },
|
||||
{ label: $gettext('On failure (default 5 retries)'), value: 'on-failure' },
|
||||
{ label: $gettext('Unless stopped'), value: 'unless-stopped' }
|
||||
]
|
||||
|
||||
const addPortRow = () => {
|
||||
@@ -100,7 +103,7 @@ const handleSubmit = () => {
|
||||
doSubmit.value = true
|
||||
useRequest(container.containerCreate(createModel))
|
||||
.onSuccess(() => {
|
||||
window.$message.success('创建成功')
|
||||
window.$message.success($gettext('Created successfully'))
|
||||
handleClose()
|
||||
})
|
||||
.onComplete(() => {
|
||||
@@ -121,7 +124,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<n-modal
|
||||
title="创建容器"
|
||||
:title="$gettext('Create Container')"
|
||||
preset="card"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
@@ -131,40 +134,40 @@ onMounted(() => {
|
||||
@close="handleClose"
|
||||
>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item path="name" label="容器名">
|
||||
<n-form-item path="name" :label="$gettext('Container Name')">
|
||||
<n-input v-model:value="createModel.name" type="text" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="name" label="镜像">
|
||||
<n-form-item path="name" :label="$gettext('Image')">
|
||||
<n-input v-model:value="createModel.image" type="text" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="exposedAll" label="端口">
|
||||
<n-form-item path="exposedAll" :label="$gettext('Ports')">
|
||||
<n-radio
|
||||
:checked="!createModel.publish_all_ports"
|
||||
:value="false"
|
||||
@change="createModel.publish_all_ports = !$event.target.value"
|
||||
>
|
||||
映射端口
|
||||
{{ $gettext('Map Ports') }}
|
||||
</n-radio>
|
||||
<n-radio
|
||||
:checked="createModel.publish_all_ports"
|
||||
:value="true"
|
||||
@change="createModel.publish_all_ports = !!$event.target.value"
|
||||
>
|
||||
暴露所有
|
||||
{{ $gettext('Expose All') }}
|
||||
</n-radio>
|
||||
</n-form-item>
|
||||
<n-form-item path="ports" label="端口映射" v-if="!createModel.publish_all_ports">
|
||||
<n-form-item path="ports" :label="$gettext('Port Mapping')" v-if="!createModel.publish_all_ports">
|
||||
<n-space vertical>
|
||||
<n-table striped>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>IP</th>
|
||||
<th>主机(起始)</th>
|
||||
<th>主机(结束)</th>
|
||||
<th>容器(起始)</th>
|
||||
<th>容器(结束)</th>
|
||||
<th>协议</th>
|
||||
<th>操作</th>
|
||||
<th>{{ $gettext('Host (Start)') }}</th>
|
||||
<th>{{ $gettext('Host (End)') }}</th>
|
||||
<th>{{ $gettext('Container (Start)') }}</th>
|
||||
<th>{{ $gettext('Container (End)') }}</th>
|
||||
<th>{{ $gettext('Protocol') }}</th>
|
||||
<th>{{ $gettext('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -174,7 +177,7 @@ onMounted(() => {
|
||||
v-model:value="item.host"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="可留空"
|
||||
:placeholder="$gettext('Optional')"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
@@ -223,25 +226,25 @@ onMounted(() => {
|
||||
UDP
|
||||
</n-radio>
|
||||
</td>
|
||||
<td><n-button @click="removePortRow(index)" size="small">删除</n-button></td>
|
||||
<td><n-button @click="removePortRow(index)" size="small">{{ $gettext('Delete') }}</n-button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</n-table>
|
||||
<n-button @click="addPortRow">添加</n-button>
|
||||
<n-button @click="addPortRow">{{ $gettext('Add') }}</n-button>
|
||||
</n-space>
|
||||
</n-form-item>
|
||||
<n-form-item path="network" label="网络">
|
||||
<n-form-item path="network" :label="$gettext('Network')">
|
||||
<n-select v-model:value="createModel.network" :options="networks" />
|
||||
</n-form-item>
|
||||
<n-form-item path="mount" label="挂载">
|
||||
<n-form-item path="mount" :label="$gettext('Mount')">
|
||||
<n-space vertical>
|
||||
<n-table striped>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>主机目录</th>
|
||||
<th>容器目录</th>
|
||||
<th>权限</th>
|
||||
<th>操作</th>
|
||||
<th>{{ $gettext('Host Directory') }}</th>
|
||||
<th>{{ $gettext('Container Directory') }}</th>
|
||||
<th>{{ $gettext('Permission') }}</th>
|
||||
<th>{{ $gettext('Actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -259,7 +262,7 @@ onMounted(() => {
|
||||
name="mode"
|
||||
@change="item.mode = $event.target.value"
|
||||
>
|
||||
读写
|
||||
{{ $gettext('Read-Write') }}
|
||||
</n-radio>
|
||||
<n-radio
|
||||
:checked="item.mode === 'ro'"
|
||||
@@ -267,25 +270,25 @@ onMounted(() => {
|
||||
name="mode"
|
||||
@change="item.mode = $event.target.value"
|
||||
>
|
||||
只读
|
||||
{{ $gettext('Read-Only') }}
|
||||
</n-radio>
|
||||
</td>
|
||||
<td><n-button @click="removeVolumeRow(index)" size="small">删除</n-button></td>
|
||||
<td><n-button @click="removeVolumeRow(index)" size="small">{{ $gettext('Delete') }}</n-button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</n-table>
|
||||
<n-button @click="addVolumeRow">添加</n-button>
|
||||
<n-button @click="addVolumeRow">{{ $gettext('Add') }}</n-button>
|
||||
</n-space>
|
||||
</n-form-item>
|
||||
<n-form-item path="command" label="启动命令">
|
||||
<n-dynamic-input v-model:value="createModel.command" placeholder="命令" />
|
||||
<n-form-item path="command" :label="$gettext('Command')">
|
||||
<n-dynamic-input v-model:value="createModel.command" :placeholder="$gettext('Command')" />
|
||||
</n-form-item>
|
||||
<n-form-item path="entrypoint" label="入口点">
|
||||
<n-dynamic-input v-model:value="createModel.entrypoint" placeholder="入口点" />
|
||||
<n-form-item path="entrypoint" :label="$gettext('Entrypoint')">
|
||||
<n-dynamic-input v-model:value="createModel.entrypoint" :placeholder="$gettext('Entrypoint')" />
|
||||
</n-form-item>
|
||||
<n-row :gutter="[0, 24]">
|
||||
<n-col :span="8">
|
||||
<n-form-item path="memory" label="内存">
|
||||
<n-form-item path="memory" :label="$gettext('Memory')">
|
||||
<n-input-number v-model:value="createModel.memory" />
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
@@ -295,61 +298,61 @@ onMounted(() => {
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
<n-col :span="8">
|
||||
<n-form-item path="cpu_shares" label="CPU 权重">
|
||||
<n-form-item path="cpu_shares" :label="$gettext('CPU Shares')">
|
||||
<n-input-number v-model:value="createModel.cpu_shares" />
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
</n-row>
|
||||
<n-row :gutter="[0, 24]">
|
||||
<n-col :span="6">
|
||||
<n-form-item path="tty" label="伪终端(-t)">
|
||||
<n-form-item path="tty" :label="$gettext('TTY (-t)')">
|
||||
<n-switch v-model:value="createModel.tty" />
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
<n-col :span="6">
|
||||
<n-form-item path="open_stdin" label="标准输入(-i)">
|
||||
<n-form-item path="open_stdin" :label="$gettext('STDIN (-i)')">
|
||||
<n-switch v-model:value="createModel.open_stdin" />
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
<n-col :span="6">
|
||||
<n-form-item path="auto_remove" label="退出后自动删除">
|
||||
<n-form-item path="auto_remove" :label="$gettext('Auto Remove')">
|
||||
<n-switch v-model:value="createModel.auto_remove" />
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
<n-col :span="6">
|
||||
<n-form-item path="privileged" label="特权模式">
|
||||
<n-form-item path="privileged" :label="$gettext('Privileged Mode')">
|
||||
<n-switch v-model:value="createModel.privileged" />
|
||||
</n-form-item>
|
||||
</n-col>
|
||||
</n-row>
|
||||
<n-form-item path="restart_policy" label="重启策略">
|
||||
<n-form-item path="restart_policy" :label="$gettext('Restart Policy')">
|
||||
<n-select
|
||||
v-model:value="createModel.restart_policy"
|
||||
placeholder="选择重启策略"
|
||||
:placeholder="$gettext('Select restart policy')"
|
||||
:options="restartPolicyOptions"
|
||||
>
|
||||
{{ createModel.restart_policy || '选择重启策略' }}
|
||||
{{ createModel.restart_policy || $gettext('Select restart policy') }}
|
||||
</n-select>
|
||||
</n-form-item>
|
||||
<n-form-item path="env" label="环境变量">
|
||||
<n-form-item path="env" :label="$gettext('Environment Variables')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.env"
|
||||
preset="pair"
|
||||
key-placeholder="变量名"
|
||||
value-placeholder="变量值"
|
||||
:key-placeholder="$gettext('Variable Name')"
|
||||
:value-placeholder="$gettext('Variable Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="labels" label="标签">
|
||||
<n-form-item path="labels" :label="$gettext('Labels')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.labels"
|
||||
preset="pair"
|
||||
key-placeholder="标签名"
|
||||
value-placeholder="标签值"
|
||||
:key-placeholder="$gettext('Label Name')"
|
||||
:value-placeholder="$gettext('Label Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block :loading="doSubmit" :disabled="doSubmit" @click="handleSubmit">
|
||||
提交
|
||||
{{ $gettext('Submit') }}
|
||||
</n-button>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NDataTable, NDropdown, NFlex, NInput, NSwitch, NTag } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import container from '@/api/panel/container'
|
||||
import ContainerCreate from '@/views/container/ContainerCreate.vue'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const logModal = ref(false)
|
||||
const logs = ref('')
|
||||
const renameModal = ref(false)
|
||||
@@ -19,14 +22,14 @@ const selectedRowKeys = ref<any>([])
|
||||
const columns: any = [
|
||||
{ type: 'selection', fixed: 'left' },
|
||||
{
|
||||
title: '容器名',
|
||||
title: $gettext('Container Name'),
|
||||
key: 'name',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
title: $gettext('Status'),
|
||||
key: 'state',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
@@ -46,7 +49,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '镜像',
|
||||
title: $gettext('Image'),
|
||||
key: 'image',
|
||||
minWidth: 300,
|
||||
resizable: true,
|
||||
@@ -57,7 +60,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '端口(主机->容器)',
|
||||
title: $gettext('Ports (Host->Container)'),
|
||||
key: 'ports',
|
||||
minWidth: 200,
|
||||
resizable: true,
|
||||
@@ -74,14 +77,14 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '运行状态',
|
||||
title: $gettext('Running Status'),
|
||||
key: 'status',
|
||||
width: 300,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: $gettext('Actions'),
|
||||
key: 'actions',
|
||||
width: 250,
|
||||
align: 'center',
|
||||
@@ -97,7 +100,7 @@ const columns: any = [
|
||||
onClick: () => handleShowLog(row)
|
||||
},
|
||||
{
|
||||
default: () => '日志'
|
||||
default: () => $gettext('Logs')
|
||||
}
|
||||
),
|
||||
h(
|
||||
@@ -113,7 +116,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
default: () => '重命名'
|
||||
default: () => $gettext('Rename')
|
||||
}
|
||||
),
|
||||
h(
|
||||
@@ -121,37 +124,37 @@ const columns: any = [
|
||||
{
|
||||
options: [
|
||||
{
|
||||
label: '启动',
|
||||
label: $gettext('Start'),
|
||||
key: 'start',
|
||||
disabled: row.state === 'running'
|
||||
},
|
||||
{
|
||||
label: '停止',
|
||||
label: $gettext('Stop'),
|
||||
key: 'stop',
|
||||
disabled: row.state !== 'running'
|
||||
},
|
||||
{
|
||||
label: '重启',
|
||||
label: $gettext('Restart'),
|
||||
key: 'restart',
|
||||
disabled: row.state !== 'running'
|
||||
},
|
||||
{
|
||||
label: '强制停止',
|
||||
label: $gettext('Force Stop'),
|
||||
key: 'forceStop',
|
||||
disabled: row.state !== 'running'
|
||||
},
|
||||
{
|
||||
label: '暂停',
|
||||
label: $gettext('Pause'),
|
||||
key: 'pause',
|
||||
disabled: row.state !== 'running'
|
||||
},
|
||||
{
|
||||
label: '恢复',
|
||||
label: $gettext('Resume'),
|
||||
key: 'unpause',
|
||||
disabled: row.state === 'running'
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
label: $gettext('Delete'),
|
||||
key: 'delete'
|
||||
}
|
||||
],
|
||||
@@ -191,7 +194,7 @@ const columns: any = [
|
||||
style: 'margin-left: 15px;'
|
||||
},
|
||||
{
|
||||
default: () => '更多'
|
||||
default: () => $gettext('More')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -224,7 +227,7 @@ const handleRename = () => {
|
||||
() => {
|
||||
refresh()
|
||||
renameModal.value = false
|
||||
window.$message.success('重命名成功')
|
||||
window.$message.success($gettext('Rename successful'))
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -232,62 +235,62 @@ const handleRename = () => {
|
||||
const handleStart = (id: string) => {
|
||||
useRequest(container.containerStart(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('启动成功')
|
||||
window.$message.success($gettext('Start successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleStop = (id: string) => {
|
||||
useRequest(container.containerStop(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('停止成功')
|
||||
window.$message.success($gettext('Stop successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleRestart = (id: string) => {
|
||||
useRequest(container.containerRestart(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('重启成功')
|
||||
window.$message.success($gettext('Restart successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleForceStop = (id: string) => {
|
||||
useRequest(container.containerKill(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('强制停止成功')
|
||||
window.$message.success($gettext('Force stop successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handlePause = (id: string) => {
|
||||
useRequest(container.containerPause(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('暂停成功')
|
||||
window.$message.success($gettext('Pause successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleUnpause = (id: string) => {
|
||||
useRequest(container.containerUnpause(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('恢复成功')
|
||||
window.$message.success($gettext('Resume successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
useRequest(container.containerRemove(id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
window.$message.success($gettext('Delete successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handlePrune = () => {
|
||||
useRequest(container.containerPrune()).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('清理成功')
|
||||
window.$message.success($gettext('Cleanup successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const bulkStart = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要启动的容器')
|
||||
window.$message.info($gettext('Please select containers to start'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -296,12 +299,12 @@ const bulkStart = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('启动成功')
|
||||
window.$message.success($gettext('Start successful'))
|
||||
}
|
||||
|
||||
const bulkStop = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要停止的容器')
|
||||
window.$message.info($gettext('Please select containers to stop'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -310,12 +313,12 @@ const bulkStop = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('停止成功')
|
||||
window.$message.success($gettext('Stop successful'))
|
||||
}
|
||||
|
||||
const bulkRestart = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要重启的容器')
|
||||
window.$message.info($gettext('Please select containers to restart'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -324,12 +327,12 @@ const bulkRestart = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('重启成功')
|
||||
window.$message.success($gettext('Restart successful'))
|
||||
}
|
||||
|
||||
const bulkForceStop = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要强制停止的容器')
|
||||
window.$message.info($gettext('Please select containers to force stop'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -338,12 +341,12 @@ const bulkForceStop = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('强制停止成功')
|
||||
window.$message.success($gettext('Force stop successful'))
|
||||
}
|
||||
|
||||
const bulkDelete = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要删除的容器')
|
||||
window.$message.info($gettext('Please select containers to delete'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -352,12 +355,12 @@ const bulkDelete = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
window.$message.success($gettext('Delete successful'))
|
||||
}
|
||||
|
||||
const bulkPause = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要暂停的容器')
|
||||
window.$message.info($gettext('Please select containers to pause'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -366,12 +369,12 @@ const bulkPause = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('暂停成功')
|
||||
window.$message.success($gettext('Pause successful'))
|
||||
}
|
||||
|
||||
const bulkUnpause = async () => {
|
||||
if (selectedRowKeys.value.length === 0) {
|
||||
window.$message.info('请选择要恢复的容器')
|
||||
window.$message.info($gettext('Please select containers to resume'))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -380,7 +383,7 @@ const bulkUnpause = async () => {
|
||||
|
||||
selectedRowKeys.value = []
|
||||
refresh()
|
||||
window.$message.success('恢复成功')
|
||||
window.$message.success($gettext('Resume successful'))
|
||||
}
|
||||
|
||||
const closeContainerCreateModal = () => {
|
||||
@@ -396,16 +399,16 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="containerCreateModal = true">创建容器</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>清理容器</n-button>
|
||||
<n-button type="primary" @click="containerCreateModal = true">{{ $gettext('Create Container') }}</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>{{ $gettext('Cleanup Containers') }}</n-button>
|
||||
<n-button-group>
|
||||
<n-button @click="bulkStart">启动</n-button>
|
||||
<n-button @click="bulkStop">停止</n-button>
|
||||
<n-button @click="bulkRestart">重启</n-button>
|
||||
<n-button @click="bulkForceStop">强制停止</n-button>
|
||||
<n-button @click="bulkPause">暂停</n-button>
|
||||
<n-button @click="bulkUnpause">恢复</n-button>
|
||||
<n-button @click="bulkDelete">删除</n-button>
|
||||
<n-button @click="bulkStart">{{ $gettext('Start') }}</n-button>
|
||||
<n-button @click="bulkStop">{{ $gettext('Stop') }}</n-button>
|
||||
<n-button @click="bulkRestart">{{ $gettext('Restart') }}</n-button>
|
||||
<n-button @click="bulkForceStop">{{ $gettext('Force Stop') }}</n-button>
|
||||
<n-button @click="bulkPause">{{ $gettext('Pause') }}</n-button>
|
||||
<n-button @click="bulkUnpause">{{ $gettext('Resume') }}</n-button>
|
||||
<n-button @click="bulkDelete">{{ $gettext('Delete') }}</n-button>
|
||||
</n-button-group>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
@@ -433,7 +436,7 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="logModal"
|
||||
preset="card"
|
||||
title="日志"
|
||||
:title="$gettext('Logs')"
|
||||
style="width: 80vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
@@ -456,23 +459,23 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="renameModal"
|
||||
preset="card"
|
||||
title="重命名"
|
||||
:title="$gettext('Rename')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-form :model="renameModel">
|
||||
<n-form-item path="name" label="新名称">
|
||||
<n-form-item path="name" :label="$gettext('New Name')">
|
||||
<n-input
|
||||
v-model:value="renameModel.name"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入新名称"
|
||||
:placeholder="$gettext('Enter new name')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block @click="handleRename">提交</n-button>
|
||||
<n-button type="info" block @click="handleRename">{{ $gettext('Submit') }}</n-button>
|
||||
</n-modal>
|
||||
<ContainerCreate :show="containerCreateModal" @close="closeContainerCreateModal" />
|
||||
</template>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NDataTable, NFlex, NInput, NPopconfirm, NTag } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import container from '@/api/panel/container'
|
||||
import { formatDateTime } from '@/utils'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const pullModel = ref({
|
||||
name: '',
|
||||
auth: false,
|
||||
@@ -23,14 +26,14 @@ const columns: any = [
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '容器数',
|
||||
title: $gettext('Container Count'),
|
||||
key: 'containers',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '镜像',
|
||||
title: $gettext('Image'),
|
||||
key: 'repo_tags',
|
||||
minWidth: 200,
|
||||
resizable: true,
|
||||
@@ -47,14 +50,14 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '大小',
|
||||
title: $gettext('Size'),
|
||||
key: 'size',
|
||||
width: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
title: $gettext('Creation Time'),
|
||||
key: 'created_at',
|
||||
width: 200,
|
||||
resizable: true,
|
||||
@@ -63,7 +66,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: $gettext('Actions'),
|
||||
key: 'actions',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
@@ -79,7 +82,7 @@ const columns: any = [
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定删除吗?'
|
||||
return $gettext('Are you sure you want to delete?')
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
@@ -89,7 +92,7 @@ const columns: any = [
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除'
|
||||
default: () => $gettext('Delete')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -113,14 +116,14 @@ const { loading, data, page, total, pageSize, pageCount, refresh } = usePaginati
|
||||
const handleDelete = async (row: any) => {
|
||||
useRequest(container.imageRemove(row.id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
window.$message.success($gettext('Delete successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handlePrune = () => {
|
||||
useRequest(container.imagePrune()).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('清理成功')
|
||||
window.$message.success($gettext('Cleanup successful'))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -129,7 +132,7 @@ const handlePull = () => {
|
||||
useRequest(container.imagePull(pullModel.value))
|
||||
.onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('拉取成功')
|
||||
window.$message.success($gettext('Pull successful'))
|
||||
})
|
||||
.onComplete(() => {
|
||||
loading.value = false
|
||||
@@ -145,8 +148,8 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="pullModal = true">拉取镜像</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>清理镜像</n-button>
|
||||
<n-button type="primary" @click="pullModal = true">{{ $gettext('Pull Image') }}</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>{{ $gettext('Cleanup Images') }}</n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
striped
|
||||
@@ -173,44 +176,44 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="pullModal"
|
||||
preset="card"
|
||||
title="拉取镜像"
|
||||
:title="$gettext('Pull Image')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-form :model="pullModel">
|
||||
<n-form-item path="name" label="镜像名">
|
||||
<n-form-item path="name" :label="$gettext('Image Name')">
|
||||
<n-input
|
||||
v-model:value="pullModel.name"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="docker.io/php:8.3-fpm"
|
||||
:placeholder="$gettext('docker.io/php:8.3-fpm')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="auth" label="验证">
|
||||
<n-form-item path="auth" :label="$gettext('Authentication')">
|
||||
<n-switch v-model:value="pullModel.auth" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="pullModel.auth" path="username" label="用户名">
|
||||
<n-form-item v-if="pullModel.auth" path="username" :label="$gettext('Username')">
|
||||
<n-input
|
||||
v-model:value="pullModel.username"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入用户名"
|
||||
:placeholder="$gettext('Enter username')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="pullModel.auth" path="password" label="密码">
|
||||
<n-form-item v-if="pullModel.auth" path="password" :label="$gettext('Password')">
|
||||
<n-input
|
||||
v-model:value="pullModel.password"
|
||||
type="password"
|
||||
show-password-on="click"
|
||||
@keydown.enter.prevent
|
||||
placeholder="输入密码"
|
||||
:placeholder="$gettext('Enter password')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block :loading="loading" :disabled="loading" @click="handlePull">
|
||||
提交
|
||||
{{ $gettext('Submit') }}
|
||||
</n-button>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import ComposeView from '@/views/container/ComposeView.vue'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
defineOptions({
|
||||
name: 'container-index'
|
||||
@@ -10,25 +11,26 @@ import ImageView from '@/views/container/ImageView.vue'
|
||||
import NetworkView from '@/views/container/NetworkView.vue'
|
||||
import VolumeView from '@/views/container/VolumeView.vue'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const current = ref('container')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-tabs v-model:value="current" type="line" animated>
|
||||
<n-tab-pane name="container" tab="容器">
|
||||
<n-tab-pane name="container" :tab="$gettext('Containers')">
|
||||
<container-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="compose" tab="编排">
|
||||
<n-tab-pane name="compose" :tab="$gettext('Compose')">
|
||||
<compose-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="image" tab="镜像">
|
||||
<n-tab-pane name="image" :tab="$gettext('Images')">
|
||||
<image-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="network" tab="网络">
|
||||
<n-tab-pane name="network" :tab="$gettext('Networks')">
|
||||
<network-view />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="volume" tab="卷">
|
||||
<n-tab-pane name="volume" :tab="$gettext('Volumes')">
|
||||
<volume-view />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NDataTable, NFlex, NInput, NPopconfirm, NTag } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import container from '@/api/panel/container'
|
||||
import { formatDateTime } from '@/utils'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const createModel = ref({
|
||||
name: '',
|
||||
driver: 'bridge',
|
||||
@@ -39,28 +42,28 @@ const selectedRowKeys = ref<any>([])
|
||||
const columns: any = [
|
||||
{ type: 'selection', fixed: 'left' },
|
||||
{
|
||||
title: '名称',
|
||||
title: $gettext('Name'),
|
||||
key: 'name',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '驱动',
|
||||
title: $gettext('Driver'),
|
||||
key: 'driver',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '范围',
|
||||
title: $gettext('Scope'),
|
||||
key: 'scope',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '子网',
|
||||
title: $gettext('Subnet'),
|
||||
key: 'subnet',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
@@ -77,7 +80,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '网关',
|
||||
title: $gettext('Gateway'),
|
||||
key: 'gateway',
|
||||
width: 150,
|
||||
resizable: true,
|
||||
@@ -94,7 +97,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
title: $gettext('Creation Time'),
|
||||
key: 'created_at',
|
||||
width: 200,
|
||||
resizable: true,
|
||||
@@ -103,7 +106,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: $gettext('Actions'),
|
||||
key: 'actions',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
@@ -119,7 +122,7 @@ const columns: any = [
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定删除吗?'
|
||||
return $gettext('Are you sure you want to delete?')
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
@@ -129,7 +132,7 @@ const columns: any = [
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除'
|
||||
default: () => $gettext('Delete')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -153,14 +156,14 @@ const { loading, data, page, total, pageSize, pageCount, refresh } = usePaginati
|
||||
const handleDelete = (row: any) => {
|
||||
useRequest(container.networkRemove(row.id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
window.$message.success($gettext('Delete successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handlePrune = () => {
|
||||
useRequest(container.networkPrune()).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('清理成功')
|
||||
window.$message.success($gettext('Cleanup successful'))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -169,7 +172,7 @@ const handleCreate = () => {
|
||||
useRequest(container.networkCreate(createModel.value))
|
||||
.onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('创建成功')
|
||||
window.$message.success($gettext('Created successfully'))
|
||||
})
|
||||
.onComplete(() => {
|
||||
loading.value = false
|
||||
@@ -185,8 +188,8 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="createModal = true">创建网络</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>清理网络</n-button>
|
||||
<n-button type="primary" @click="createModal = true">{{ $gettext('Create Network') }}</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>{{ $gettext('Cleanup Networks') }}</n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
striped
|
||||
@@ -213,17 +216,17 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="createModal"
|
||||
preset="card"
|
||||
title="创建网络"
|
||||
:title="$gettext('Create Network')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item path="name" label="网络名">
|
||||
<n-form-item path="name" :label="$gettext('Network Name')">
|
||||
<n-input v-model:value="createModel.name" type="text" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="driver" label="驱动">
|
||||
<n-form-item path="driver" :label="$gettext('Driver')">
|
||||
<n-select
|
||||
:options="options"
|
||||
v-model:value="createModel.driver"
|
||||
@@ -235,76 +238,76 @@ onMounted(() => {
|
||||
<n-form-item path="ipv4" label="IPV4">
|
||||
<n-switch v-model:value="createModel.ipv4.enabled" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.ipv4.enabled" path="subnet" label="子网">
|
||||
<n-form-item v-if="createModel.ipv4.enabled" path="subnet" :label="$gettext('Subnet')">
|
||||
<n-input
|
||||
v-model:value="createModel.ipv4.subnet"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="172.16.10.0/24"
|
||||
:placeholder="$gettext('172.16.10.0/24')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.ipv4.enabled" path="gateway" label="网关">
|
||||
<n-form-item v-if="createModel.ipv4.enabled" path="gateway" :label="$gettext('Gateway')">
|
||||
<n-input
|
||||
v-model:value="createModel.ipv4.gateway"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="172.16.10.254"
|
||||
:placeholder="$gettext('172.16.10.254')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.ipv4.enabled" path="ip_range" label="IP范围">
|
||||
<n-form-item v-if="createModel.ipv4.enabled" path="ip_range" :label="$gettext('IP Range')">
|
||||
<n-input
|
||||
v-model:value="createModel.ipv4.ip_range"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="172.16.10.0/24"
|
||||
:placeholder="$gettext('172.16.10.0/24')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="ipv6" label="IPV6">
|
||||
<n-switch v-model:value="createModel.ipv6.enabled" />
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.ipv6.enabled" path="subnet" label="子网">
|
||||
<n-form-item v-if="createModel.ipv6.enabled" path="subnet" :label="$gettext('Subnet')">
|
||||
<n-input
|
||||
v-model:value="createModel.ipv6.subnet"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="2408:400e::/48"
|
||||
:placeholder="$gettext('2408:400e::/48')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.ipv6.enabled" path="gateway" label="网关">
|
||||
<n-form-item v-if="createModel.ipv6.enabled" path="gateway" :label="$gettext('Gateway')">
|
||||
<n-input
|
||||
v-model:value="createModel.ipv6.gateway"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="2408:400e::1"
|
||||
:placeholder="$gettext('2408:400e::1')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="createModel.ipv6.enabled" path="ip_range" label="IP范围">
|
||||
<n-form-item v-if="createModel.ipv6.enabled" path="ip_range" :label="$gettext('IP Range')">
|
||||
<n-input
|
||||
v-model:value="createModel.ipv6.ip_range"
|
||||
type="text"
|
||||
@keydown.enter.prevent
|
||||
placeholder="2408:400e::/64"
|
||||
:placeholder="$gettext('2408:400e::/64')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="env" label="标签">
|
||||
<n-form-item path="env" :label="$gettext('Labels')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.labels"
|
||||
preset="pair"
|
||||
key-placeholder="标签名"
|
||||
value-placeholder="标签值"
|
||||
:key-placeholder="$gettext('Label Name')"
|
||||
:value-placeholder="$gettext('Label Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="env" label="选项">
|
||||
<n-form-item path="env" :label="$gettext('Options')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.options"
|
||||
preset="pair"
|
||||
key-placeholder="选项名"
|
||||
value-placeholder="选项值"
|
||||
:key-placeholder="$gettext('Option Name')"
|
||||
:value-placeholder="$gettext('Option Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block :loading="loading" :disabled="loading" @click="handleCreate">
|
||||
提交
|
||||
{{ $gettext('Submit') }}
|
||||
</n-button>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NDataTable, NInput, NPopconfirm } from 'naive-ui'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import container from '@/api/panel/container'
|
||||
import { formatDateTime } from '@/utils'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const createModel = ref({
|
||||
name: '',
|
||||
driver: 'local',
|
||||
@@ -20,35 +23,35 @@ const selectedRowKeys = ref<any>([])
|
||||
const columns: any = [
|
||||
{ type: 'selection', fixed: 'left' },
|
||||
{
|
||||
title: '名称',
|
||||
title: $gettext('Name'),
|
||||
key: 'name',
|
||||
minWidth: 150,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '驱动',
|
||||
title: $gettext('Driver'),
|
||||
key: 'driver',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '范围',
|
||||
title: $gettext('Scope'),
|
||||
key: 'scope',
|
||||
width: 100,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '挂载点',
|
||||
title: $gettext('Mount Point'),
|
||||
key: 'mount_point',
|
||||
resizable: true,
|
||||
minWidth: 150,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
title: $gettext('Creation Time'),
|
||||
key: 'created_at',
|
||||
width: 200,
|
||||
resizable: true,
|
||||
@@ -57,7 +60,7 @@ const columns: any = [
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
title: $gettext('Actions'),
|
||||
key: 'actions',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
@@ -73,7 +76,7 @@ const columns: any = [
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定删除吗?'
|
||||
return $gettext('Are you sure you want to delete?')
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
@@ -83,7 +86,7 @@ const columns: any = [
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除'
|
||||
default: () => $gettext('Delete')
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -107,14 +110,14 @@ const { loading, data, page, total, pageSize, pageCount, refresh } = usePaginati
|
||||
const handleDelete = async (row: any) => {
|
||||
useRequest(container.volumeRemove(row.id)).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('删除成功')
|
||||
window.$message.success($gettext('Delete successful'))
|
||||
})
|
||||
}
|
||||
|
||||
const handlePrune = () => {
|
||||
useRequest(container.volumePrune()).onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('清理成功')
|
||||
window.$message.success($gettext('Cleanup successful'))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -123,7 +126,7 @@ const handleCreate = () => {
|
||||
useRequest(container.volumeCreate(createModel.value))
|
||||
.onSuccess(() => {
|
||||
refresh()
|
||||
window.$message.success('创建成功')
|
||||
window.$message.success($gettext('Created successfully'))
|
||||
})
|
||||
.onComplete(() => {
|
||||
loading.value = false
|
||||
@@ -139,8 +142,8 @@ onMounted(() => {
|
||||
<template>
|
||||
<n-flex vertical :size="20">
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="createModal = true">创建卷</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>清理卷</n-button>
|
||||
<n-button type="primary" @click="createModal = true">{{ $gettext('Create Volume') }}</n-button>
|
||||
<n-button type="primary" @click="handlePrune" ghost>{{ $gettext('Cleanup Volumes') }}</n-button>
|
||||
</n-flex>
|
||||
<n-data-table
|
||||
striped
|
||||
@@ -167,17 +170,17 @@ onMounted(() => {
|
||||
<n-modal
|
||||
v-model:show="createModal"
|
||||
preset="card"
|
||||
title="创建卷"
|
||||
:title="$gettext('Create Volume')"
|
||||
style="width: 60vw"
|
||||
size="huge"
|
||||
:bordered="false"
|
||||
:segmented="false"
|
||||
>
|
||||
<n-form :model="createModel">
|
||||
<n-form-item path="name" label="卷名">
|
||||
<n-form-item path="name" :label="$gettext('Volume Name')">
|
||||
<n-input v-model:value="createModel.name" type="text" @keydown.enter.prevent />
|
||||
</n-form-item>
|
||||
<n-form-item path="driver" label="驱动">
|
||||
<n-form-item path="driver" :label="$gettext('Driver')">
|
||||
<n-select
|
||||
:options="options"
|
||||
v-model:value="createModel.driver"
|
||||
@@ -186,25 +189,25 @@ onMounted(() => {
|
||||
>
|
||||
</n-select>
|
||||
</n-form-item>
|
||||
<n-form-item path="env" label="标签">
|
||||
<n-form-item path="env" :label="$gettext('Labels')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.labels"
|
||||
preset="pair"
|
||||
key-placeholder="标签名"
|
||||
value-placeholder="标签值"
|
||||
:key-placeholder="$gettext('Label Name')"
|
||||
:value-placeholder="$gettext('Label Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item path="env" label="选项">
|
||||
<n-form-item path="env" :label="$gettext('Options')">
|
||||
<n-dynamic-input
|
||||
v-model:value="createModel.options"
|
||||
preset="pair"
|
||||
key-placeholder="选项名"
|
||||
value-placeholder="选项值"
|
||||
:key-placeholder="$gettext('Option Name')"
|
||||
:value-placeholder="$gettext('Option Value')"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button type="info" block :loading="loading" :disabled="loading" @click="handleCreate">
|
||||
提交
|
||||
{{ $gettext('Submit') }}
|
||||
</n-button>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $gettext } from '@/utils/gettext'
|
||||
import type { RouteType } from '~/types/router'
|
||||
|
||||
const Layout = () => import('@/layout/IndexView.vue')
|
||||
@@ -15,7 +16,7 @@ export default {
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'containerIndex.title',
|
||||
title: $gettext('Container'),
|
||||
icon: 'mdi:layers-outline',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
|
||||
Reference in New Issue
Block a user