diff --git a/backend/app/api/v1/database_mysql.go b/backend/app/api/v1/database_mysql.go index 16bff6396..6370df3ee 100644 --- a/backend/app/api/v1/database_mysql.go +++ b/backend/app/api/v1/database_mysql.go @@ -217,7 +217,7 @@ func (b *BaseApi) DeleteCheckMysql(c *gin.Context) { } func (b *BaseApi) DeleteMysql(c *gin.Context) { - var req dto.OperateByID + var req dto.MysqlDBDelete if err := c.ShouldBindJSON(&req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) return @@ -227,7 +227,7 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) { return } - if err := mysqlService.Delete(req.ID); err != nil { + if err := mysqlService.Delete(req); err != nil { helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) return } diff --git a/backend/app/dto/database.go b/backend/app/dto/database.go index 234d2f41e..e6b18938b 100644 --- a/backend/app/dto/database.go +++ b/backend/app/dto/database.go @@ -28,6 +28,12 @@ type MysqlDBCreate struct { Description string `json:"description"` } +type MysqlDBDelete struct { + ID uint `json:"id" validate:"required"` + ForceDelete bool `json:"forceDelete"` + DeleteBackup bool `json:"deleteBackup"` +} + type MysqlStatus struct { AbortedClients string `json:"Aborted_clients"` AbortedConnects string `json:"Aborted_connects"` diff --git a/backend/app/service/database_mysql.go b/backend/app/service/database_mysql.go index 986c25df9..baac7ce85 100644 --- a/backend/app/service/database_mysql.go +++ b/backend/app/service/database_mysql.go @@ -44,7 +44,7 @@ type IMysqlService interface { Recover(db dto.RecoverDB) error DeleteCheck(id uint) ([]string, error) - Delete(id uint) error + Delete(req dto.MysqlDBDelete) error LoadStatus() (*dto.MysqlStatus, error) LoadVariables() (*dto.MysqlVariables, error) LoadBaseInfo() (*dto.DBBaseInfo, error) @@ -256,36 +256,37 @@ func (u *MysqlService) DeleteCheck(id uint) ([]string, error) { return appInUsed, nil } -func (u *MysqlService) Delete(id uint) error { +func (u *MysqlService) Delete(req dto.MysqlDBDelete) error { app, err := appInstallRepo.LoadBaseInfo("mysql", "") - if err != nil { + if err != nil && !req.ForceDelete { return err } - db, err := mysqlRepo.Get(commonRepo.WithByID(id)) - if err != nil { + db, err := mysqlRepo.Get(commonRepo.WithByID(req.ID)) + if err != nil && !req.ForceDelete { return err } - if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", db.Name, db.Permission)); err != nil { + if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop user if exists '%s'@'%s'", db.Name, db.Permission)); err != nil && !req.ForceDelete { return err } - if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil { + if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil && !req.ForceDelete { return err } - uploadDir := fmt.Sprintf("%s/uploads/%s/mysql/%s", constant.DefaultDataDir, app.Name, db.Name) + uploadDir := fmt.Sprintf("%s/uploads/database/mysql/%s/%s", constant.DefaultDataDir, app.Name, db.Name) if _, err := os.Stat(uploadDir); err == nil { _ = os.RemoveAll(uploadDir) } - - localDir, err := loadLocalDir() - if err != nil { - return err - } - backupDir := fmt.Sprintf("%s/database/mysql/%s/%s", localDir, db.MysqlName, db.Name) - if _, err := os.Stat(backupDir); err == nil { - _ = os.RemoveAll(backupDir) + if req.DeleteBackup { + localDir, err := loadLocalDir() + if err != nil && !req.ForceDelete { + return err + } + backupDir := fmt.Sprintf("%s/database/mysql/%s/%s", localDir, db.MysqlName, db.Name) + if _, err := os.Stat(backupDir); err == nil { + _ = os.RemoveAll(backupDir) + } } _ = backupRepo.DeleteRecord(context.Background(), commonRepo.WithByType("database-mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name)) diff --git a/backend/middleware/operation.go b/backend/middleware/operation.go index a1096f8c4..f6e206364 100644 --- a/backend/middleware/operation.go +++ b/backend/middleware/operation.go @@ -68,18 +68,16 @@ func OperationLog() gin.HandlerFunc { if len(operationDic.BeforeFuntions) != 0 { for _, funcs := range operationDic.BeforeFuntions { for key, value := range formatMap { - if funcs.Info == key { + if funcs.InputValue == key { var names []string if funcs.IsList { - if key == "ids" { - sql := fmt.Sprintf("SELECT %s FROM %s where id in (?);", funcs.Key, funcs.DB) - fmt.Println(value) - _ = global.DB.Raw(sql, value).Scan(&names) - } + sql := fmt.Sprintf("SELECT %s FROM %s where %s in (?);", funcs.OutputColume, funcs.DB, funcs.InputColume) + fmt.Println(value) + _ = global.DB.Raw(sql, value).Scan(&names) } else { - _ = global.DB.Raw(fmt.Sprintf("select %s from %s where %s = ?;", funcs.Key, funcs.DB, key), value).Scan(&names) + _ = global.DB.Raw(fmt.Sprintf("select %s from %s where %s = ?;", funcs.OutputColume, funcs.DB, funcs.InputColume), value).Scan(&names) } - formatMap[funcs.Value] = strings.Join(names, ",") + formatMap[funcs.OutputValue] = strings.Join(names, ",") break } } @@ -136,11 +134,12 @@ type operationJson struct { FormatEN string `json:"formatEN"` } type functionInfo struct { - Info string `json:"info"` - IsList bool `json:"isList"` - DB string `json:"db"` - Key string `json:"key"` - Value string `json:"value"` + InputColume string `json:"input_colume"` + InputValue string `json:"input_value"` + IsList bool `json:"isList"` + DB string `json:"db"` + OutputColume string `json:"output_colume"` + OutputValue string `json:"output_value"` } type response struct { diff --git a/cmd/server/operation/operation.json b/cmd/server/operation/operation.json index 065253fdf..ce64ccad9 100644 --- a/cmd/server/operation/operation.json +++ b/cmd/server/operation/operation.json @@ -44,11 +44,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_column": "id", + "input_value": "id", "isList": false, "db": "image_repos", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "更新镜像仓库 [name]", @@ -63,11 +64,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "image_repos", - "key": "name", - "value": "names" + "output_colume": "name", + "output_value": "names" } ], "formatZH": "删除镜像仓库 [names]", @@ -116,11 +118,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "compose_templates", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "更新 compose 模版 [name]", @@ -146,11 +149,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "compose_templates", - "key": "name", - "value": "names" + "output_colume": "name", + "output_value": "names" } ], "formatZH": "删除 compose 模版 [names]", @@ -166,11 +170,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "repoID", + "input_colume": "id", + "input_value": "repoID", "isList": false, "db": "image_repos", - "key": "name", - "value": "reponame" + "output_colume": "name", + "output_value": "reponame" } ], "formatZH": "镜像拉取 [reponame][imageName]", @@ -187,11 +192,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "repoID", + "input_colume": "id", + "input_value": "repoID", "isList": false, "db": "image_repos", - "key": "name", - "value": "reponame" + "output_colume": "name", + "output_value": "reponame" } ], "formatZH": "[tagName] 推送到 [reponame][name]", @@ -242,11 +248,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "repoID", + "input_colume": "id", + "input_value": "repoID", "isList": false, "db": "image_repos", - "key": "name", - "value": "reponame" + "output_colume": "name", + "output_value": "reponame" } ], "formatZH": "tag 镜像 [reponame][targetName]", @@ -345,11 +352,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "cronjobs", - "key": "name", - "value": "names" + "output_colume": "name", + "output_value": "names" } ], "formatZH": "删除计划任务 [names]", @@ -364,11 +372,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "cronjobs", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "更新计划任务 [name]", @@ -384,11 +393,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "cronjobs", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "修改计划任务 [name] 状态为 [status]", @@ -403,11 +413,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "cronjobs", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "手动执行计划任务 [name]", @@ -472,11 +483,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "database_mysqls", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "删除 mysql 数据库 [name]", @@ -489,11 +501,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "database_mysqls", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "mysql 数据库 [name] 描述信息修改 [description]", @@ -595,11 +608,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "commands", - "key": "name", - "value": "names" + "output_colume": "name", + "output_value": "names" } ], "formatZH": "删除快捷命令 [names]", @@ -636,11 +650,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "backup_accounts", - "key": "type", - "value": "types" + "output_colume": "type", + "output_value": "types" } ], "formatZH": "删除备份账号 [types]", @@ -678,11 +693,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "backup_records", - "key": "file_name", - "value": "files" + "output_colume": "file_name", + "output_value": "files" } ], "formatZH": "删除备份记录 [files]", @@ -697,11 +713,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "groups", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "删除组 [name]", @@ -740,11 +757,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "hosts", - "key": "addr", - "value": "addr" + "output_colume": "addr", + "output_value": "addr" } ], "formatZH": "删除主机 [addr]", @@ -849,18 +867,19 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "name", + "input_colume": "name", + "input_value": "name", "isList": false, "db": "app_installs", - "key": "app_id", - "value": "appId" + "output_colume": "app_id", + "output_value": "appId" }, { "info": "appId", "isList": false, "db": "apps", - "key": "key", - "value": "appKey" + "output_colume": "key", + "output_value": "appKey" } ], "formatZH": "安装应用 [appKey]-[name]", @@ -876,29 +895,32 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "installId", + "input_colume": "id", + "input_value": "installId", "isList": false, "db": "app_installs", - "key": "app_id", - "value": "appId" + "output_colume": "app_id", + "output_value": "appId" }, { - "info": "installId", + "input_colume": "id", + "input_value": "installId", "isList": false, "db": "app_installs", - "key": "name", - "value": "appName" + "output_colume": "name", + "output_value": "appName" }, { - "info": "appId", + "input_colume": "id", + "input_value": "appId", "isList": false, "db": "apps", - "key": "key", - "value": "appKey" + "output_colume": "key", + "output_value": "appKey" } ], - "formatZH": "应用 [appKey]-[appName] [operate]", - "formatEN": "App [appKey]-[appName] [operate]" + "formatZH": "[appKey] 应用 [appName] [operate]", + "formatEN": "[appKey] App [appName] [operate]" }, { "api": "/api/v1/apps/installed/sync", @@ -918,11 +940,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "ids", + "input_colume": "id", + "input_value": "ids", "isList": true, "db": "app_install_backups", - "key": "name", - "value": "names" + "output_colume": "name", + "output_value": "names" } ], "formatZH": "删除应用备份 [names]", @@ -1089,11 +1112,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "websiteId", + "input_colume": "id", + "input_value": "websiteId", "isList": false, "db": "websites", - "key": "primary_domain", - "value": "domain" + "output_colume": "primary_domain", + "output_value": "domain" } ], "formatZH": "更新 nginx 配置 [domain]", @@ -1128,11 +1152,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "website_acme_accounts", - "key": "email", - "value": "email" + "output_colume": "email", + "output_value": "email" } ], "formatZH": "删除网站 acme [email]", @@ -1169,11 +1194,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "website_dns_accounts", - "key": "name", - "value": "name" + "output_colume": "name", + "output_value": "name" } ], "formatZH": "删除网站 dns [name]", @@ -1210,11 +1236,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "SSLId", + "input_colume": "id", + "input_value": "SSLId", "isList": false, "db": "website_ssls", - "key": "primary_domain", - "value": "domain" + "output_colume": "primary_domain", + "output_value": "domain" } ], "formatZH": "重置 ssl [domain]", @@ -1251,11 +1278,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "websites", - "key": "primary_domain", - "value": "domain" + "output_colume": "primary_domain", + "output_value": "domain" } ], "formatZH": "删除网站 [domain]", @@ -1295,11 +1323,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "id", + "input_colume": "id", + "input_value": "id", "isList": false, "db": "website_domains", - "key": "domain", - "value": "domain" + "output_colume": "domain", + "output_value": "domain" } ], "formatZH": "删除域名 [domain]", @@ -1325,11 +1354,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "websiteId", + "input_colume": "id", + "input_value": "websiteId", "isList": false, "db": "websites", - "key": "primary_domain", - "value": "domain" + "output_colume": "primary_domain", + "output_value": "domain" } ], "formatZH": "nginx 配置修改 [domain]", @@ -1344,11 +1374,12 @@ "paramKeys": [], "BeforeFuntions": [ { - "info": "websiteId", + "input_colume": "id", + "input_value": "websiteId", "isList": false, "db": "websites", - "key": "primary_domain", - "value": "domain" + "output_colume": "primary_domain", + "output_value": "domain" } ], "formatZH": "WAF 配置修改 [domain]", diff --git a/frontend/src/api/interface/database.ts b/frontend/src/api/interface/database.ts index 0bc30a4f2..3ad8f62f1 100644 --- a/frontend/src/api/interface/database.ts +++ b/frontend/src/api/interface/database.ts @@ -54,6 +54,11 @@ export namespace Database { permission: string; description: string; } + export interface MysqlDBDelete { + id: number; + forceDelete: boolean; + deleteBackup: boolean; + } export interface MysqlVariables { mysqlName: string; binlog_cache_size: number; diff --git a/frontend/src/api/modules/database.ts b/frontend/src/api/modules/database.ts index e89446924..54012f6ae 100644 --- a/frontend/src/api/modules/database.ts +++ b/frontend/src/api/modules/database.ts @@ -37,8 +37,8 @@ export const updateMysqlConfByFile = (params: Database.MysqlConfUpdateByFile) => export const deleteCheckMysqlDB = (id: number) => { return http.post>(`/databases/del/check`, { id: id }); }; -export const deleteMysqlDB = (id: number) => { - return http.post(`/databases/del`, { id: id }); +export const deleteMysqlDB = (params: Database.MysqlDBDelete) => { + return http.post(`/databases/del`, params); }; export const loadMysqlBaseInfo = () => { diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index b61897d5b..be0c91745 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -225,6 +225,8 @@ export default { logout: 'Logout', }, database: { + delete: 'Delete operation cannot be rolled back, please input "', + deleteHelper: '" to delete this database', create: 'Create database', noMysql: 'No {0} database is detected, please go to App Store and click Install!', goInstall: 'Go to install', @@ -591,7 +593,7 @@ export default { detail: { users: 'User', hosts: 'Host', - groups: 'Group', + apps: 'App', containers: 'Container', commands: 'Command', backups: 'Backup Account', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 7eb37483c..0c9cdb16d 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -230,6 +230,8 @@ export default { logout: '退出登录', }, database: { + delete: '删除操作无法回滚,请输入 "', + deleteHelper: '" 删除此数据库', create: '创建数据库', noMysql: '当前未检测到 {0} 数据库,请进入应用商店点击安装!', mysqlBadStatus: '当前 mysql 应用状态异常,请在', @@ -603,7 +605,7 @@ export default { detail: { users: '用户', hosts: '主机', - groups: '组', + apps: '应用', containers: '容器', commands: '快捷命令', backups: '备份账号', diff --git a/frontend/src/views/app-store/installed/delete/index.vue b/frontend/src/views/app-store/installed/delete/index.vue index af16c19f7..8f011777b 100644 --- a/frontend/src/views/app-store/installed/delete/index.vue +++ b/frontend/src/views/app-store/installed/delete/index.vue @@ -9,23 +9,18 @@ - -
{{ $t('app.forceDeleteHelper') }} -
+ - -
{{ $t('app.deleteBackupHelper') }} -
-
- + +
@@ -98,9 +93,3 @@ defineExpose({ acceptParams, }); - - diff --git a/frontend/src/views/container/compose/create/index.vue b/frontend/src/views/container/compose/create/index.vue index f5b7aa6d2..d39bfee2b 100644 --- a/frontend/src/views/container/compose/create/index.vue +++ b/frontend/src/views/container/compose/create/index.vue @@ -36,7 +36,7 @@
- - {{ $t('container.start') }} - {{ $t('container.stop') }} - - {{ $t('container.remove') }} - - + + + + {{ $t('container.start') }} + {{ $t('container.stop') }} + + {{ $t('container.remove') }} + + +
diff --git a/frontend/src/views/container/compose/edit/index.vue b/frontend/src/views/container/compose/edit/index.vue index e8a6a3379..052d03455 100644 --- a/frontend/src/views/container/compose/edit/index.vue +++ b/frontend/src/views/container/compose/edit/index.vue @@ -8,7 +8,7 @@
+ + + + + + {{ $t('app.forceDeleteHelper') }} + + + + + + {{ $t('app.deleteBackupHelper') }} + + + +
+ {{ $t('database.delete') }} + {{ dbName }} + {{ $t('database.deleteHelper') }} +
+ +
+
+ +
+ + diff --git a/frontend/src/views/database/mysql/index.vue b/frontend/src/views/database/mysql/index.vue index 30fb74a64..03dc7fa8a 100644 --- a/frontend/src/views/database/mysql/index.vue +++ b/frontend/src/views/database/mysql/index.vue @@ -19,12 +19,7 @@
- + - @@ -170,10 +164,11 @@ - + +
@@ -181,7 +176,8 @@ - -