feat: 容器批量操作增加详情显示 (#2201)

pull/2207/head
ssongliu 2023-09-06 17:14:16 +08:00 committed by GitHub
parent df5a1b3e40
commit ae515b079c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 107 additions and 68 deletions

View File

@ -611,7 +611,7 @@ var AddDatabases = &gormigrate.Migration{
if err := tx.Create(&model.Database{
AppInstallID: redisInfo.ID,
Name: redisInfo.Name,
Type: "mariadb",
Type: "redis",
Version: redisInfo.Version,
From: "local",
Address: redisInfo.ServiceName,
@ -627,7 +627,7 @@ var AddDatabases = &gormigrate.Migration{
if err := tx.Create(&model.Database{
AppInstallID: pgInfo.ID,
Name: pgInfo.Name,
Type: "mariadb",
Type: "postgresql",
Version: pgInfo.Version,
From: "local",
Address: pgInfo.ServiceName,
@ -643,7 +643,7 @@ var AddDatabases = &gormigrate.Migration{
if err := tx.Create(&model.Database{
AppInstallID: mongodbInfo.ID,
Name: mongodbInfo.Name,
Type: "mariadb",
Type: "mongodb",
Version: mongodbInfo.Version,
From: "local",
Address: mongodbInfo.ServiceName,
@ -659,7 +659,7 @@ var AddDatabases = &gormigrate.Migration{
if err := tx.Create(&model.Database{
AppInstallID: memcachedInfo.ID,
Name: memcachedInfo.Name,
Type: "mariadb",
Type: "memcached",
Version: memcachedInfo.Version,
From: "local",
Address: memcachedInfo.ServiceName,

View File

@ -470,9 +470,9 @@ const message = {
updateContaienrHelper:
'Container editing requires rebuilding the container. Any data that has not been persisted will be lost. Do you want to continue?',
containerList: 'Container list',
operatorHelper: '{0} will be performed on the selected container. Do you want to continue?',
operatorHelper: '{0} will be performed on the following container, Do you want to continue?',
operatorAppHelper:
'There is a container from the App store. The {0} operation may affect the normal use of this service. Are you sure?',
'The {0} operation will be performed on the following containers, some of which are from the App Store. This operation may affect the normal use of the service, Do you want to continue?',
start: 'Start',
stop: 'Stop',
restart: 'Restart',

View File

@ -459,8 +459,9 @@ const message = {
edit: '',
updateContaienrHelper: '',
containerList: '',
operatorHelper: ' {0} ',
operatorAppHelper: '{0} 使',
operatorHelper: ' {0} ',
operatorAppHelper:
' {0} 使',
start: '',
stop: '',
restart: '',

View File

@ -459,8 +459,9 @@ const message = {
edit: '',
updateContaienrHelper: '',
containerList: '',
operatorHelper: ' {0} ',
operatorAppHelper: '{0} 使',
operatorHelper: ' {0} ',
operatorAppHelper:
' {0} 使',
start: '',
stop: '',
restart: '',

View File

@ -245,6 +245,7 @@ html {
// search
.search-button {
float: right;
margin-right: 10px;
.el-input__wrapper {
border-radius: 50px;
}

View File

@ -106,6 +106,7 @@
<ContainerLogDialog ref="dialogContainerLogRef" />
<MonitorDialog ref="dialogMonitorRef" />
<TerminalDialog ref="dialogTerminalRef" />
<HandleDialog @search="search" ref="handleRef" />
</template>
</LayoutContent>
</div>
@ -117,10 +118,11 @@ import Tooltip from '@/components/tooltip/index.vue';
import MonitorDialog from '@/views/container/container/monitor/index.vue';
import ContainerLogDialog from '@/views/container/container/log/index.vue';
import TerminalDialog from '@/views/container/container/terminal/index.vue';
import HandleDialog from '@/views/container/container/handle/index.vue';
import CodemirrorDialog from '@/components/codemirror-dialog/index.vue';
import Status from '@/components/status/index.vue';
import { dateFormat } from '@/utils/util';
import { composeOperator, containerOperator, inspect, searchContainer } from '@/api/modules/container';
import { composeOperator, inspect, searchContainer } from '@/api/modules/container';
import { ElMessageBox } from 'element-plus';
import i18n from '@/lang';
import { Container } from '@/api/interface/container';
@ -131,6 +133,9 @@ const composePath = ref();
const filters = ref();
const createdBy = ref();
const dialogContainerLogRef = ref();
const handleRef = ref();
const emit = defineEmits<{ (e: 'back'): void }>();
interface DialogProps {
createdBy: string;
@ -228,35 +233,14 @@ const checkStatus = (operation: string) => {
const onOperate = async (operation: string) => {
let msg = i18n.global.t('container.operatorHelper', [i18n.global.t('container.' + operation)]);
let containers = [];
for (const item of selects.value) {
containers.push(item.name);
if (item.isFromApp) {
msg = i18n.global.t('container.operatorAppHelper', [i18n.global.t('container.' + operation)]);
break;
}
}
ElMessageBox.confirm(msg, i18n.global.t('container.' + operation), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
}).then(() => {
let ps = [];
for (const item of selects.value) {
const param = {
name: item.name,
operation: operation,
newName: '',
};
ps.push(containerOperator(param));
}
Promise.all(ps)
.then(() => {
search();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
search();
});
});
handleRef.value.acceptParams({ containers: containers, operation: operation, msg: msg });
};
const onComposeOperate = async (operation: string) => {
@ -302,8 +286,6 @@ const onTerminal = (row: any) => {
dialogTerminalRef.value!.acceptParams({ containerID: row.containerID, container: row.name });
};
const dialogContainerLogRef = ref();
const buttons = [
{
label: i18n.global.t('file.terminal'),

View File

@ -0,0 +1,77 @@
<template>
<el-dialog v-model="open" :title="$t('app.delete')" width="30%" :close-on-click-modal="false">
<div>
<span class="lineClass" style="color: red">{{ msg }}</span>
<ul>
<li class="lineClass" v-for="(row, index) in containers" :key="index">{{ row }}</li>
</ul>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="open = false" :disabled="loading">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button type="primary" @click="onConfirm" v-loading="loading">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import i18n from '@/lang';
import { ref } from 'vue';
import { containerOperator } from '@/api/modules/container';
import { MsgSuccess } from '@/utils/message';
const open = ref(false);
const containers = ref();
const msg = ref();
const operation = ref();
const loading = ref(false);
const em = defineEmits(['search']);
interface DialogProps {
containers: Array<string>;
operation: string;
msg: string;
}
const acceptParams = (props: DialogProps) => {
containers.value = props.containers;
operation.value = props.operation;
msg.value = props.msg;
open.value = true;
};
const onConfirm = () => {
const pros = [];
for (const item of containers.value) {
pros.push(containerOperator({ name: item, operation: operation.value, newName: '' }));
}
loading.value = true;
Promise.all(pros)
.then(() => {
open.value = false;
loading.value = false;
em('search');
MsgSuccess(i18n.global.t('commons.msg.deleteSuccess'));
})
.finally(() => {
open.value = false;
loading.value = false;
em('search');
});
};
defineExpose({
acceptParams,
});
</script>
<style scoped>
.lineClass {
line-height: 25px;
}
</style>

View File

@ -179,6 +179,7 @@
<TerminalDialog ref="dialogTerminalRef" />
<PortJumpDialog ref="dialogPortJumpRef" />
<HandleDialog @search="search" ref="handleRef" />
</div>
</template>
@ -192,23 +193,22 @@ import UpgraeDialog from '@/views/container/container/upgrade/index.vue';
import MonitorDialog from '@/views/container/container/monitor/index.vue';
import ContainerLogDialog from '@/views/container/container/log/index.vue';
import TerminalDialog from '@/views/container/container/terminal/index.vue';
import HandleDialog from '@/views/container/container/handle/index.vue';
import CodemirrorDialog from '@/components/codemirror-dialog/index.vue';
import PortJumpDialog from '@/components/port-jump/index.vue';
import Status from '@/components/status/index.vue';
import { reactive, onMounted, ref, computed } from 'vue';
import {
containerListStats,
containerOperator,
inspect,
loadContainerInfo,
loadDockerStatus,
searchContainer,
} from '@/api/modules/container';
import { Container } from '@/api/interface/container';
import { ElMessageBox } from 'element-plus';
import i18n from '@/lang';
import router from '@/routers';
import { MsgSuccess, MsgWarning } from '@/utils/message';
import { MsgWarning } from '@/utils/message';
import { GlobalStore } from '@/store';
const globalStore = GlobalStore();
@ -229,6 +229,7 @@ const paginationConfig = reactive({
const searchName = ref();
const dialogUpgradeRef = ref();
const dialogPortJumpRef = ref();
const handleRef = ref();
const dockerStatus = ref('Running');
const loadStatus = async () => {
@ -415,38 +416,14 @@ const checkStatus = (operation: string, row: Container.ContainerInfo | null) =>
const onOperate = async (operation: string, row: Container.ContainerInfo | null) => {
let opList = row ? [row] : selects.value;
let msg = i18n.global.t('container.operatorHelper', [i18n.global.t('container.' + operation)]);
let containers = [];
for (const item of opList) {
containers.push(item.name);
if (item.isFromApp) {
msg = i18n.global.t('container.operatorAppHelper', [i18n.global.t('container.' + operation)]);
break;
}
}
ElMessageBox.confirm(msg, i18n.global.t('container.' + operation), {
confirmButtonText: i18n.global.t('commons.button.confirm'),
cancelButtonText: i18n.global.t('commons.button.cancel'),
type: 'info',
}).then(() => {
let ps = [];
for (const item of opList) {
const param = {
name: item.name,
operation: operation,
newName: '',
};
ps.push(containerOperator(param));
}
loading.value = true;
Promise.all(ps)
.then(() => {
loading.value = false;
search();
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
})
.catch(() => {
loading.value = false;
search();
});
});
handleRef.value.acceptParams({ containers: containers, operation: operation, msg: msg });
};
const buttons = [

View File

@ -2,7 +2,7 @@
<el-dialog v-model="dialogVisiable" :title="$t('container.containerPrune')" :destroy-on-close="true" width="30%">
<div>
<ul class="help-ul">
<li lineClass style="color: red">{{ $t('container.containerPruneHelper1') }}</li>
<li class="lineClass" style="color: red">{{ $t('container.containerPruneHelper1') }}</li>
<li class="lineClass">{{ $t('container.containerPruneHelper2') }}</li>
<li class="lineClass">{{ $t('container.containerPruneHelper3') }}</li>
</ul>