Go Wails Docker图形界面管理工具 (1)
1.背景
市面上已有很多顶级Docker 图形界面管理工具,出于学习容器开发目的,计划动手写个简单的界面管理工具
2. 技术选型
2.1 Wails
使用 Go 和 Web 技术编写桌面应用的项目,类似于ElectronJS 。
官方网站 https://wails.io/zh-Hans/docs/introduction/
2.2 Go
Docker本身采用Go编写,官网SDK如下
官方网站 https://docs.docker.com/engine/api/sdk/
2.3 Ant Design Vue
开箱即用的高质量 Vue 组件,使用方便
官方网站 https://www.antdv.com/docs/vue/introduce-cn
3. 当前功能
项目地址 https://github.com/LeoBest2/my-docker-gui
- 容器查看、创建、启动、删除功能
- 其他待研究
4. 效果图
5. 踩的坑备忘
JS异步处理问题:
版本1中调用的ContainerStop
是异步执行的,调用最后的handleRefresh
刷新界面时实际执行的容器可能操作没完成,导致界面操作完成后不变参考: https://blog.csdn.net/weixin_39629679/article/details/111261923 修改为版本2得以解决
版本1
<script setup>
const handleStop = () => {
spinning.value = true;
selectedRows.value.forEach((row) => {
ContainerStop(row.ID).then(() => { message.success(`容器${row.Names[0].substring(1)}停止成功!`); }).catch((e) => message.error(`容器${row.Names[0].substring(1)}停止失败: ${e}!`));
});
handleRefresh();
};
</script>
版本2
<script setup>
const handleStop = () => {
spinning.value = true;
let promises = [];
selectedRows.value.forEach((row) => {
let p = ContainerStop(row.ID)
p.then(() => { message.success(`容器${row.Names[0].substring(1)}停止成功!`); }).catch((e) => message.error(`容器${row.Names[0].substring(1)}停止失败: ${e}!`));
promises.push(p);
});
Promise.all(promises).finally(() => { spinning.value = false; handleRefresh() });
};
</script>
总代码
<template>
<a-spin :spinning="spinning">
<div>
<div class="table-operations">
<a-button @click="handleRefresh">刷新容器</a-button>
<a-popconfirm :title="'确定启动已选的 ' selectedRows.length ' 个容器?'" ok-text="确定" cancel-text="取消"
@confirm="handleStart">
<a-button>启动容器</a-button>
</a-popconfirm>
<a-popconfirm :title="'确定停止已选的 ' selectedRows.length ' 个容器?'" ok-text="确定" cancel-text="取消"
@confirm="handleStop">
<a-button>停止容器</a-button>
</a-popconfirm>
<a-popconfirm :title="'确定删除已选的 ' selectedRows.length ' 个容器?'" ok-text="确定" cancel-text="取消"
@confirm="handleDelete">
<a-button type="danger">删除容器</a-button>
</a-popconfirm>
</div>
<a-table :row-selection="{ onChange: (selectedRowKeys, _selectedRows) => selectedRows = _selectedRows }"
row-key="ID" :columns="columns" :data-source="data" :scroll="{ x: 'max-content' }">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'Names'">
<a-tag v-for="name in record.Names" color="geekblue">{{ name.substring(1) }}</a-tag>
</template>
<template v-else-if="column.dataIndex === 'State'">
<a-tag :color="record.State == 'running' ? 'green' : 'volcano'">{{ record.State }}</a-tag>
</template>
<template v-else-if="column.dataIndex === 'Ports'">
<a-tag v-for="port in record.Ports">
{{ port.IP }}:{{ port.PublicPort }}->{{ port.PrivatePort }}/{{ port.Type }}
</a-tag>
</template>
</template>
</a-table>
</div>
</a-spin>
</template>
<script setup>
import { ref } from 'vue';
import { ContainerList, ContainerStop, ContainerStart, ContainerDelete } from "../../wailsjs/go/main/App";
import { message } from "ant-design-vue";
const spinning = ref(false);
const columns = [{
title: 'ID',
dataIndex: 'ID',
fixed: 'left',
}, {
title: 'NAMES',
dataIndex: 'Names',
fixed: 'left',
}, {
title: 'STATE',
dataIndex: 'State',
fixed: 'left',
}, {
title: 'IMAGE',
dataIndex: 'Image',
}, {
title: 'COMMAND',
dataIndex: 'Command',
}, {
title: 'CREATED',
dataIndex: 'Created',
}
, {
title: 'STATUS',
dataIndex: 'Status',
}, {
title: 'PORTS',
dataIndex: 'Ports',
}];
const data = ref([]);
const selectedRows = ref([]);
const handleRefresh = () => {
ContainerList()
.then((containers) => {
data.value = containers;
})
.catch(e => message.error(e));
};
const handleStart = () => {
spinning.value = true;
let promises = [];
selectedRows.value.forEach((row) => {
let p = ContainerStart(row.ID)
p.then(() => message.success(`容器${row.Names[0].substring(1)}启动成功!`)).catch((e) => message.error(`容器${row.Names[0].substring(1)}启动失败: ${e}!`));
promises.push(p);
});
Promise.all(promises).finally(() => { spinning.value = false; handleRefresh() });
};
const handleStop = () => {
spinning.value = true;
let promises = [];
selectedRows.value.forEach((row) => {
let p = ContainerStop(row.ID)
p.then(() => { message.success(`容器${row.Names[0].substring(1)}停止成功!`); }).catch((e) => message.error(`容器${row.Names[0].substring(1)}停止失败: ${e}!`));
promises.push(p);
});
Promise.all(promises).finally(() => { spinning.value = false; handleRefresh() });
};
const handleDelete = () => {
spinning.value = true;
let promises = [];
selectedRows.value.forEach((row) => {
let p = ContainerDelete(row.ID)
p.then(() => { message.success(`容器${row.Names[0].substring(1)}停止成功!`); }).catch((e) => message.error(`容器${row.Names[0].substring(1)}停止失败: ${e}!`));
promises.push(p);
});
Promise.all(promises).finally(() => { spinning.value = false; handleRefresh() });
};
</script>
<style scoped>
.table-operations {
margin-bottom: 16px;
}
.table-operations>button {
margin-right: 8px;
}
</style>
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfiahj
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01