mirror of https://github.com/1Panel-dev/1Panel
feat: 编排删除增加删除文件勾选 (#808)
parent
5b68332b9a
commit
b42cf32326
|
@ -146,6 +146,7 @@ type ComposeOperation struct {
|
|||
Name string `json:"name" validate:"required"`
|
||||
Path string `json:"path" validate:"required"`
|
||||
Operation string `json:"operation" validate:"required,oneof=start stop down"`
|
||||
WithFile bool `json:"withFile"`
|
||||
}
|
||||
type ComposeUpdate struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
|
|
|
@ -182,7 +182,9 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
|
|||
global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name)
|
||||
if req.Operation == "down" {
|
||||
_ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name))
|
||||
_ = os.RemoveAll(strings.ReplaceAll(req.Path, "/docker-compose.yml", ""))
|
||||
if req.WithFile {
|
||||
_ = os.RemoveAll(path.Dir(req.Path))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -208,6 +208,7 @@ export namespace Container {
|
|||
name: string;
|
||||
operation: string;
|
||||
path: string;
|
||||
withFile: boolean;
|
||||
}
|
||||
export interface ComposeUpdate {
|
||||
name: string;
|
||||
|
|
|
@ -546,6 +546,11 @@ const message = {
|
|||
compose: 'Compose',
|
||||
fromChangeHelper: 'Switching the source will clear the current edited content. Do you want to continue?',
|
||||
composePathHelper: 'Config file save path: {0}',
|
||||
composeHelper:
|
||||
'The composition created through 1Panel editor or template will be saved in the {0}/docker/compose directory.',
|
||||
deleteFile: 'Delete file',
|
||||
deleteComposeHelper: 'Delete the corresponding composition file.',
|
||||
deleteCompose: '" Delete this composition.',
|
||||
apps: 'Apps',
|
||||
local: 'Local',
|
||||
createCompose: 'Create compose',
|
||||
|
|
|
@ -563,6 +563,10 @@ const message = {
|
|||
compose: '编排',
|
||||
fromChangeHelper: '切换来源将清空当前已编辑内容,是否继续?',
|
||||
composePathHelper: '配置文件保存路径: {0}',
|
||||
composeHelper: '通过 1Panel 编辑或者模版创建的编排,将保存在 {0}/docker/compose 路径下',
|
||||
deleteFile: '删除文件',
|
||||
deleteComposeHelper: '删除对应的编排文件',
|
||||
deleteCompose: '" 删除此编排',
|
||||
apps: '应用商店',
|
||||
local: '本地',
|
||||
createCompose: '创建编排',
|
||||
|
|
|
@ -172,6 +172,7 @@ const acceptParams = (): void => {
|
|||
form.from = 'edit';
|
||||
form.path = '';
|
||||
form.file = '';
|
||||
form.template = null;
|
||||
logInfo.value = '';
|
||||
loadTemplates();
|
||||
loadPath();
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisiable"
|
||||
:title="$t('commons.button.delete') + ' - ' + composeName"
|
||||
width="30%"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form ref="deleteForm" v-loading="loading">
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="deleteFile" :label="$t('container.deleteFile')" />
|
||||
<span class="input-help">
|
||||
{{ $t('container.deleteComposeHelper') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div>
|
||||
<span style="font-size: 12px">{{ $t('database.delete') }}</span>
|
||||
<span style="font-size: 12px; color: red; font-weight: 500">{{ composeName }}</span>
|
||||
<span style="font-size: 12px">{{ $t('container.deleteCompose') }}</span>
|
||||
</div>
|
||||
<el-input v-model="deleteInfo" :placeholder="composeName"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="dialogVisiable = false" :disabled="loading">
|
||||
{{ $t('commons.button.cancel') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="submit" :disabled="deleteInfo != composeName || loading">
|
||||
{{ $t('commons.button.confirm') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { ref } from 'vue';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { composeOperator } from '@/api/modules/container';
|
||||
|
||||
let dialogVisiable = ref(false);
|
||||
let loading = ref(false);
|
||||
let deleteInfo = ref('');
|
||||
|
||||
const deleteFile = ref();
|
||||
const composeName = ref();
|
||||
const composePath = ref();
|
||||
|
||||
const deleteForm = ref<FormInstance>();
|
||||
|
||||
interface DialogProps {
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
|
||||
const acceptParams = async (prop: DialogProps) => {
|
||||
deleteFile.value = false;
|
||||
composeName.value = prop.name;
|
||||
composePath.value = prop.path;
|
||||
deleteInfo.value = '';
|
||||
dialogVisiable.value = true;
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
loading.value = true;
|
||||
let params = {
|
||||
name: composeName.value,
|
||||
path: composePath.value,
|
||||
operation: 'down',
|
||||
withFile: deleteFile.value,
|
||||
};
|
||||
await composeOperator(params)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
emit('search');
|
||||
MsgSuccess(i18n.global.t('commons.msg.deleteSuccess'));
|
||||
dialogVisiable.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
|
@ -10,6 +10,20 @@
|
|||
</el-card>
|
||||
|
||||
<LayoutContent v-if="!isOnDetail" :title="$t('container.compose')" :class="{ mask: dockerStatus != 'Running' }">
|
||||
<template #prompt>
|
||||
<el-alert type="info" :closable="false">
|
||||
<template #default>
|
||||
<span>
|
||||
<span>{{ $t('container.composeHelper', [baseDir]) }}</span>
|
||||
<el-button type="primary" link @click="toFolder">
|
||||
<el-icon>
|
||||
<FolderOpened />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
</template>
|
||||
<template #toolbar>
|
||||
<el-row>
|
||||
<el-col :span="16">
|
||||
|
@ -72,6 +86,7 @@
|
|||
|
||||
<EditDialog ref="dialogEditRef" />
|
||||
<CreateDialog @search="search" ref="dialogRef" />
|
||||
<DeleteDialog @search="search" ref="dialogDelRef" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -83,12 +98,13 @@ import { reactive, onMounted, ref } from 'vue';
|
|||
import LayoutContent from '@/layout/layout-content.vue';
|
||||
import EditDialog from '@/views/container/compose/edit/index.vue';
|
||||
import CreateDialog from '@/views/container/compose/create/index.vue';
|
||||
import DeleteDialog from '@/views/container/compose/delete/index.vue';
|
||||
import ComposeDetial from '@/views/container/compose/detail/index.vue';
|
||||
import { composeOperator, loadDockerStatus, searchCompose } from '@/api/modules/container';
|
||||
import { loadDockerStatus, searchCompose } from '@/api/modules/container';
|
||||
import i18n from '@/lang';
|
||||
import { Container } from '@/api/interface/container';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import { LoadFile } from '@/api/modules/files';
|
||||
import { loadBaseDir } from '@/api/modules/setting';
|
||||
import router from '@/routers';
|
||||
|
||||
const data = ref();
|
||||
|
@ -96,6 +112,7 @@ const selects = ref<any>([]);
|
|||
const loading = ref(false);
|
||||
|
||||
const isOnDetail = ref(false);
|
||||
const baseDir = ref();
|
||||
|
||||
const paginationConfig = reactive({
|
||||
currentPage: 1,
|
||||
|
@ -124,6 +141,15 @@ const goSetting = async () => {
|
|||
router.push({ name: 'ContainerSetting' });
|
||||
};
|
||||
|
||||
const toFolder = async () => {
|
||||
router.push({ path: '/hosts/files', query: { path: baseDir.value + '/docker/compose' } });
|
||||
};
|
||||
|
||||
const loadPath = async () => {
|
||||
const pathRes = await loadBaseDir();
|
||||
baseDir.value = pathRes.data;
|
||||
};
|
||||
|
||||
const search = async () => {
|
||||
let params = {
|
||||
info: searchName.value,
|
||||
|
@ -163,14 +189,13 @@ const onOpenDialog = async () => {
|
|||
dialogRef.value!.acceptParams();
|
||||
};
|
||||
|
||||
const dialogDelRef = ref();
|
||||
const onDelete = async (row: Container.ComposeInfo) => {
|
||||
const param = {
|
||||
name: row.name,
|
||||
path: row.path,
|
||||
operation: 'down',
|
||||
};
|
||||
await useDeleteData(composeOperator, param, 'commons.msg.delete');
|
||||
search();
|
||||
dialogDelRef.value.acceptParams(param);
|
||||
};
|
||||
|
||||
const dialogEditRef = ref();
|
||||
|
@ -205,6 +230,7 @@ const buttons = [
|
|||
},
|
||||
];
|
||||
onMounted(() => {
|
||||
loadPath();
|
||||
loadStatus();
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue