diff --git a/backend/app/dto/app.go b/backend/app/dto/app.go index ebb0e8689..620370bbb 100644 --- a/backend/app/dto/app.go +++ b/backend/app/dto/app.go @@ -104,8 +104,9 @@ type PortUpdate struct { } type AppService struct { - Label string `json:"label"` - Value string `json:"value"` + Label string `json:"label"` + Value string `json:"value"` + Config interface{} `json:"config"` } type AppDatabase struct { diff --git a/backend/app/model/app_install.go b/backend/app/model/app_install.go index cc1a35903..4044f86ff 100644 --- a/backend/app/model/app_install.go +++ b/backend/app/model/app_install.go @@ -7,17 +7,16 @@ import ( type AppInstall struct { BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null"` - AppId uint `json:"appId" gorm:"type:integer;not null"` - AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - Param string `json:"param" gorm:"type:longtext;"` - Env string `json:"env" gorm:"type:longtext;"` - DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` - Status string `json:"status" gorm:"type:varchar(256);not null"` - Description string `json:"description" gorm:"type:varchar(256);"` - Message string `json:"message" gorm:"type:longtext;"` - //CanUpdate bool `json:"canUpdate"` + Name string `json:"name" gorm:"type:varchar(64);not null;UNIQUE"` + AppId uint `json:"appId" gorm:"type:integer;not null"` + AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` + Version string `json:"version" gorm:"type:varchar(64);not null"` + Param string `json:"param" gorm:"type:longtext;"` + Env string `json:"env" gorm:"type:longtext;"` + DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` + Status string `json:"status" gorm:"type:varchar(256);not null"` + Description string `json:"description" gorm:"type:varchar(256);"` + Message string `json:"message" gorm:"type:longtext;"` ContainerName string `json:"containerName" gorm:"type:varchar(256);not null"` ServiceName string `json:"serviceName" gorm:"type:varchar(256);not null"` HttpPort int `json:"httpPort" gorm:"type:integer;not null"` diff --git a/backend/app/service/app.go b/backend/app/service/app.go index a61286567..09d3e09c7 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -3,6 +3,7 @@ package service import ( "encoding/base64" "encoding/json" + "github.com/1Panel-dev/1Panel/backend/buserr" "os" "path" "strings" @@ -139,6 +140,11 @@ func (a AppService) GetAppDetail(appId uint, version string) (dto.AppDetailDTO, func (a AppService) Install(name string, appDetailId uint, params map[string]interface{}) (*model.AppInstall, error) { + list, _ := appInstallRepo.GetBy(commonRepo.WithByName(name)) + if len(list) > 0 { + return nil, buserr.New(constant.ErrNameIsExist, "", nil) + } + httpPort, err := checkPort("PANEL_APP_PORT_HTTP", params) if err != nil { return nil, err diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go index 3a8c2f97e..07909ad3b 100644 --- a/backend/app/service/app_install.go +++ b/backend/app/service/app_install.go @@ -2,6 +2,7 @@ package service import ( "context" + "encoding/json" "fmt" "io/ioutil" "os" @@ -210,9 +211,14 @@ func (a AppInstallService) GetServices(key string) ([]dto.AppService, error) { } var res []dto.AppService for _, install := range installs { + paramMap := make(map[string]string) + if install.Param != "" { + _ = json.Unmarshal([]byte(install.Param), ¶mMap) + } res = append(res, dto.AppService{ - Label: install.Name, - Value: install.ServiceName, + Label: install.Name, + Value: install.ServiceName, + Config: paramMap, }) } return res, nil diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 0c068f472..477d0d5ed 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -436,20 +436,21 @@ func handleMap(params map[string]interface{}, envParams map[string]string) { } func copyAppData(key, version, installName string, params map[string]interface{}) (err error) { - resourceDir := path.Join(constant.AppResourceDir, key, "versions", version) - installDir := path.Join(constant.AppInstallDir, key) - installVersionDir := path.Join(installDir, version) fileOp := files.NewFileOp() - if fileOp.Stat(installVersionDir) { - if err = fileOp.DeleteDir(installVersionDir); err != nil { + resourceDir := path.Join(constant.AppResourceDir, key, "versions", version) + installAppDir := path.Join(constant.AppInstallDir, key) + if !fileOp.Stat(installAppDir) { + if err = fileOp.CreateDir(installAppDir, 0755); err != nil { return } } - if err = fileOp.Copy(resourceDir, installVersionDir); err != nil { - return + appDir := path.Join(installAppDir, installName) + if fileOp.Stat(appDir) { + if err = fileOp.DeleteDir(appDir); err != nil { + return + } } - appDir := path.Join(installDir, installName) - if err = fileOp.Rename(installVersionDir, appDir); err != nil { + if err = fileOp.Copy(resourceDir, appDir); err != nil { return } envPath := path.Join(appDir, ".env") diff --git a/backend/constant/errs.go b/backend/constant/errs.go index b88f07027..14f361a85 100644 --- a/backend/constant/errs.go +++ b/backend/constant/errs.go @@ -40,6 +40,7 @@ var ( ErrTypeNotLogin = "ErrNotLogin" ErrTypePasswordExpired = "ErrPasswordExpired" ErrTypeNotSafety = "ErrNotSafety" + ErrNameIsExist = "ErrNameIsExist" ) // app diff --git a/backend/i18n/lang/en.yaml b/backend/i18n/lang/en.yaml index b43907edf..3588aa761 100644 --- a/backend/i18n/lang/en.yaml +++ b/backend/i18n/lang/en.yaml @@ -14,6 +14,9 @@ ErrPasswordExpired: "The current password has expired: {{ .detail }}" ErrNotSupportType: "The system does not support the current type: {{ .detail }}" +#common +ErrNameIsExist: "Name is already exist" + #app ErrPortInUsed: "{{ .detail }} port already in use" ErrAppLimit: "App exceeds install limit" diff --git a/backend/i18n/lang/zh.yaml b/backend/i18n/lang/zh.yaml index 2b46baeaf..8a95b5685 100644 --- a/backend/i18n/lang/zh.yaml +++ b/backend/i18n/lang/zh.yaml @@ -14,6 +14,9 @@ ErrPasswordExpired: "当前密码已过期: {{ .detail }}" ErrNotSupportType: "系统暂不支持当前类型: {{ .detail }}" +#common +ErrNameIsExist: "名称已存在" + #app ErrPortInUsed: "{{ .detail }} 已被占用!" ErrAppLimit: "应用超出安装数量限制" diff --git a/frontend/src/api/interface/app.ts b/frontend/src/api/interface/app.ts index e142a030b..5401ebb33 100644 --- a/frontend/src/api/interface/app.ts +++ b/frontend/src/api/interface/app.ts @@ -117,6 +117,7 @@ export namespace App { export interface AppService { label: string; value: string; + config?: Object; } export interface AppBackupReq extends ReqPage { diff --git a/frontend/src/api/modules/app.ts b/frontend/src/api/modules/app.ts index bcf864397..d4c44ec68 100644 --- a/frontend/src/api/modules/app.ts +++ b/frontend/src/api/modules/app.ts @@ -51,7 +51,7 @@ export const SyncInstalledApp = () => { }; export const GetAppService = (key: string | undefined) => { - return http.get(`apps/services/${key}`); + return http.get(`apps/services/${key}`); }; export const GetAppBackups = (info: App.AppBackupReq) => { diff --git a/frontend/src/views/app-store/detail/params/index.vue b/frontend/src/views/app-store/detail/params/index.vue index 17a0ac30a..036730331 100644 --- a/frontend/src/views/app-store/detail/params/index.vue +++ b/frontend/src/views/app-store/detail/params/index.vue @@ -15,7 +15,11 @@ show-password @change="updateParam" > - + { emit('update:rules', rules); updateParam(); } - console.log(rules); - console.log(paramObjs); } }; @@ -122,11 +124,27 @@ const getServices = async (envKey: string, key: string | undefined, pObj: ParamO pObj.services = res.data; if (res.data.length > 0) { form[envKey] = res.data[0].value; + if (res.data[0].config) { + Object.entries(res.data[0].config).forEach(([k, v]) => { + form[k] = v; + }); + } updateParam(); } }); }; +const changeService = (value: string, services: App.AppService[]) => { + services.forEach((item) => { + if (item.value === value) { + Object.entries(item.config).forEach(([k, v]) => { + form[k] = v; + }); + } + }); + updateParam(); +}; + onMounted(() => { handleParams(); });