diff --git a/backend/app/dto/container.go b/backend/app/dto/container.go index cadc1c780cff..1fa107a26828 100644 --- a/backend/app/dto/container.go +++ b/backend/app/dto/container.go @@ -219,7 +219,7 @@ type ComposeCreate struct { type ComposeOperation struct { Name string `json:"name" validate:"required"` Path string `json:"path" validate:"required"` - Operation string `json:"operation" validate:"required,oneof=up start stop down"` + Operation string `json:"operation" validate:"required,oneof=up start stop down delete"` WithFile bool `json:"withFile"` } type ComposeUpdate struct { diff --git a/backend/app/service/container_compose.go b/backend/app/service/container_compose.go index 953d01b291be..e977a976e4c9 100644 --- a/backend/app/service/container_compose.go +++ b/backend/app/service/container_compose.go @@ -258,30 +258,20 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error { if _, err := os.Stat(req.Path); err != nil { return fmt.Errorf("load file with path %s failed, %v", req.Path, err) } - if req.Operation == "up" { - if stdout, err := compose.Up(req.Path); err != nil { + if req.Operation == "delete" { + if stdout, err := compose.Operate(req.Path, "down"); err != nil { return errors.New(string(stdout)) } - } else { - if stdout, err := compose.Operate(req.Path, req.Operation); err != nil { - return errors.New(string(stdout)) - } - } - global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name) - if req.Operation == "down" { if req.WithFile { - _ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name)) _ = os.RemoveAll(path.Dir(req.Path)) - } else { - composeItem, _ := composeRepo.GetRecord(commonRepo.WithByName(req.Name)) - if composeItem.Path == "" { - upMap := make(map[string]interface{}) - upMap["path"] = req.Path - _ = composeRepo.UpdateRecord(req.Name, upMap) - } } + _ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name)) + return nil } - + if stdout, err := compose.Operate(req.Path, req.Operation); err != nil { + return errors.New(string(stdout)) + } + global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name) return nil } diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 10a7dab0bbe6..61e04ad5dc28 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -772,7 +772,7 @@ const message = { deleteFile: 'Delete file', allDelete: 'Permanently Delete', deleteComposeHelper: - '1. Delete container orchestration records \n2. Delete all container orchestration files, including configuration and persistent files', + 'Delete all files related to container compose, including configuration files and persistent files. Please proceed with caution!', deleteCompose: '" Delete this composition.', apps: 'Apps', local: 'Local', @@ -793,6 +793,8 @@ const message = { composeDetailHelper: 'The compose is created external to 1Panel. The start and stop operations are not supported.', composeOperatorHelper: '{1} operation will be performed on {0}. Do you want to continue?', + composeDownHelper: + 'This will stop and remove all containers and networks under the {0} compose. Do you want to continue?', setting: 'Setting', operatorStatusHelper: 'This action will {0} Docker service, do you want to continue?', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index a684d860fb92..70d319d6878e 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -742,7 +742,7 @@ const message = { composeHelper: '通過 1Panel 編輯或者模版創建的編排,將保存在 {0}/docker/compose 路徑下', deleteFile: '刪除文件', allDelete: '徹底刪除', - deleteComposeHelper: '1. 刪除容器編排記錄 \n2. 刪除容器編排的所有文件,包括配置文件和持久化文件', + deleteComposeHelper: '刪除容器編排的所有文件,包括配置文件和持久化文件,請謹慎操作!', deleteCompose: '" 刪除此編排', apps: '應用商店', local: '本地', @@ -762,6 +762,7 @@ const message = { up: '啟動', composeDetailHelper: '該 compose 為 1Panel 編排外部創建。暫不支持啟停操作。', composeOperatorHelper: '將對 {0} 進行 {1} 操作,是否繼續?', + composeDownHelper: '將停止並刪除 {0} 編排下所有容器及網絡,是否繼續?', setting: '配置', operatorStatusHelper: '此操作將{0}Docker 服務,是否繼續?', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 90247e846421..0a8339239113 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -743,7 +743,7 @@ const message = { composeHelper: '通过 1Panel 编辑或者模版创建的编排,将保存在 {0}/docker/compose 路径下', deleteFile: '删除文件', allDelete: '彻底删除', - deleteComposeHelper: '1. 删除容器编排记录 \n2. 删除容器编排的所有文件,包括配置文件和持久化文件', + deleteComposeHelper: '删除容器编排的所有文件,包括配置文件和持久化文件,请谨慎操作!', deleteCompose: '" 删除此编排', apps: '应用商店', local: '本地', @@ -763,6 +763,7 @@ const message = { up: '启动', composeDetailHelper: '该 compose 为 1Panel 编排外部创建。暂不支持启停操作。', composeOperatorHelper: '将对 {0} 进行 {1} 操作,是否继续?', + composeDownHelper: '将停止并删除 {0} 编排下所有容器及网络,是否继续?', setting: '配置', operatorStatusHelper: '此操作将{0}Docker 服务,是否继续?', diff --git a/frontend/src/views/container/compose/delete/index.vue b/frontend/src/views/container/compose/delete/index.vue index 828a87388b94..098676751b93 100644 --- a/frontend/src/views/container/compose/delete/index.vue +++ b/frontend/src/views/container/compose/delete/index.vue @@ -7,7 +7,7 @@ > - + {{ $t('container.deleteComposeHelper') }} @@ -69,7 +69,7 @@ const submit = async () => { let params = { name: composeName.value, path: composePath.value, - operation: 'down', + operation: 'delete', withFile: deleteFile.value, }; await composeOperator(params) diff --git a/frontend/src/views/container/compose/detail/index.vue b/frontend/src/views/container/compose/detail/index.vue index a102f247ca52..a219deafd4f8 100644 --- a/frontend/src/views/container/compose/detail/index.vue +++ b/frontend/src/views/container/compose/detail/index.vue @@ -260,15 +260,18 @@ const onOperate = async (op: string) => { }; const onComposeOperate = async (operation: string) => { - ElMessageBox.confirm( - i18n.global.t('container.composeOperatorHelper', [composeName.value, i18n.global.t('container.' + operation)]), - i18n.global.t('container.' + operation), - { - confirmButtonText: i18n.global.t('commons.button.confirm'), - cancelButtonText: i18n.global.t('commons.button.cancel'), - type: 'info', - }, - ).then(async () => { + let mes = + operation === 'down' + ? i18n.global.t('container.composeDownHelper', [composeName.value]) + : i18n.global.t('container.composeOperatorHelper', [ + composeName.value, + i18n.global.t('container.' + operation), + ]); + ElMessageBox.confirm(mes, i18n.global.t('container.' + operation), { + confirmButtonText: i18n.global.t('commons.button.confirm'), + cancelButtonText: i18n.global.t('commons.button.cancel'), + type: 'info', + }).then(async () => { let params = { name: composeName.value, path: composePath.value,