mirror of
				https://github.com/1Panel-dev/1Panel.git
				synced 2025-10-31 03:07:34 +08:00 
			
		
		
		
	feat: 网站应用创建可以选择存量数据库,删除应用增加删除数据库选项
This commit is contained in:
		
							parent
							
								
									a1c3fa644c
								
							
						
					
					
						commit
						e1518e842f
					
				
					 12 changed files with 52 additions and 21 deletions
				
			
		|  | @ -45,6 +45,7 @@ type AppInstalledOperate struct { | |||
| 	Operate      constant.AppOperate `json:"operate" validate:"required"` | ||||
| 	ForceDelete  bool                `json:"forceDelete"` | ||||
| 	DeleteBackup bool                `json:"deleteBackup"` | ||||
| 	DeleteDB     bool                `json:"deleteDB"` | ||||
| } | ||||
| 
 | ||||
| type PortUpdate struct { | ||||
|  |  | |||
|  | @ -33,7 +33,6 @@ type IAppService interface { | |||
| 	GetApp(key string) (*response.AppDTO, error) | ||||
| 	GetAppDetail(appId uint, version string) (response.AppDetailDTO, error) | ||||
| 	Install(ctx context.Context, req request.AppInstallCreate) (*model.AppInstall, error) | ||||
| 	//SyncInstalled(installId uint) error | ||||
| 	SyncAppList() error | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -184,7 +184,7 @@ func (a AppInstallService) Operate(req request.AppInstalledOperate) error { | |||
| 		install.Status = constant.Running | ||||
| 	case constant.Delete: | ||||
| 		tx, ctx := getTxAndContext() | ||||
| 		if err := deleteAppInstall(ctx, install, req.DeleteBackup, req.ForceDelete); err != nil && !req.ForceDelete { | ||||
| 		if err := deleteAppInstall(ctx, install, req.DeleteBackup, req.ForceDelete, req.DeleteDB); err != nil && !req.ForceDelete { | ||||
| 			tx.Rollback() | ||||
| 			return err | ||||
| 		} | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import ( | |||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"github.com/1Panel-dev/1Panel/backend/app/repo" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"path" | ||||
|  | @ -88,18 +89,29 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall | |||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		var createMysql dto.MysqlDBCreate | ||||
| 		createMysql.Name = dbConfig.DbName | ||||
| 		createMysql.Username = dbConfig.DbUser | ||||
| 		createMysql.Format = "utf8mb4" | ||||
| 		createMysql.Permission = "%" | ||||
| 		createMysql.Password = dbConfig.Password | ||||
| 		mysqldb, err := NewIMysqlService().Create(ctx, createMysql) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		iMysqlRepo := repo.NewIMysqlRepo() | ||||
| 		oldMysqlDb, _ := iMysqlRepo.Get(commonRepo.WithByName(dbConfig.DbName)) | ||||
| 		resourceId := oldMysqlDb.ID | ||||
| 		if oldMysqlDb.ID > 0 { | ||||
| 			if oldMysqlDb.Username != dbConfig.DbUser || oldMysqlDb.Password != dbConfig.Password { | ||||
| 				return buserr.New(constant.ErrDbUserNotValid) | ||||
| 			} | ||||
| 		} else { | ||||
| 			var createMysql dto.MysqlDBCreate | ||||
| 			createMysql.Name = dbConfig.DbName | ||||
| 			createMysql.Username = dbConfig.DbUser | ||||
| 			createMysql.Format = "utf8mb4" | ||||
| 			createMysql.Permission = "%" | ||||
| 			createMysql.Password = dbConfig.Password | ||||
| 			mysqldb, err := NewIMysqlService().Create(ctx, createMysql) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			resourceId = mysqldb.ID | ||||
| 		} | ||||
| 
 | ||||
| 		var installResource model.AppInstallResource | ||||
| 		installResource.ResourceId = mysqldb.ID | ||||
| 		installResource.ResourceId = resourceId | ||||
| 		installResource.AppInstallId = appInstall.ID | ||||
| 		installResource.LinkId = dbInstall.ID | ||||
| 		installResource.Key = dbInstall.App.Key | ||||
|  | @ -110,7 +122,7 @@ func createLink(ctx context.Context, app model.App, appInstall *model.AppInstall | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool) error { | ||||
| func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBackup bool, forceDelete bool, deleteDB bool) error { | ||||
| 	op := files.NewFileOp() | ||||
| 	appDir := install.GetPath() | ||||
| 	dir, _ := os.Stat(appDir) | ||||
|  | @ -126,7 +138,7 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku | |||
| 	if err := appInstallRepo.Delete(ctx, install); err != nil && !forceDelete { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := deleteLink(ctx, &install); err != nil && !forceDelete { | ||||
| 	if err := deleteLink(ctx, &install, deleteDB); err != nil && !forceDelete { | ||||
| 		return err | ||||
| 	} | ||||
| 	uploadDir := fmt.Sprintf("%s/1panel/uploads/app/%s/%s", global.CONF.System.BaseDir, install.App.Key, install.Name) | ||||
|  | @ -149,14 +161,14 @@ func deleteAppInstall(ctx context.Context, install model.AppInstall, deleteBacku | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func deleteLink(ctx context.Context, install *model.AppInstall) error { | ||||
| func deleteLink(ctx context.Context, install *model.AppInstall, deleteDB bool) error { | ||||
| 	resources, _ := appInstallResourceRepo.GetBy(appInstallResourceRepo.WithAppInstallId(install.ID)) | ||||
| 	if len(resources) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	for _, re := range resources { | ||||
| 		mysqlService := NewIMysqlService() | ||||
| 		if re.Key == "mysql" { | ||||
| 		if re.Key == "mysql" && deleteDB { | ||||
| 			database, _ := mysqlRepo.Get(commonRepo.WithByID(re.ResourceId)) | ||||
| 			if reflect.DeepEqual(database, model.DatabaseMysql{}) { | ||||
| 				continue | ||||
|  |  | |||
|  | @ -253,7 +253,7 @@ func (w WebsiteService) DeleteWebsite(ctx context.Context, req request.WebsiteDe | |||
| 			return err | ||||
| 		} | ||||
| 		if !reflect.DeepEqual(model.AppInstall{}, appInstall) { | ||||
| 			if err := deleteAppInstall(ctx, appInstall, true, req.ForceDelete); err != nil && !req.ForceDelete { | ||||
| 			if err := deleteAppInstall(ctx, appInstall, true, req.ForceDelete, true); err != nil && !req.ForceDelete { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -57,6 +57,7 @@ var ( | |||
| 	ErrFileToLarge    = "ErrFileToLarge" | ||||
| 	ErrNotInstall     = "ErrNotInstall" | ||||
| 	ErrPortInOtherApp = "ErrPortInOtherApp" | ||||
| 	ErrDbUserNotValid = "ErrDbUserNotValid" | ||||
| ) | ||||
| 
 | ||||
| //website | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ ErrAppLimit: "App exceeds install limit" | |||
| ErrAppRequired: "{{ .detail }} app is required" | ||||
| ErrNotInstall: "App not installed" | ||||
| ErrPortInOtherApp: "{{ .port }} port  already in use by  {{ .apps }}" | ||||
| ErrDbUserNotValid: "Stock database, username and password do not match!" | ||||
| 
 | ||||
| #file | ||||
| ErrFileCanNotRead: "File can not read" | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ ErrAppLimit: "应用超出安装数量限制" | |||
| ErrAppRequired: "请先安装 {{ .detail }} 应用" | ||||
| ErrNotInstall: "应用未安装" | ||||
| ErrPortInOtherApp: "{{ .port }} 端口已被 {{ .apps }}占用!" | ||||
| ErrDbUserNotValid: "存量数据库,用户名密码不匹配!" | ||||
| 
 | ||||
| #file | ||||
| ErrFileCanNotRead: "此文件不支持预览" | ||||
|  |  | |||
|  | @ -863,6 +863,7 @@ export default { | |||
|         all: 'All', | ||||
|         version: 'Version', | ||||
|         detail: 'Details', | ||||
|         params: 'Param', | ||||
|         install: 'Install', | ||||
|         author: 'Author', | ||||
|         source: 'Source', | ||||
|  | @ -905,7 +906,9 @@ export default { | |||
|         forceDeleteHelper: | ||||
|             'Forced deletion will ignore errors generated during the deletion process and eventually delete metadata', | ||||
|         deleteBackup: 'Delete backup', | ||||
|         deleteBackupHelper: 'Delete application backup at the same time', | ||||
|         deleteBackupHelper: 'Also delete the application backup', | ||||
|         deleteDB: 'Delete Database', | ||||
|         deleteDBHelper: 'Also delete the database', | ||||
|         noService: 'No {0}', | ||||
|         toInstall: 'to install', | ||||
|         param: 'parameter configuration', | ||||
|  |  | |||
|  | @ -866,7 +866,8 @@ export default { | |||
|         installed: '已安装', | ||||
|         all: '全部', | ||||
|         version: '版本', | ||||
|         detail: '参数', | ||||
|         detail: '详情', | ||||
|         params: '参数', | ||||
|         install: '安装', | ||||
|         author: '作者', | ||||
|         source: '来源', | ||||
|  | @ -907,6 +908,8 @@ export default { | |||
|         forceDeleteHelper: '强制删除,会忽略删除过程中产生的错误并最终删除元数据', | ||||
|         deleteBackup: '删除备份', | ||||
|         deleteBackupHelper: '同时删除应用备份', | ||||
|         deleteDB: '删除数据库', | ||||
|         deleteDBHelper: '同时删除与应用关联的数据库', | ||||
|         noService: '无{0}', | ||||
|         toInstall: '去安装', | ||||
|         param: '参数配置', | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
|     <el-dialog | ||||
|         v-model="open" | ||||
|         :title="$t('commons.button.delete') + ' - ' + appInstallName" | ||||
|         width="30%" | ||||
|         width="40%" | ||||
|         :close-on-click-modal="false" | ||||
|         :before-close="handleClose" | ||||
|     > | ||||
|  | @ -19,6 +19,12 @@ | |||
|                     {{ $t('app.deleteBackupHelper') }} | ||||
|                 </span> | ||||
|             </el-form-item> | ||||
|             <el-form-item v-if="appType === 'website'"> | ||||
|                 <el-checkbox v-model="deleteReq.deleteDB" :label="$t('app.deleteDB')" /> | ||||
|                 <span class="input-help"> | ||||
|                     {{ $t('app.deleteDBHelper') }} | ||||
|                 </span> | ||||
|             </el-form-item> | ||||
|             <el-form-item> | ||||
|                 <span v-html="deleteHelper"></span> | ||||
|                 <el-input v-model="deleteInfo" :placeholder="appInstallName" /> | ||||
|  | @ -50,12 +56,14 @@ let deleteReq = ref({ | |||
|     installId: 0, | ||||
|     deleteBackup: false, | ||||
|     forceDelete: false, | ||||
|     deleteDB: true, | ||||
| }); | ||||
| let open = ref(false); | ||||
| let loading = ref(false); | ||||
| let deleteHelper = ref(''); | ||||
| let deleteInfo = ref(''); | ||||
| let appInstallName = ref(''); | ||||
| let appType = ref(''); | ||||
| 
 | ||||
| const deleteForm = ref<FormInstance>(); | ||||
| const em = defineEmits(['close']); | ||||
|  | @ -71,9 +79,11 @@ const acceptParams = async (app: App.AppInstalled) => { | |||
|         installId: 0, | ||||
|         deleteBackup: false, | ||||
|         forceDelete: false, | ||||
|         deleteDB: true, | ||||
|     }; | ||||
|     deleteInfo.value = ''; | ||||
|     deleteReq.value.installId = app.id; | ||||
|     appType.value = app.app.type; | ||||
|     deleteHelper.value = i18n.global.t('website.deleteConfirmHelper', [app.name]); | ||||
|     appInstallName.value = app.name; | ||||
|     open.value = true; | ||||
|  |  | |||
|  | @ -348,7 +348,7 @@ const buttons = [ | |||
|         }, | ||||
|     }, | ||||
|     { | ||||
|         label: i18n.global.t('app.detail'), | ||||
|         label: i18n.global.t('app.params'), | ||||
|         click: (row: any) => { | ||||
|             openParam(row.id); | ||||
|         }, | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue