Feat: add container list

This commit is contained in:
Lazy 2023-10-18 23:12:40 +08:00
parent 6721f1e271
commit c4a169b1ac
4 changed files with 178 additions and 9 deletions

View File

@ -1,8 +1,8 @@
import { useDefineApi } from "@/stores/useDefineApi";
import type { ImageInfo, DockerNetworkModes } from "@/types";
import type { ImageInfo, DockerNetworkModes, ContainerInfo } from "@/types";
// 获取镜像列表
export const ImageList = useDefineApi<
export const imageList = useDefineApi<
{
params: {
remote_uuid: string;
@ -27,3 +27,17 @@ export const getNetworkModeList = useDefineApi<
url: "/api/environment/networkModes",
method: "GET"
});
// 获取容器列表
export const containerList = useDefineApi<
{
params: {
remote_uuid: string;
imageId?: string;
};
},
ContainerInfo[]
>({
url: "/api/environment/containers",
method: "GET"
});

View File

@ -155,6 +155,61 @@ export interface DockerNetworkModes {
};
}
export interface ContainerInfo {
Id: string;
Names: string[];
Image: string;
ImageID: string;
Command: string;
Created: number;
Ports: {
IP: string;
PrivatePort: number;
PublicPort: number;
Type: string;
}[];
Labels: {
[propName: string]: unknown;
};
State: string;
Status: string;
HostConfig: {
NetworkMode: string;
[propName: string]: unknown;
};
NetworkSettings: {
Networks: {
bridge: {
IPAMConfig: null;
Links: null;
Aliases: null;
NetworkID: string;
EndpointID: string;
Gateway: string;
IPAddress: string;
IPPrefixLen: number;
IPv6Gateway: string;
GlobalIPv6Address: string;
GlobalIPv6PrefixLen: number;
MacAddress: string;
DriverOpts: null;
[propName: string]: unknown;
};
[propName: string]: unknown;
};
};
Mounts: [
{
Type: string;
Source: string;
Destination: string;
Mode: string;
RW: true;
Propagation: string;
}
];
}
export interface NewInstanceForm {
nickname: string;
startCommand: string;

View File

@ -2,14 +2,14 @@
import { ref, computed, onMounted, h } from "vue";
import { t } from "@/lang/i18n";
import { Modal, message, notification } from "ant-design-vue";
import { DownOutlined, PlusOutlined } from "@ant-design/icons-vue";
import { PlusOutlined } from "@ant-design/icons-vue";
import CardPanel from "@/components/CardPanel.vue";
import BetweenMenus from "@/components/BetweenMenus.vue";
import { useScreen } from "../hooks/useScreen";
import { arrayFilter } from "../tools/array";
import { useLayoutCardTools } from "@/hooks/useCardTools";
import { ImageList } from "@/services/apis/envImage";
import type { LayoutCard, ImageInfo } from "@/types";
import { imageList, containerList } from "@/services/apis/envImage";
import type { LayoutCard, ImageInfo, ContainerInfo } from "@/types";
const props = defineProps<{
card: LayoutCard;
}>();
@ -18,7 +18,7 @@ const { getMetaOrRouteValue } = useLayoutCardTools(props.card);
const daemonId: string | undefined = getMetaOrRouteValue("daemonId");
const screen = useScreen();
const { execute: execImageList, state: images, isLoading: ImageListLoading } = ImageList();
const { execute: execImageList, state: images, isLoading: imageListLoading } = imageList();
const getImageList = async () => {
try {
await execImageList({
@ -109,8 +109,71 @@ const delImage = async (item: ImageInfo) => {
}
};
const containerDataSource = ref<ContainerInfo[]>();
const containerColumns = computed(() => {
return arrayFilter([
{
align: "center",
title: "ID",
dataIndex: "Id",
key: "Id",
minWidth: "200px"
},
{
align: "center",
title: t("启动命令"),
dataIndex: "Command",
key: "Command"
},
{
align: "center",
title: t("使用镜像"),
dataIndex: "Image",
key: "Image"
},
{
align: "center",
title: t("状态"),
dataIndex: "State",
key: "State"
},
{
align: "center",
title: t("情况"),
dataIndex: "Status",
key: "Status"
},
{
align: "center",
title: t("TXT_CODE_fe731dfc"),
key: "action",
minWidth: "200px"
}
]);
});
const {
execute: execContainerList,
state: containers,
isLoading: containerListLoading
} = containerList();
const getContainerList = async () => {
try {
await execContainerList({
params: {
remote_uuid: daemonId ?? ""
}
});
if (containers.value) containerDataSource.value = containers.value;
} catch (err: any) {
console.error(err);
return message.error(err.message);
}
};
onMounted(async () => {
await getImageList();
await getContainerList();
});
</script>
@ -156,7 +219,7 @@ onMounted(async () => {
pageSize: 10,
showSizeChanger: true
}"
:loading="ImageListLoading"
:loading="imageListLoading"
size="small"
>
<template #bodyCell="{ column, record }">
@ -178,6 +241,43 @@ onMounted(async () => {
</template>
</CardPanel>
</a-col>
<a-col :span="24">
<CardPanel style="height: 100%">
<template #title>
{{ t("远程主机容器列表") }}
</template>
<template #body>
<a-typography-paragraph>
<a-typography-text>
{{
t(
"容器列表代表所有正在独立镜像环境运行的应用实例,此处列表不仅仅包括面板所启动的容器。"
)
}}
</a-typography-text>
</a-typography-paragraph>
<a-table
:data-source="containerDataSource"
:columns="containerColumns"
:pagination="{
pageSize: 10,
showSizeChanger: true
}"
:loading="containerListLoading"
size="small"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-button class="mr-8" size="" @click="showDetail(record)">
{{ t("详情") }}
</a-button>
</template>
</template>
</a-table>
</template>
</CardPanel>
</a-col>
</a-row>
</div>
</template>

View File

@ -6,7 +6,7 @@ import type { InstanceDetail, DockerNetworkModes } from "@/types";
import type { FormInstance } from "ant-design-vue";
import type { Rule } from "ant-design-vue/es/form";
import { updateAnyInstanceConfig } from "@/services/apis/instance";
import { ImageList, getNetworkModeList } from "@/services/apis/envImage";
import { imageList, getNetworkModeList } from "@/services/apis/envImage";
import { message } from "ant-design-vue";
import { TERMINAL_CODE } from "@/types/const";
import { INSTANCE_TYPE_TRANSLATION } from "@/hooks/useInstance";
@ -35,7 +35,7 @@ const { execute: executeGetNetworkModeList } = getNetworkModeList();
const networkModes = ref<DockerNetworkModes[]>([]);
const { execute, isLoading } = updateAnyInstanceConfig();
const formRef = ref<FormInstance>();
const { execute: getImageList } = ImageList();
const { execute: getImageList } = imageList();
const dockerImages = ref<string[]>([]);
const openDialog = () => {