1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00

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

This commit is contained in:
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>