package handlers import ( "strconv" "time" "tyapi-server/internal/application/api" "tyapi-server/internal/application/finance" "tyapi-server/internal/application/product" "tyapi-server/internal/application/product/dto/commands" "tyapi-server/internal/application/product/dto/queries" "tyapi-server/internal/application/product/dto/responses" "tyapi-server/internal/shared/interfaces" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // ProductAdminHandler 产品管理员HTTP处理器 type ProductAdminHandler struct { productAppService product.ProductApplicationService categoryAppService product.CategoryApplicationService subscriptionAppService product.SubscriptionApplicationService documentationAppService product.DocumentationApplicationServiceInterface apiAppService api.ApiApplicationService financeAppService finance.FinanceApplicationService responseBuilder interfaces.ResponseBuilder validator interfaces.RequestValidator logger *zap.Logger } // NewProductAdminHandler 创建产品管理员HTTP处理器 func NewProductAdminHandler( productAppService product.ProductApplicationService, categoryAppService product.CategoryApplicationService, subscriptionAppService product.SubscriptionApplicationService, documentationAppService product.DocumentationApplicationServiceInterface, apiAppService api.ApiApplicationService, financeAppService finance.FinanceApplicationService, responseBuilder interfaces.ResponseBuilder, validator interfaces.RequestValidator, logger *zap.Logger, ) *ProductAdminHandler { return &ProductAdminHandler{ productAppService: productAppService, categoryAppService: categoryAppService, subscriptionAppService: subscriptionAppService, documentationAppService: documentationAppService, apiAppService: apiAppService, financeAppService: financeAppService, responseBuilder: responseBuilder, validator: validator, logger: logger, } } // CreateProduct 创建产品 // @Summary 创建产品 // @Description 管理员创建新产品 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param request body commands.CreateProductCommand true "创建产品请求" // @Success 201 {object} map[string]interface{} "产品创建成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products [post] func (h *ProductAdminHandler) CreateProduct(c *gin.Context) { var cmd commands.CreateProductCommand if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } if err := h.productAppService.CreateProduct(c.Request.Context(), &cmd); err != nil { h.logger.Error("创建产品失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Created(c, nil, "产品创建成功") } // UpdateProduct 更新产品 // @Summary 更新产品 // @Description 管理员更新产品信息 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Param request body commands.UpdateProductCommand true "更新产品请求" // @Success 200 {object} map[string]interface{} "产品更新成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id} [put] func (h *ProductAdminHandler) UpdateProduct(c *gin.Context) { var cmd commands.UpdateProductCommand cmd.ID = c.Param("id") if cmd.ID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } if err := h.productAppService.UpdateProduct(c.Request.Context(), &cmd); err != nil { h.logger.Error("更新产品失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "产品更新成功") } // DeleteProduct 删除产品 // @Summary 删除产品 // @Description 管理员删除产品 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Success 200 {object} map[string]interface{} "产品删除成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id} [delete] func (h *ProductAdminHandler) DeleteProduct(c *gin.Context) { var cmd commands.DeleteProductCommand if err := h.validator.ValidateParam(c, &cmd); err != nil { return } if err := h.productAppService.DeleteProduct(c.Request.Context(), &cmd); err != nil { h.logger.Error("删除产品失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "产品删除成功") } // CreateCategory 创建分类 // @Summary 创建分类 // @Description 管理员创建新产品分类 // @Tags 分类管理 // @Accept json // @Produce json // @Security Bearer // @Param request body commands.CreateCategoryCommand true "创建分类请求" // @Success 201 {object} map[string]interface{} "分类创建成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/product-categories [post] func (h *ProductAdminHandler) CreateCategory(c *gin.Context) { var cmd commands.CreateCategoryCommand if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } if err := h.categoryAppService.CreateCategory(c.Request.Context(), &cmd); err != nil { h.logger.Error("创建分类失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Created(c, nil, "分类创建成功") } // UpdateCategory 更新分类 // @Summary 更新分类 // @Description 管理员更新产品分类信息 // @Tags 分类管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "分类ID" // @Param request body commands.UpdateCategoryCommand true "更新分类请求" // @Success 200 {object} map[string]interface{} "分类更新成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "分类不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/product-categories/{id} [put] func (h *ProductAdminHandler) UpdateCategory(c *gin.Context) { var cmd commands.UpdateCategoryCommand if err := h.validator.ValidateParam(c, &cmd); err != nil { return } if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } if err := h.categoryAppService.UpdateCategory(c.Request.Context(), &cmd); err != nil { h.logger.Error("更新分类失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "分类更新成功") } // DeleteCategory 删除分类 // @Summary 删除分类 // @Description 管理员删除产品分类 // @Tags 分类管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "分类ID" // @Success 200 {object} map[string]interface{} "分类删除成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "分类不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/product-categories/{id} [delete] func (h *ProductAdminHandler) DeleteCategory(c *gin.Context) { var cmd commands.DeleteCategoryCommand if err := h.validator.ValidateParam(c, &cmd); err != nil { return } if err := h.categoryAppService.DeleteCategory(c.Request.Context(), &cmd); err != nil { h.logger.Error("删除分类失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "分类删除成功") } // UpdateSubscriptionPrice 更新订阅价格 // @Summary 更新订阅价格 // @Description 管理员修改用户订阅价格 // @Tags 订阅管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "订阅ID" // @Param request body commands.UpdateSubscriptionPriceCommand true "更新订阅价格请求" // @Success 200 {object} map[string]interface{} "订阅价格更新成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "订阅不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/subscriptions/{id}/price [put] func (h *ProductAdminHandler) UpdateSubscriptionPrice(c *gin.Context) { var cmd commands.UpdateSubscriptionPriceCommand if err := h.validator.ValidateParam(c, &cmd); err != nil { return } if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } if err := h.subscriptionAppService.UpdateSubscriptionPrice(c.Request.Context(), &cmd); err != nil { h.logger.Error("更新订阅价格失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "订阅价格更新成功") } // ListProducts 获取产品列表(管理员) // @Summary 获取产品列表 // @Description 管理员获取产品列表,支持筛选和分页,包含所有产品(包括隐藏的) // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(10) // @Param keyword query string false "搜索关键词" // @Param category_id query string false "分类ID" // @Param is_enabled query bool false "是否启用" // @Param is_visible query bool false "是否可见" // @Param is_package query bool false "是否组合包" // @Param sort_by query string false "排序字段" // @Param sort_order query string false "排序方向" Enums(asc, desc) // @Success 200 {object} responses.ProductAdminListResponse "获取产品列表成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products [get] func (h *ProductAdminHandler) ListProducts(c *gin.Context) { // 解析查询参数 page := h.getIntQuery(c, "page", 1) pageSize := h.getIntQuery(c, "page_size", 10) // 构建筛选条件 filters := make(map[string]interface{}) // 搜索关键词筛选 if keyword := c.Query("keyword"); keyword != "" { filters["keyword"] = keyword } // 分类ID筛选 if categoryID := c.Query("category_id"); categoryID != "" { filters["category_id"] = categoryID } // 启用状态筛选 if isEnabled := c.Query("is_enabled"); isEnabled != "" { if enabled, err := strconv.ParseBool(isEnabled); err == nil { filters["is_enabled"] = enabled } } // 可见状态筛选 if isVisible := c.Query("is_visible"); isVisible != "" { if visible, err := strconv.ParseBool(isVisible); err == nil { filters["is_visible"] = visible } } // 产品类型筛选 if isPackage := c.Query("is_package"); isPackage != "" { if pkg, err := strconv.ParseBool(isPackage); err == nil { filters["is_package"] = pkg } } // 排序字段 sortBy := c.Query("sort_by") if sortBy == "" { sortBy = "created_at" } // 排序方向 sortOrder := c.Query("sort_order") if sortOrder == "" { sortOrder = "desc" } // 构建分页选项 options := interfaces.ListOptions{ Page: page, PageSize: pageSize, Sort: sortBy, Order: sortOrder, } // 使用管理员专用的产品列表方法 result, err := h.productAppService.ListProductsForAdmin(c.Request.Context(), filters, options) if err != nil { h.logger.Error("获取产品列表失败", zap.Error(err)) h.responseBuilder.InternalError(c, "获取产品列表失败") return } h.responseBuilder.Success(c, result, "获取产品列表成功") } // getIntQuery 获取整数查询参数 func (h *ProductAdminHandler) getIntQuery(c *gin.Context, key string, defaultValue int) int { if value := c.Query(key); value != "" { if intValue, err := strconv.Atoi(value); err == nil && intValue > 0 { return intValue } } return defaultValue } // GetProductDetail 获取产品详情 // @Summary 获取产品详情 // @Description 管理员获取产品详细信息 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Param with_document query bool false "是否包含文档信息" // @Success 200 {object} responses.ProductAdminInfoResponse "获取产品详情成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id} [get] func (h *ProductAdminHandler) GetProductDetail(c *gin.Context) { var query queries.GetProductDetailQuery query.ID = c.Param("id") if query.ID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } // 解析可选参数 if withDocument := c.Query("with_document"); withDocument != "" { if withDoc, err := strconv.ParseBool(withDocument); err == nil { query.WithDocument = &withDoc } } result, err := h.productAppService.GetProductByIDForAdmin(c.Request.Context(), &query) if err != nil { h.logger.Error("获取产品详情失败", zap.Error(err)) h.responseBuilder.NotFound(c, "产品不存在") return } h.responseBuilder.Success(c, result, "获取产品详情成功") } // GetAvailableProducts 获取可选子产品列表 // @Summary 获取可选子产品列表 // @Description 管理员获取可选作组合包子产品的产品列表 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param exclude_package_id query string false "排除的组合包ID" // @Param keyword query string false "搜索关键词" // @Param category_id query string false "分类ID" // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(20) // @Success 200 {object} responses.ProductListResponse "获取可选产品列表成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/available [get] func (h *ProductAdminHandler) GetAvailableProducts(c *gin.Context) { var query queries.GetAvailableProductsQuery if err := h.validator.ValidateQuery(c, &query); err != nil { return } // 设置默认值 if query.Page <= 0 { query.Page = 1 } if query.PageSize <= 0 { query.PageSize = 20 } if query.PageSize > 100 { query.PageSize = 100 } result, err := h.productAppService.GetAvailableProducts(c.Request.Context(), &query) if err != nil { h.logger.Error("获取可选产品列表失败", zap.Error(err)) h.responseBuilder.InternalError(c, "获取可选产品列表失败") return } h.responseBuilder.Success(c, result, "获取可选产品列表成功") } // AddPackageItem 添加组合包子产品 // @Summary 添加组合包子产品 // @Description 管理员向组合包添加子产品 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "组合包ID" // @Param command body commands.AddPackageItemCommand true "添加子产品命令" // @Success 200 {object} map[string]interface{} "添加成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/package-items [post] func (h *ProductAdminHandler) AddPackageItem(c *gin.Context) { packageID := c.Param("id") if packageID == "" { h.responseBuilder.BadRequest(c, "组合包ID不能为空") return } var cmd commands.AddPackageItemCommand if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } err := h.productAppService.AddPackageItem(c.Request.Context(), packageID, &cmd) if err != nil { h.logger.Error("添加组合包子产品失败", zap.Error(err), zap.String("package_id", packageID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "添加组合包子产品成功") } // UpdatePackageItem 更新组合包子产品 // @Summary 更新组合包子产品 // @Description 管理员更新组合包子产品信息 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "组合包ID" // @Param item_id path string true "子产品项目ID" // @Param command body commands.UpdatePackageItemCommand true "更新子产品命令" // @Success 200 {object} map[string]interface{} "更新成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/package-items/{item_id} [put] func (h *ProductAdminHandler) UpdatePackageItem(c *gin.Context) { packageID := c.Param("id") itemID := c.Param("item_id") if packageID == "" || itemID == "" { h.responseBuilder.BadRequest(c, "参数不能为空") return } var cmd commands.UpdatePackageItemCommand if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } err := h.productAppService.UpdatePackageItem(c.Request.Context(), packageID, itemID, &cmd) if err != nil { h.logger.Error("更新组合包子产品失败", zap.Error(err), zap.String("package_id", packageID), zap.String("item_id", itemID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "更新组合包子产品成功") } // RemovePackageItem 移除组合包子产品 // @Summary 移除组合包子产品 // @Description 管理员从组合包移除子产品 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "组合包ID" // @Param item_id path string true "子产品项目ID" // @Success 200 {object} map[string]interface{} "移除成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/package-items/{item_id} [delete] func (h *ProductAdminHandler) RemovePackageItem(c *gin.Context) { packageID := c.Param("id") itemID := c.Param("item_id") if packageID == "" || itemID == "" { h.responseBuilder.BadRequest(c, "参数不能为空") return } err := h.productAppService.RemovePackageItem(c.Request.Context(), packageID, itemID) if err != nil { h.logger.Error("移除组合包子产品失败", zap.Error(err), zap.String("package_id", packageID), zap.String("item_id", itemID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "移除组合包子产品成功") } // ReorderPackageItems 重新排序组合包子产品 // @Summary 重新排序组合包子产品 // @Description 管理员重新排序组合包子产品 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "组合包ID" // @Param command body commands.ReorderPackageItemsCommand true "重新排序命令" // @Success 200 {object} map[string]interface{} "排序成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/package-items/reorder [put] func (h *ProductAdminHandler) ReorderPackageItems(c *gin.Context) { packageID := c.Param("id") if packageID == "" { h.responseBuilder.BadRequest(c, "组合包ID不能为空") return } var cmd commands.ReorderPackageItemsCommand if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } err := h.productAppService.ReorderPackageItems(c.Request.Context(), packageID, &cmd) if err != nil { h.logger.Error("重新排序组合包子产品失败", zap.Error(err), zap.String("package_id", packageID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "重新排序组合包子产品成功") } // UpdatePackageItems 批量更新组合包子产品 // @Summary 批量更新组合包子产品 // @Description 管理员批量更新组合包子产品配置 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "组合包ID" // @Param command body commands.UpdatePackageItemsCommand true "批量更新命令" // @Success 200 {object} map[string]interface{} "更新成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/package-items/batch [put] func (h *ProductAdminHandler) UpdatePackageItems(c *gin.Context) { packageID := c.Param("id") if packageID == "" { h.responseBuilder.BadRequest(c, "组合包ID不能为空") return } var cmd commands.UpdatePackageItemsCommand if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } err := h.productAppService.UpdatePackageItems(c.Request.Context(), packageID, &cmd) if err != nil { h.logger.Error("批量更新组合包子产品失败", zap.Error(err), zap.String("package_id", packageID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "批量更新组合包子产品成功") } // ListCategories 获取分类列表(管理员) // @Summary 获取分类列表 // @Description 管理员获取产品分类列表 // @Tags 分类管理 // @Accept json // @Produce json // @Security Bearer // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(10) // @Success 200 {object} responses.CategoryListResponse "获取分类列表成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/product-categories [get] func (h *ProductAdminHandler) ListCategories(c *gin.Context) { var query queries.ListCategoriesQuery if err := h.validator.ValidateQuery(c, &query); err != nil { return } // 设置默认值 if query.Page <= 0 { query.Page = 1 } if query.PageSize <= 0 { query.PageSize = 10 } if query.PageSize > 100 { query.PageSize = 100 } result, err := h.categoryAppService.ListCategories(c.Request.Context(), &query) if err != nil { h.logger.Error("获取分类列表失败", zap.Error(err)) h.responseBuilder.InternalError(c, "获取分类列表失败") return } h.responseBuilder.Success(c, result, "获取分类列表成功") } // GetCategoryDetail 获取分类详情(管理员) // @Summary 获取分类详情 // @Description 管理员获取分类详细信息 // @Tags 分类管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "分类ID" // @Success 200 {object} responses.CategoryInfoResponse "获取分类详情成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "分类不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/product-categories/{id} [get] func (h *ProductAdminHandler) GetCategoryDetail(c *gin.Context) { var query queries.GetCategoryQuery query.ID = c.Param("id") if query.ID == "" { h.responseBuilder.BadRequest(c, "分类ID不能为空") return } result, err := h.categoryAppService.GetCategoryByID(c.Request.Context(), &query) if err != nil { h.logger.Error("获取分类详情失败", zap.Error(err), zap.String("category_id", query.ID)) h.responseBuilder.NotFound(c, "分类不存在") return } h.responseBuilder.Success(c, result, "获取分类详情成功") } // ListSubscriptions 获取订阅列表(管理员) // @Summary 获取订阅列表 // @Description 管理员获取订阅列表 // @Tags 订阅管理 // @Accept json // @Produce json // @Security Bearer // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(10) // @Param keyword query string false "搜索关键词" // @Param company_name query string false "企业名称" // @Param product_name query string false "产品名称" // @Param start_time query string false "订阅开始时间" format(date-time) // @Param end_time query string false "订阅结束时间" format(date-time) // @Param sort_by query string false "排序字段" // @Param sort_order query string false "排序方向" Enums(asc, desc) // @Success 200 {object} responses.SubscriptionListResponse "获取订阅列表成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/subscriptions [get] func (h *ProductAdminHandler) ListSubscriptions(c *gin.Context) { var query queries.ListSubscriptionsQuery if err := c.ShouldBindQuery(&query); err != nil { h.responseBuilder.BadRequest(c, err.Error()) return } // 设置默认值 if query.Page <= 0 { query.Page = 1 } if query.PageSize <= 0 { query.PageSize = 10 } if query.PageSize > 100 { query.PageSize = 100 } // 设置默认排序 if query.SortBy == "" { query.SortBy = "created_at" } if query.SortOrder == "" { query.SortOrder = "desc" } result, err := h.subscriptionAppService.ListSubscriptions(c.Request.Context(), &query) if err != nil { h.logger.Error("获取订阅列表失败", zap.Error(err)) h.responseBuilder.InternalError(c, "获取订阅列表失败") return } h.responseBuilder.Success(c, result, "获取订阅列表成功") } // GetSubscriptionStats 获取订阅统计(管理员) // @Summary 获取订阅统计 // @Description 管理员获取订阅统计信息 // @Tags 订阅管理 // @Accept json // @Produce json // @Security Bearer // @Success 200 {object} responses.SubscriptionStatsResponse "获取订阅统计成功" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/subscriptions/stats [get] func (h *ProductAdminHandler) GetSubscriptionStats(c *gin.Context) { result, err := h.subscriptionAppService.GetSubscriptionStats(c.Request.Context()) if err != nil { h.logger.Error("获取订阅统计失败", zap.Error(err)) h.responseBuilder.InternalError(c, "获取订阅统计失败") return } h.responseBuilder.Success(c, result, "获取订阅统计成功") } // GetProductApiConfig 获取产品API配置 // @Summary 获取产品API配置 // @Description 管理员获取产品的API配置信息,如果不存在则返回空配置 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Success 200 {object} responses.ProductApiConfigResponse "获取API配置成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/api-config [get] func (h *ProductAdminHandler) GetProductApiConfig(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } result, err := h.productAppService.GetProductApiConfig(c.Request.Context(), productID) if err != nil { // 如果是配置不存在的错误,返回空配置而不是错误 if err.Error() == "record not found" || err.Error() == "产品API配置不存在" { // 返回空的配置结构,让前端可以创建新配置 emptyConfig := &responses.ProductApiConfigResponse{ ID: "", ProductID: productID, RequestParams: []responses.RequestParamResponse{}, ResponseFields: []responses.ResponseFieldResponse{}, ResponseExample: map[string]interface{}{}, } h.responseBuilder.Success(c, emptyConfig, "获取API配置成功") return } h.logger.Error("获取产品API配置失败", zap.Error(err), zap.String("product_id", productID)) h.responseBuilder.NotFound(c, "产品不存在") return } h.responseBuilder.Success(c, result, "获取API配置成功") } // CreateProductApiConfig 创建产品API配置 // @Summary 创建产品API配置 // @Description 管理员为产品创建API配置 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Param request body responses.ProductApiConfigResponse true "API配置信息" // @Success 201 {object} map[string]interface{} "API配置创建成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 409 {object} map[string]interface{} "API配置已存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/api-config [post] func (h *ProductAdminHandler) CreateProductApiConfig(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } var configResponse responses.ProductApiConfigResponse if err := h.validator.BindAndValidate(c, &configResponse); err != nil { return } if err := h.productAppService.CreateProductApiConfig(c.Request.Context(), productID, &configResponse); err != nil { h.logger.Error("创建产品API配置失败", zap.Error(err), zap.String("product_id", productID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Created(c, nil, "API配置创建成功") } // UpdateProductApiConfig 更新产品API配置 // @Summary 更新产品API配置 // @Description 管理员更新产品的API配置 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Param request body responses.ProductApiConfigResponse true "API配置信息" // @Success 200 {object} map[string]interface{} "API配置更新成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品或配置不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/api-config [put] func (h *ProductAdminHandler) UpdateProductApiConfig(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } var configResponse responses.ProductApiConfigResponse if err := h.validator.BindAndValidate(c, &configResponse); err != nil { return } // 先获取现有配置以获取配置ID existingConfig, err := h.productAppService.GetProductApiConfig(c.Request.Context(), productID) if err != nil { h.logger.Error("获取现有API配置失败", zap.Error(err), zap.String("product_id", productID)) h.responseBuilder.NotFound(c, "产品API配置不存在") return } if err := h.productAppService.UpdateProductApiConfig(c.Request.Context(), existingConfig.ID, &configResponse); err != nil { h.logger.Error("更新产品API配置失败", zap.Error(err), zap.String("product_id", productID)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "API配置更新成功") } // DeleteProductApiConfig 删除产品API配置 // @Summary 删除产品API配置 // @Description 管理员删除产品的API配置 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Success 200 {object} map[string]interface{} "API配置删除成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品或API配置不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/api-config [delete] func (h *ProductAdminHandler) DeleteProductApiConfig(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } if err := h.productAppService.DeleteProductApiConfig(c.Request.Context(), productID); err != nil { h.logger.Error("删除产品API配置失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "API配置删除成功") } // GetProductDocumentation 获取产品文档 // @Summary 获取产品文档 // @Description 管理员获取产品的文档信息 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Success 200 {object} responses.DocumentationResponse "获取文档成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品或文档不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/documentation [get] func (h *ProductAdminHandler) GetProductDocumentation(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } doc, err := h.documentationAppService.GetDocumentationByProductID(c.Request.Context(), productID) if err != nil { // 文档不存在时,返回空数据而不是错误 h.logger.Info("产品文档不存在,返回空数据", zap.String("product_id", productID)) h.responseBuilder.Success(c, nil, "文档不存在") return } h.responseBuilder.Success(c, doc, "获取文档成功") } // CreateOrUpdateProductDocumentation 创建或更新产品文档 // @Summary 创建或更新产品文档 // @Description 管理员创建或更新产品的文档信息,如果文档不存在则创建,存在则更新 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Param request body commands.CreateDocumentationCommand true "文档信息" // @Success 200 {object} responses.DocumentationResponse "文档操作成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/documentation [post] func (h *ProductAdminHandler) CreateOrUpdateProductDocumentation(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } var cmd commands.CreateDocumentationCommand cmd.ProductID = productID if err := h.validator.BindAndValidate(c, &cmd); err != nil { return } // 先尝试获取现有文档 existingDoc, err := h.documentationAppService.GetDocumentationByProductID(c.Request.Context(), productID) if err != nil { // 文档不存在,创建新文档 doc, err := h.documentationAppService.CreateDocumentation(c.Request.Context(), &cmd) if err != nil { h.logger.Error("创建产品文档失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Created(c, doc, "文档创建成功") return } // 文档存在,更新文档 updateCmd := commands.UpdateDocumentationCommand{ RequestURL: cmd.RequestURL, RequestMethod: cmd.RequestMethod, BasicInfo: cmd.BasicInfo, RequestParams: cmd.RequestParams, ResponseFields: cmd.ResponseFields, ResponseExample: cmd.ResponseExample, ErrorCodes: cmd.ErrorCodes, } doc, err := h.documentationAppService.UpdateDocumentation(c.Request.Context(), existingDoc.ID, &updateCmd) if err != nil { h.logger.Error("更新产品文档失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, doc, "文档更新成功") } // DeleteProductDocumentation 删除产品文档 // @Summary 删除产品文档 // @Description 管理员删除产品的文档 // @Tags 产品管理 // @Accept json // @Produce json // @Security Bearer // @Param id path string true "产品ID" // @Success 200 {object} map[string]interface{} "文档删除成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 404 {object} map[string]interface{} "产品或文档不存在" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/products/{id}/documentation [delete] func (h *ProductAdminHandler) DeleteProductDocumentation(c *gin.Context) { productID := c.Param("id") if productID == "" { h.responseBuilder.BadRequest(c, "产品ID不能为空") return } // 先获取文档 doc, err := h.documentationAppService.GetDocumentationByProductID(c.Request.Context(), productID) if err != nil { h.responseBuilder.NotFound(c, "文档不存在") return } // 删除文档 if err := h.documentationAppService.DeleteDocumentation(c.Request.Context(), doc.ID); err != nil { h.logger.Error("删除产品文档失败", zap.Error(err)) h.responseBuilder.BadRequest(c, err.Error()) return } h.responseBuilder.Success(c, nil, "文档删除成功") } // GetAdminApiCalls 获取管理端API调用记录 // @Summary 获取管理端API调用记录 // @Description 管理员获取API调用记录,支持筛选和分页 // @Tags API管理 // @Accept json // @Produce json // @Security Bearer // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(10) // @Param user_id query string false "用户ID" // @Param transaction_id query string false "交易ID" // @Param product_name query string false "产品名称" // @Param status query string false "状态" // @Param start_time query string false "开始时间" format(date-time) // @Param end_time query string false "结束时间" format(date-time) // @Param sort_by query string false "排序字段" // @Param sort_order query string false "排序方向" Enums(asc, desc) // @Success 200 {object} dto.ApiCallListResponse "获取API调用记录成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/api-calls [get] func (h *ProductAdminHandler) GetAdminApiCalls(c *gin.Context) { // 解析查询参数 page := h.getIntQuery(c, "page", 1) pageSize := h.getIntQuery(c, "page_size", 10) // 构建筛选条件 filters := make(map[string]interface{}) // 用户ID筛选 if userId := c.Query("user_id"); userId != "" { filters["user_id"] = userId } // 时间范围筛选 if startTime := c.Query("start_time"); startTime != "" { if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil { filters["start_time"] = t } } if endTime := c.Query("end_time"); endTime != "" { if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil { filters["end_time"] = t } } // 交易ID筛选 if transactionId := c.Query("transaction_id"); transactionId != "" { filters["transaction_id"] = transactionId } // 产品名称筛选 if productName := c.Query("product_name"); productName != "" { filters["product_name"] = productName } // 状态筛选 if status := c.Query("status"); status != "" { filters["status"] = status } // 构建分页选项 options := interfaces.ListOptions{ Page: page, PageSize: pageSize, Sort: "created_at", Order: "desc", } result, err := h.apiAppService.GetAdminApiCalls(c.Request.Context(), filters, options) if err != nil { h.logger.Error("获取管理端API调用记录失败", zap.Error(err)) h.responseBuilder.BadRequest(c, "获取API调用记录失败") return } h.responseBuilder.Success(c, result, "获取API调用记录成功") } // GetAdminWalletTransactions 获取管理端消费记录 // @Summary 获取管理端消费记录 // @Description 管理员获取消费记录,支持筛选和分页 // @Tags 财务管理 // @Accept json // @Produce json // @Security Bearer // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(10) // @Param user_id query string false "用户ID" // @Param transaction_id query string false "交易ID" // @Param product_name query string false "产品名称" // @Param min_amount query string false "最小金额" // @Param max_amount query string false "最大金额" // @Param start_time query string false "开始时间" format(date-time) // @Param end_time query string false "结束时间" format(date-time) // @Param sort_by query string false "排序字段" // @Param sort_order query string false "排序方向" Enums(asc, desc) // @Success 200 {object} dto.WalletTransactionListResponse "获取消费记录成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/wallet-transactions [get] func (h *ProductAdminHandler) GetAdminWalletTransactions(c *gin.Context) { // 解析查询参数 page := h.getIntQuery(c, "page", 1) pageSize := h.getIntQuery(c, "page_size", 10) // 构建筛选条件 filters := make(map[string]interface{}) // 用户ID筛选 if userId := c.Query("user_id"); userId != "" { filters["user_id"] = userId } // 时间范围筛选 if startTime := c.Query("start_time"); startTime != "" { if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil { filters["start_time"] = t } } if endTime := c.Query("end_time"); endTime != "" { if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil { filters["end_time"] = t } } // 交易ID筛选 if transactionId := c.Query("transaction_id"); transactionId != "" { filters["transaction_id"] = transactionId } // 产品名称筛选 if productName := c.Query("product_name"); productName != "" { filters["product_name"] = productName } // 金额范围筛选 if minAmount := c.Query("min_amount"); minAmount != "" { filters["min_amount"] = minAmount } if maxAmount := c.Query("max_amount"); maxAmount != "" { filters["max_amount"] = maxAmount } // 构建分页选项 options := interfaces.ListOptions{ Page: page, PageSize: pageSize, Sort: "created_at", Order: "desc", } result, err := h.financeAppService.GetAdminWalletTransactions(c.Request.Context(), filters, options) if err != nil { h.logger.Error("获取管理端消费记录失败", zap.Error(err)) h.responseBuilder.BadRequest(c, "获取消费记录失败") return } h.responseBuilder.Success(c, result, "获取消费记录成功") } // GetAdminRechargeRecords 获取管理端充值记录 // @Summary 获取管理端充值记录 // @Description 管理员获取充值记录,支持筛选和分页 // @Tags 财务管理 // @Accept json // @Produce json // @Security Bearer // @Param page query int false "页码" default(1) // @Param page_size query int false "每页数量" default(10) // @Param user_id query string false "用户ID" // @Param recharge_type query string false "充值类型" Enums(alipay, transfer, gift) // @Param status query string false "状态" Enums(pending, success, failed) // @Param min_amount query string false "最小金额" // @Param max_amount query string false "最大金额" // @Param start_time query string false "开始时间" format(date-time) // @Param end_time query string false "结束时间" format(date-time) // @Param sort_by query string false "排序字段" // @Param sort_order query string false "排序方向" Enums(asc, desc) // @Success 200 {object} dto.RechargeRecordListResponse "获取充值记录成功" // @Failure 400 {object} map[string]interface{} "请求参数错误" // @Failure 401 {object} map[string]interface{} "未认证" // @Failure 500 {object} map[string]interface{} "服务器内部错误" // @Router /api/v1/admin/recharge-records [get] func (h *ProductAdminHandler) GetAdminRechargeRecords(c *gin.Context) { // 解析查询参数 page := h.getIntQuery(c, "page", 1) pageSize := h.getIntQuery(c, "page_size", 10) // 构建筛选条件 filters := make(map[string]interface{}) // 用户ID筛选 if userId := c.Query("user_id"); userId != "" { filters["user_id"] = userId } // 时间范围筛选 if startTime := c.Query("start_time"); startTime != "" { if t, err := time.Parse("2006-01-02 15:04:05", startTime); err == nil { filters["start_time"] = t } } if endTime := c.Query("end_time"); endTime != "" { if t, err := time.Parse("2006-01-02 15:04:05", endTime); err == nil { filters["end_time"] = t } } // 充值类型筛选 if rechargeType := c.Query("recharge_type"); rechargeType != "" { filters["recharge_type"] = rechargeType } // 状态筛选 if status := c.Query("status"); status != "" { filters["status"] = status } // 金额范围筛选 if minAmount := c.Query("min_amount"); minAmount != "" { filters["min_amount"] = minAmount } if maxAmount := c.Query("max_amount"); maxAmount != "" { filters["max_amount"] = maxAmount } // 构建分页选项 options := interfaces.ListOptions{ Page: page, PageSize: pageSize, Sort: "created_at", Order: "desc", } result, err := h.financeAppService.GetAdminRechargeRecords(c.Request.Context(), filters, options) if err != nil { h.logger.Error("获取管理端充值记录失败", zap.Error(err)) h.responseBuilder.BadRequest(c, "获取充值记录失败") return } h.responseBuilder.Success(c, result, "获取充值记录成功") }