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

feat: Mysql 数据库删除增加强制删除、删除备份选项

This commit is contained in:
ssongliu 2022-12-26 14:47:08 +08:00 committed by ssongliu
parent 9ce02b14c8
commit cfeb158d0a
25 changed files with 324 additions and 202 deletions

View File

@ -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
}

View File

@ -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"`

View File

@ -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))

View File

@ -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 {

View File

@ -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]",

View File

@ -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;

View File

@ -37,8 +37,8 @@ export const updateMysqlConfByFile = (params: Database.MysqlConfUpdateByFile) =>
export const deleteCheckMysqlDB = (id: number) => {
return http.post<Array<string>>(`/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 = () => {

View File

@ -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',

View File

@ -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: '备份账号',

View File

@ -9,23 +9,18 @@
<el-form ref="deleteForm" label-position="left">
<el-form-item>
<el-checkbox v-model="deleteReq.forceDelete" :label="$t('app.forceDelete')" />
</el-form-item>
<div class="helper">
<span class="input-help">
{{ $t('app.forceDeleteHelper') }}
</span>
</div>
</el-form-item>
<el-form-item>
<el-checkbox v-model="deleteReq.deleteBackup" :label="$t('app.deleteBackup')" />
</el-form-item>
<div class="helper">
<span class="input-help">
{{ $t('app.deleteBackupHelper') }}
</span>
</div>
<br />
<span v-html="deleteHelper"></span>
</el-form-item>
<el-form-item>
<span v-html="deleteHelper"></span>
<el-input v-model="deleteInfo" :placeholder="appInstallName" />
</el-form-item>
</el-form>
@ -98,9 +93,3 @@ defineExpose({
acceptParams,
});
</script>
<style lang="scss">
.helper {
margin-top: -20px;
}
</style>

View File

@ -36,7 +36,7 @@
<el-form-item v-if="form.from === 'edit'">
<codemirror
:autofocus="true"
placeholder="None data"
placeholder="#Define or paste the content of your docker-compose file here"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px; width: 100%; min-height: 200px"

View File

@ -2,13 +2,20 @@
<div v-loading="loading">
<LayoutContent :header="composeName" back-name="Compose" :reload="true">
<div v-if="createdBy === '1Panel'">
<el-button-group>
<el-button @click="onComposeOperate('start')">{{ $t('container.start') }}</el-button>
<el-button @click="onComposeOperate('stop')">{{ $t('container.stop') }}</el-button>
<el-button @click="onComposeOperate('down')">
{{ $t('container.remove') }}
</el-button>
</el-button-group>
<el-card>
<template #header>
<div class="card-header">
<span>{{ $t('container.compose') }}</span>
</div>
</template>
<el-button-group>
<el-button @click="onComposeOperate('start')">{{ $t('container.start') }}</el-button>
<el-button @click="onComposeOperate('stop')">{{ $t('container.stop') }}</el-button>
<el-button @click="onComposeOperate('down')">
{{ $t('container.remove') }}
</el-button>
</el-button-group>
</el-card>
</div>
<div v-else>
<el-alert :closable="false" show-icon :title="$t('container.composeDetailHelper')" type="info" />

View File

@ -8,7 +8,7 @@
<div v-loading="loading">
<codemirror
:autofocus="true"
placeholder="None data"
placeholder="#Define or paste the content of your docker-compose file here"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px; width: 100%; min-height: 200px"

View File

@ -24,7 +24,7 @@
<el-form-item v-if="form.from === 'edit'" :rules="Rules.requiredInput">
<codemirror
:autofocus="true"
placeholder="None data"
placeholder="#Define or paste the content of your Dockerfile here"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px; width: 100%; min-height: 200px"
@ -57,7 +57,7 @@
<codemirror
v-if="logVisiable"
:autofocus="true"
placeholder="Wait for build output..."
placeholder="Waiting for build output..."
:indent-with-tab="true"
:tabSize="4"
style="max-height: 300px"

View File

@ -35,7 +35,7 @@
<codemirror
v-if="logVisiable"
:autofocus="true"
placeholder="Wait for pull output..."
placeholder="Waiting for pull output..."
:indent-with-tab="true"
:tabSize="4"
style="max-height: 300px"

View File

@ -32,7 +32,7 @@
<codemirror
v-if="logVisiable"
:autofocus="true"
placeholder="Wait for pull output..."
placeholder="Waiting for push output..."
:indent-with-tab="true"
:tabSize="4"
style="max-height: 300px"

View File

@ -15,7 +15,7 @@
<el-form-item>
<codemirror
:autofocus="true"
placeholder="None data"
placeholder="#Define or paste the content of your docker-compose file here"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px; width: 100%; min-height: 200px"

View File

@ -0,0 +1,94 @@
<template>
<el-dialog
v-model="dialogVisiable"
:title="$t('commons.button.delete') + ' - ' + dbName"
width="30%"
:close-on-click-modal="false"
>
<el-form ref="deleteForm">
<el-form-item>
<el-checkbox v-model="deleteReq.forceDelete" :label="$t('app.forceDelete')" />
<span class="input-help">
{{ $t('app.forceDeleteHelper') }}
</span>
</el-form-item>
<el-form-item>
<el-checkbox v-model="deleteReq.deleteBackup" :label="$t('app.deleteBackup')" />
<span class="input-help">
{{ $t('app.deleteBackupHelper') }}
</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">{{ dbName }}</span>
<span style="font-size: 12px">{{ $t('database.deleteHelper') }}</span>
</div>
<el-input v-model="deleteInfo" :placeholder="dbName"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisiable = false" :loading="loading">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button type="primary" @click="submit" :loading="loading" :disabled="deleteInfo != dbName">
{{ $t('commons.button.confirm') }}
</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ElMessage, FormInstance } from 'element-plus';
import { ref } from 'vue';
import i18n from '@/lang';
import { deleteMysqlDB } from '@/api/modules/database';
let deleteReq = ref({
id: 0,
deleteBackup: false,
forceDelete: false,
});
let dialogVisiable = ref(false);
let loading = ref(false);
let deleteInfo = ref('');
let dbName = ref('');
const deleteForm = ref<FormInstance>();
interface DialogProps {
id: number;
name: string;
}
const emit = defineEmits<{ (e: 'search'): void }>();
const acceptParams = async (prop: DialogProps) => {
deleteReq.value = {
id: prop.id,
deleteBackup: false,
forceDelete: false,
};
dbName.value = prop.name;
deleteInfo.value = '';
dialogVisiable.value = true;
};
const submit = async () => {
loading.value = true;
deleteMysqlDB(deleteReq.value)
.then(() => {
loading.value = false;
emit('search');
ElMessage.success(i18n.global.t('commons.msg.deleteSuccess'));
dialogVisiable.value = false;
})
.catch(() => {
loading.value = false;
});
};
defineExpose({
acceptParams,
});
</script>

View File

@ -19,12 +19,7 @@
</el-card>
<div v-if="mysqlIsExist" :class="{ mask: mysqlStatus != 'Running' }">
<el-card v-if="!isOnSetting" style="margin-top: 20px">
<ComplexTable
:pagination-config="paginationConfig"
v-model:selects="selects"
@search="search"
:data="data"
>
<ComplexTable :pagination-config="paginationConfig" @search="search" :data="data">
<template #toolbar>
<el-button type="primary" icon="Plus" @click="onOpenDialog()">
{{ $t('commons.button.create') }}
@ -37,7 +32,6 @@
</el-button>
<el-button @click="goDashboard" type="primary" plain icon="Position">phpMyAdmin</el-button>
</template>
<el-table-column type="selection" fix />
<el-table-column :label="$t('commons.table.name')" prop="name" />
<el-table-column :label="$t('commons.login.username')" prop="username" />
<el-table-column :label="$t('commons.login.password')" prop="password">
@ -170,10 +164,11 @@
<RootPasswordDialog ref="rootPasswordRef" />
<RemoteAccessDialog ref="remoteAccessRef" />
<UploadDialog ref="uploadRef" />
<OperatrDialog @search="search" ref="dialogRef" />
<OperateDialog @search="search" ref="dialogRef" />
<BackupRecords ref="dialogBackupRef" />
<AppResources ref="checkRef"></AppResources>
<DeleteDialog ref="deleteRef" @search="search" />
<ConfirmDialog ref="confirmDialogRef" @confirm="onSubmit"></ConfirmDialog>
</div>
@ -181,7 +176,8 @@
<script lang="ts" setup>
import ComplexTable from '@/components/complex-table/index.vue';
import OperatrDialog from '@/views/database/mysql/create/index.vue';
import OperateDialog from '@/views/database/mysql/create/index.vue';
import DeleteDialog from '@/views/database/mysql/delete/index.vue';
import RootPasswordDialog from '@/views/database/mysql/password/index.vue';
import RemoteAccessDialog from '@/views/database/mysql/remote/index.vue';
import BackupRecords from '@/views/database/mysql/backup/index.vue';
@ -195,7 +191,6 @@ import { dateFromat } from '@/utils/util';
import { reactive, ref } from 'vue';
import {
deleteCheckMysqlDB,
deleteMysqlDB,
loadRemoteAccess,
searchMysqlDBs,
updateMysqlAccess,
@ -203,7 +198,6 @@ import {
updateMysqlPassword,
} from '@/api/modules/database';
import i18n from '@/lang';
import { useDeleteData } from '@/hooks/use-delete-data';
import { ElForm, ElMessage } from 'element-plus';
import { Database } from '@/api/interface/database';
import { Rules } from '@/global/form-rules';
@ -213,11 +207,11 @@ import router from '@/routers';
const loading = ref(false);
const selects = ref<any>([]);
const mysqlName = ref();
const isOnSetting = ref<boolean>();
const checkRef = ref();
const deleteRef = ref();
const phpadminPort = ref();
const phpVisiable = ref(false);
@ -403,8 +397,7 @@ const onDelete = async (row: Database.MysqlDBInfo) => {
if (res.data && res.data.length > 0) {
checkRef.value.acceptParams({ items: res.data });
} else {
await useDeleteData(deleteMysqlDB, row.id, 'app.deleteWarn');
search();
deleteRef.value.acceptParams({ id: row.id, name: row.name });
}
};
@ -446,6 +439,7 @@ const buttons = [
if (row.permission === '%' || row.permission === 'localhost') {
changeForm.privilege = row.permission;
} else {
changeForm.privilegeIPs = row.permission;
changeForm.privilege = 'ip';
}
changeVisiable.value = true;

View File

@ -75,7 +75,7 @@ import { File } from '@/api/interface/file';
import { BatchDeleteFile, GetFilesList, UploadFileData } from '@/api/modules/files';
const selects = ref<any>([]);
const baseDir = '/opt/1Panel/data/uploads/database/';
const baseDir = ref();
const data = ref();
const paginationConfig = reactive({
@ -94,6 +94,7 @@ interface DialogProps {
const acceptParams = (params: DialogProps): void => {
mysqlName.value = params.mysqlName;
dbName.value = params.dbName;
baseDir.value = '/opt/1Panel/data/uploads/database/mysql/' + mysqlName.value + '/' + dbName.value + '/';
upVisiable.value = true;
search();
};
@ -102,7 +103,7 @@ const search = async () => {
let params = {
page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize,
path: baseDir,
path: baseDir.value,
expand: true,
};
const res = await GetFilesList(params);
@ -114,7 +115,7 @@ const onRecover = async (row: File.File) => {
let params = {
mysqlName: mysqlName.value,
dbName: dbName.value,
fileDir: baseDir,
fileDir: baseDir.value,
fileName: row.name,
};
await recoverByUpload(params);
@ -156,7 +157,7 @@ const onSubmit = () => {
if (uploaderFiles.value[0]!.raw != undefined) {
formData.append('file', uploaderFiles.value[0]!.raw);
}
formData.append('path', baseDir);
formData.append('path', baseDir.value);
UploadFileData(formData, {}).then(() => {
ElMessage.success(i18n.global.t('file.uploadSuccess'));
handleClose();
@ -167,10 +168,10 @@ const onSubmit = () => {
const onBatchDelete = async (row: File.File | null) => {
let files: Array<string> = [];
if (row) {
files.push(baseDir + row.name);
files.push(baseDir.value + row.name);
} else {
selects.value.forEach((item: File.File) => {
files.push(baseDir + item.name);
files.push(baseDir.value + item.name);
});
}
await useDeleteData(BatchDeleteFile, { paths: files, isDir: false }, 'commons.msg.delete');

View File

@ -21,7 +21,7 @@
<el-button style="margin-top: 10px" @click="getDefaultConfig()">
{{ $t('app.defaultConfig') }}
</el-button>
<el-button type="primary" @click="onSaveFile" style="margin-top: 5px">
<el-button type="primary" @click="onSaveFile" style="margin-top: 10px">
{{ $t('commons.button.save') }}
</el-button>
<el-row>
@ -98,6 +98,7 @@
</LayoutContent>
</el-card>
<ConfirmDialog ref="confirmDialogRef" @confirm="submtiFile"></ConfirmDialog>
<ConfirmDialog ref="confirmFileRef" @confirm="submtiFile"></ConfirmDialog>
<ConfirmDialog ref="confirmFormRef" @confirm="submtiForm"></ConfirmDialog>
<ConfirmDialog ref="confirmPortRef" @confirm="onChangePort(formRef)"></ConfirmDialog>

View File

@ -15,11 +15,11 @@
<el-table-column min-width="40" :label="$t('logs.loginStatus')" prop="status">
<template #default="{ row }">
<div v-if="row.status === 'Success'">
<el-tag type="success">{{ row.status }}</el-tag>
<el-tag type="success">{{ $t('commons.status.success') }}</el-tag>
</div>
<div v-else>
<el-tooltip class="box-item" effect="dark" :content="row.message" placement="top-start">
<el-tag type="danger">{{ row.status }}</el-tag>
<el-tag type="danger">{{ $t('commons.status.failed') }}</el-tag>
</el-tooltip>
</div>
</template>

View File

@ -19,6 +19,7 @@
<el-form-item prop="password">
<el-input
type="password"
clearable
v-model="registerForm.password"
show-password
:placeholder="$t('commons.login.password')"
@ -33,6 +34,7 @@
<el-form-item prop="rePassword">
<el-input
type="password"
clearable
v-model="registerForm.rePassword"
show-password
:placeholder="$t('commons.login.rePassword')"
@ -113,6 +115,7 @@
<el-form-item prop="password">
<el-input
type="password"
clearable
v-model="loginForm.password"
show-password
:placeholder="$t('commons.login.password')"

View File

@ -42,7 +42,7 @@
prop="credential"
:rules="Rules.requiredInput"
>
<el-input show-password v-model="dialogData.rowData!.credential" />
<el-input show-password clearable v-model="dialogData.rowData!.credential" />
</el-form-item>
<el-form-item
v-if="dialogData.rowData!.type === 'S3'"
@ -99,7 +99,7 @@
<el-input v-model="dialogData.rowData!.accessKey" />
</el-form-item>
<el-form-item :label="$t('setting.password')" prop="credential" :rules="[Rules.requiredInput]">
<el-input type="password" show-password v-model="dialogData.rowData!.credential" />
<el-input type="password" clearable show-password v-model="dialogData.rowData!.credential" />
</el-form-item>
<el-form-item :label="$t('setting.path')" prop="bucket">
<el-input v-model="dialogData.rowData!.bucket" />

View File

@ -10,31 +10,24 @@
<el-form ref="deleteForm" label-position="left">
<el-form-item>
<el-checkbox v-model="deleteReq.forceDelete" :label="$t('website.forceDelete')" />
</el-form-item>
<div class="helper">
<span class="input-help">
{{ $t('website.forceDeleteHelper') }}
</span>
</div>
</el-form-item>
<el-form-item v-if="type === 'deployment'">
<el-checkbox v-model="deleteReq.deleteApp" :label="$t('website.deleteApp')" />
</el-form-item>
<div class="helper" v-if="type === 'deployment'">
<span class="input-help">
{{ $t('website.deleteAppHelper') }}
</span>
</div>
</el-form-item>
<el-form-item>
<el-checkbox v-model="deleteReq.deleteBackup" :label="$t('website.deleteBackup')" />
</el-form-item>
<div class="helper">
<span class="input-help">
{{ $t('website.deleteBackupHelper') }}
</span>
</div>
<br />
<span v-html="deleteHelper"></span>
</el-form-item>
<el-form-item>
<span v-html="deleteHelper"></span>
<el-input v-model="deleteInfo" :placeholder="websiteName" />
</el-form-item>
</el-form>
@ -114,9 +107,3 @@ defineExpose({
acceptParams,
});
</script>
<style lang="scss">
.helper {
margin-top: -20px;
}
</style>