diff --git a/agent/app/api/v2/app.go b/agent/app/api/v2/app.go index 7e86446e9f8a..c462e04447cb 100644 --- a/agent/app/api/v2/app.go +++ b/agent/app/api/v2/app.go @@ -6,6 +6,8 @@ import ( "github.com/1Panel-dev/1Panel/agent/app/dto/request" "github.com/1Panel-dev/1Panel/agent/i18n" "github.com/gin-gonic/gin" + "net/http" + "time" ) // @Tags App @@ -192,3 +194,28 @@ func (b *BaseApi) GetAppListUpdate(c *gin.Context) { } helper.SuccessWithData(c, res) } + +// @Tags App +// @Summary Get app icon by app_id +// @Accept json +// @Param appId path integer true "app id" +// @Success 200 {file} file "app icon" +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /apps/icon/:appId [get] +func (b *BaseApi) GetAppIcon(c *gin.Context) { + appID, err := helper.GetIntParamByKey(c, "appID") + if err != nil { + helper.BadRequest(c, err) + return + } + iconBytes, err := appService.GetAppIcon(appID) + if err != nil { + helper.InternalServer(c, err) + return + } + c.Header("Content-Type", "image/png") + c.Header("Cache-Control", "public, max-age=31536000, immutable") + c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) + c.Data(http.StatusOK, "image/png", iconBytes) +} diff --git a/agent/app/dto/response/app.go b/agent/app/dto/response/app.go index 7b0280b25fd7..b848d110ecb1 100644 --- a/agent/app/dto/response/app.go +++ b/agent/app/dto/response/app.go @@ -33,16 +33,10 @@ type AppItem struct { Key string `json:"key"` ID uint `json:"id"` Description string `json:"description"` - Icon string `json:"icon"` - Type string `json:"type"` Status string `json:"status"` - Resource string `json:"resource"` Installed bool `json:"installed"` - Versions []string `json:"versions"` Limit int `json:"limit"` - Tags []TagDTO `json:"tags"` - Github string `json:"github"` - Website string `json:"website"` + Tags []string `json:"tags"` GpuSupport bool `json:"gpuSupport"` Recommend int `json:"recommend"` } diff --git a/agent/app/service/app.go b/agent/app/service/app.go index 89fe7e92095e..301d7b049f43 100644 --- a/agent/app/service/app.go +++ b/agent/app/service/app.go @@ -37,7 +37,7 @@ type AppService struct { } type IAppService interface { - PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error) + PageApp(ctx *gin.Context, req request.AppSearch) (*response.AppRes, error) GetAppTags(ctx *gin.Context) ([]response.TagDTO, error) GetApp(ctx *gin.Context, key string) (*response.AppDTO, error) GetAppDetail(appId uint, version, appType string) (response.AppDetailDTO, error) @@ -46,13 +46,14 @@ type IAppService interface { GetAppUpdate() (*response.AppUpdateRes, error) GetAppDetailByID(id uint) (*response.AppDetailDTO, error) SyncAppListFromLocal(taskID string) + GetAppIcon(appID uint) ([]byte, error) } func NewIAppService() IAppService { return &AppService{} } -func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{}, error) { +func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (*response.AppRes, error) { var opts []repo.DBOption opts = append(opts, appRepo.OrderByRecommend()) if req.Name != "" { @@ -98,7 +99,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{ } opts = append(opts, repo.WithByIDs(appIds)) } - var res response.AppRes + res := &response.AppRes{} total, apps, err := appRepo.Page(req.Page, req.PageSize, opts...) if err != nil { @@ -120,12 +121,7 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{ ID: ap.ID, Name: ap.Name, Key: ap.Key, - Type: ap.Type, - Icon: ap.Icon, - Resource: ap.Resource, Limit: ap.Limit, - Website: ap.Website, - Github: ap.Github, GpuSupport: ap.GpuSupport, Recommend: ap.Recommend, Description: ap.GetDescription(ctx), @@ -135,7 +131,9 @@ func (a AppService) PageApp(ctx *gin.Context, req request.AppSearch) (interface{ if err != nil { continue } - appDTO.Tags = tags + for _, tag := range tags { + appDTO.Tags = append(appDTO.Tags, tag.Name) + } if ap.Type == constant.RuntimePHP || ap.Type == constant.RuntimeGo || ap.Type == constant.RuntimeNode || ap.Type == constant.RuntimePython || ap.Type == constant.RuntimeJava || ap.Type == constant.RuntimeDotNet { details, _ := appDetailRepo.GetBy(appDetailRepo.WithAppId(ap.ID)) var ids []uint @@ -1161,3 +1159,15 @@ func (a AppService) SyncAppListFromRemote(taskID string) (err error) { return nil } + +func (a AppService) GetAppIcon(appID uint) ([]byte, error) { + app, err := appRepo.GetFirst(repo.WithByID(appID)) + if err != nil { + return nil, err + } + iconBytes, err := base64.StdEncoding.DecodeString(app.Icon) + if err != nil { + return nil, err + } + return iconBytes, nil +} diff --git a/agent/app/service/app_utils.go b/agent/app/service/app_utils.go index cd240b16ec28..fadda6158343 100644 --- a/agent/app/service/app_utils.go +++ b/agent/app/service/app_utils.go @@ -1555,7 +1555,6 @@ func handleInstalled(appInstallList []model.AppInstall, updated bool, sync bool) Message: installed.Message, HttpPort: installed.HttpPort, HttpsPort: installed.HttpsPort, - Icon: installed.App.Icon, AppName: installed.App.Name, AppKey: installed.App.Key, AppType: installed.App.Type, diff --git a/agent/router/ro_app.go b/agent/router/ro_app.go index 7510af97f1c9..2880409087d2 100644 --- a/agent/router/ro_app.go +++ b/agent/router/ro_app.go @@ -22,6 +22,7 @@ func (a *AppRouter) InitRouter(Router *gin.RouterGroup) { appRouter.GET("/details/:id", baseApi.GetAppDetailByID) appRouter.POST("/install", baseApi.InstallApp) appRouter.GET("/tags", baseApi.GetAppTags) + appRouter.GET("/icon/:appID", baseApi.GetAppIcon) appRouter.POST("/installed/check", baseApi.CheckAppInstalled) appRouter.POST("/installed/loadport", baseApi.LoadPort) diff --git a/frontend/src/api/interface/app.ts b/frontend/src/api/interface/app.ts index 3fde387f4119..a722f7eb9ada 100644 --- a/frontend/src/api/interface/app.ts +++ b/frontend/src/api/interface/app.ts @@ -3,7 +3,7 @@ import { ReqPage, CommonModel } from '.'; export namespace App { export interface App extends CommonModel { name: string; - icon: string; + icon?: string; key: string; tags: Tag[]; shortDescZh: string; @@ -14,8 +14,8 @@ export namespace App { type: string; status: string; limit: number; - website: string; - github: string; + website?: string; + github?: string; readme: string; } @@ -44,9 +44,22 @@ export namespace App { sort: number; } + export interface AppItem { + name: string; + key: string; + id: number; + description: string; + status: string; + installed: boolean; + limit: number; + tags: string[]; + gpuSupport: boolean; + recommend: number; + } + export interface AppResPage { total: number; - items: App.AppDTO[]; + items: AppItem[]; } export interface AppUpdateRes { diff --git a/frontend/src/api/modules/app.ts b/frontend/src/api/modules/app.ts index bfaef028809f..859aebaf90ee 100644 --- a/frontend/src/api/modules/app.ts +++ b/frontend/src/api/modules/app.ts @@ -128,3 +128,9 @@ export const syncCutomAppStore = (req: App.AppStoreSync) => { export const getCurrentNodeCustomAppConfig = () => { return http.get(`/custom/app/config`); }; + +export function getAppIconUrl(appId: number, node?: string): string { + const baseURL = import.meta.env.VITE_API_URL as string; + const params = node ? `?operateNode=${node}` : ''; + return `${baseURL}/apps/icon/${appId}${params}`; +} diff --git a/frontend/src/views/app-store/apps/app/index.vue b/frontend/src/views/app-store/apps/app/index.vue index b2671c31b8b7..fb63a5469e8d 100644 --- a/frontend/src/views/app-store/apps/app/index.vue +++ b/frontend/src/views/app-store/apps/app/index.vue @@ -3,7 +3,7 @@
- +
@@ -23,7 +23,7 @@
- {{ tag.name }} + {{ tag }} @@ -48,6 +48,10 @@