package appconfig import ( "fmt" "strconv" "strings" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/repository" "hyapp-admin-server/internal/response" "github.com/gin-gonic/gin" ) type Handler struct { service *AppConfigService audit shared.OperationLogger } func New(store *repository.Store, audit shared.OperationLogger) *Handler { return &Handler{service: NewService(store), audit: audit} } func (h *Handler) ListH5Links(c *gin.Context) { items, err := h.service.ListH5Links() if err != nil { response.ServerError(c, "获取 H5 配置失败") return } response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) UpdateH5Links(c *gin.Context) { var request updateH5LinksRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } items, err := h.service.UpdateH5Links(request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-app-h5-links", "admin_app_configs", "success", fmt.Sprintf("%d h5 links", len(request.Items))) response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) CreateH5Link(c *gin.Context) { var request h5LinkPayload if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.CreateH5Link(request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "create-app-h5-link", "admin_app_configs", "success", fmt.Sprintf("h5_key=%s", item.Key)) response.Created(c, item) } func (h *Handler) UpdateH5Link(c *gin.Context) { key := strings.TrimSpace(c.Param("key")) if key == "" { response.BadRequest(c, "h5 config key is invalid") return } var request h5LinkPayload if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.UpdateH5Link(key, request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-app-h5-link", "admin_app_configs", "success", fmt.Sprintf("h5_key=%s", item.Key)) response.OK(c, item) } func (h *Handler) DeleteH5Link(c *gin.Context) { key := strings.TrimSpace(c.Param("key")) if key == "" { response.BadRequest(c, "h5 config key is invalid") return } if err := h.service.DeleteH5Link(key); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "delete-app-h5-link", "admin_app_configs", "success", fmt.Sprintf("h5_key=%s", key)) response.OK(c, gin.H{"deleted": true}) } func (h *Handler) ListBanners(c *gin.Context) { options := shared.ListOptions(c) items, err := h.service.ListBanners(appctx.FromContext(c.Request.Context()), repository.AppBannerListOptions{ Keyword: options.Keyword, Status: options.Status, DisplayScope: firstQuery(c, "displayScope", "display_scope"), Platform: strings.TrimSpace(c.Query("platform")), RegionID: parseOptionalInt64(c.Query("regionId"), c.Query("region_id")), Country: firstQuery(c, "countryCode", "country_code", "country"), }) if err != nil { response.ServerError(c, "获取 BANNER 配置失败") return } response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) CreateBanner(c *gin.Context) { var request bannerRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.CreateBanner(appctx.FromContext(c.Request.Context()), request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "create-app-banner", "admin_app_banners", "success", fmt.Sprintf("banner_id=%d", item.ID)) response.Created(c, item) } func (h *Handler) UpdateBanner(c *gin.Context) { id, ok := bannerID(c) if !ok { return } var request bannerRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.UpdateBanner(appctx.FromContext(c.Request.Context()), id, request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-app-banner", "admin_app_banners", "success", fmt.Sprintf("banner_id=%d", item.ID)) response.OK(c, item) } func (h *Handler) DeleteBanner(c *gin.Context) { id, ok := bannerID(c) if !ok { return } if err := h.service.DeleteBanner(appctx.FromContext(c.Request.Context()), id); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "delete-app-banner", "admin_app_banners", "success", fmt.Sprintf("banner_id=%d", id)) response.OK(c, gin.H{"deleted": true}) } func (h *Handler) ListSplashScreens(c *gin.Context) { options := shared.ListOptions(c) items, err := h.service.ListSplashScreens(appctx.FromContext(c.Request.Context()), repository.AppSplashScreenListOptions{ Keyword: options.Keyword, Status: options.Status, Platform: strings.TrimSpace(c.Query("platform")), RegionID: parseOptionalInt64(c.Query("regionId"), c.Query("region_id")), Country: firstQuery(c, "countryCode", "country_code", "country"), }) if err != nil { response.ServerError(c, "获取开屏配置失败") return } response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) CreateSplashScreen(c *gin.Context) { var request splashScreenRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.CreateSplashScreen(appctx.FromContext(c.Request.Context()), request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "create-app-splash-screen", "admin_app_splash_screens", "success", fmt.Sprintf("splash_id=%d", item.ID)) response.Created(c, item) } func (h *Handler) UpdateSplashScreen(c *gin.Context) { id, ok := splashScreenID(c) if !ok { return } var request splashScreenRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.UpdateSplashScreen(appctx.FromContext(c.Request.Context()), id, request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-app-splash-screen", "admin_app_splash_screens", "success", fmt.Sprintf("splash_id=%d", item.ID)) response.OK(c, item) } func (h *Handler) DeleteSplashScreen(c *gin.Context) { id, ok := splashScreenID(c) if !ok { return } if err := h.service.DeleteSplashScreen(appctx.FromContext(c.Request.Context()), id); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "delete-app-splash-screen", "admin_app_splash_screens", "success", fmt.Sprintf("splash_id=%d", id)) response.OK(c, gin.H{"deleted": true}) } func (h *Handler) ListAppVersions(c *gin.Context) { items, err := h.service.ListAppVersions(appctx.FromContext(c.Request.Context()), repository.AppVersionListOptions{ Keyword: strings.TrimSpace(c.Query("keyword")), Platform: strings.TrimSpace(c.Query("platform")), }) if err != nil { response.ServerError(c, "获取版本配置失败") return } response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) CreateAppVersion(c *gin.Context) { var request appVersionRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.CreateAppVersion(appctx.FromContext(c.Request.Context()), request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "create-app-version", "admin_app_versions", "success", fmt.Sprintf("version_id=%d", item.ID)) response.Created(c, item) } func (h *Handler) UpdateAppVersion(c *gin.Context) { id, ok := appVersionID(c) if !ok { return } var request appVersionRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.UpdateAppVersion(appctx.FromContext(c.Request.Context()), id, request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-app-version", "admin_app_versions", "success", fmt.Sprintf("version_id=%d", item.ID)) response.OK(c, item) } func (h *Handler) DeleteAppVersion(c *gin.Context) { id, ok := appVersionID(c) if !ok { return } if err := h.service.DeleteAppVersion(appctx.FromContext(c.Request.Context()), id); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "delete-app-version", "admin_app_versions", "success", fmt.Sprintf("version_id=%d", id)) response.OK(c, gin.H{"deleted": true}) } func (h *Handler) ListExploreTabs(c *gin.Context) { var enabled *bool switch strings.ToLower(strings.TrimSpace(c.Query("enabled"))) { case "true", "1", "enabled": value := true enabled = &value case "false", "0", "disabled": value := false enabled = &value } items, err := h.service.ListExploreTabs(appctx.FromContext(c.Request.Context()), repository.AppExploreTabListOptions{ Keyword: strings.TrimSpace(c.Query("keyword")), Enabled: enabled, }) if err != nil { response.ServerError(c, "获取 Explore 配置失败") return } response.OK(c, gin.H{"items": items, "total": len(items)}) } func (h *Handler) CreateExploreTab(c *gin.Context) { var request exploreTabRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.CreateExploreTab(appctx.FromContext(c.Request.Context()), request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "create-app-explore-tab", "admin_app_explore_tabs", "success", fmt.Sprintf("explore_tab_id=%d", item.ID)) response.Created(c, item) } func (h *Handler) UpdateExploreTab(c *gin.Context) { id, ok := exploreTabID(c) if !ok { return } var request exploreTabRequest if err := c.ShouldBindJSON(&request); err != nil { response.BadRequest(c, "参数不正确") return } item, err := h.service.UpdateExploreTab(appctx.FromContext(c.Request.Context()), id, request) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-app-explore-tab", "admin_app_explore_tabs", "success", fmt.Sprintf("explore_tab_id=%d", item.ID)) response.OK(c, item) } func (h *Handler) DeleteExploreTab(c *gin.Context) { id, ok := exploreTabID(c) if !ok { return } if err := h.service.DeleteExploreTab(appctx.FromContext(c.Request.Context()), id); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "delete-app-explore-tab", "admin_app_explore_tabs", "success", fmt.Sprintf("explore_tab_id=%d", id)) response.OK(c, gin.H{"deleted": true}) } func bannerID(c *gin.Context) (uint, bool) { value, err := strconv.ParseUint(c.Param("banner_id"), 10, 64) if err != nil || value == 0 { response.BadRequest(c, "banner id is invalid") return 0, false } return uint(value), true } func splashScreenID(c *gin.Context) (uint, bool) { value, err := strconv.ParseUint(c.Param("splash_id"), 10, 64) if err != nil || value == 0 { response.BadRequest(c, "splash screen id is invalid") return 0, false } return uint(value), true } func appVersionID(c *gin.Context) (uint, bool) { value, err := strconv.ParseUint(c.Param("version_id"), 10, 64) if err != nil || value == 0 { response.BadRequest(c, "version id is invalid") return 0, false } return uint(value), true } func exploreTabID(c *gin.Context) (uint, bool) { value, err := strconv.ParseUint(c.Param("tab_id"), 10, 64) if err != nil || value == 0 { response.BadRequest(c, "explore tab id is invalid") return 0, false } return uint(value), true } func parseOptionalInt64(values ...string) int64 { for _, value := range values { value = strings.TrimSpace(value) if value == "" { continue } parsed, err := strconv.ParseInt(value, 10, 64) if err == nil && parsed > 0 { return parsed } } return 0 } func firstQuery(c *gin.Context, keys ...string) string { for _, key := range keys { if value := c.Query(key); value != "" { return value } } return "" }