1562 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			1562 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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
 | ||
| 	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.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, "获取订阅列表成功")
 | ||
| }
 | ||
| 
 | ||
| // BatchUpdateSubscriptionPrices 一键改价
 | ||
| // @Summary 一键改价
 | ||
| // @Description 管理员一键调整用户所有订阅的价格
 | ||
| // @Tags 订阅管理
 | ||
| // @Accept json
 | ||
| // @Produce json
 | ||
| // @Security Bearer
 | ||
| // @Param request body commands.BatchUpdateSubscriptionPricesCommand true "批量改价请求"
 | ||
| // @Success 200 {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/subscriptions/batch-update-prices [post]
 | ||
| func (h *ProductAdminHandler) BatchUpdateSubscriptionPrices(c *gin.Context) {
 | ||
| 	var cmd commands.BatchUpdateSubscriptionPricesCommand
 | ||
| 	if err := c.ShouldBindJSON(&cmd); err != nil {
 | ||
| 		h.responseBuilder.BadRequest(c, err.Error())
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	err := h.subscriptionAppService.BatchUpdateSubscriptionPrices(c.Request.Context(), &cmd)
 | ||
| 	if err != nil {
 | ||
| 		h.logger.Error("一键改价失败", zap.Error(err), zap.String("user_id", cmd.UserID))
 | ||
| 		h.responseBuilder.InternalError(c, "一键改价失败")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	h.responseBuilder.Success(c, map[string]interface{}{
 | ||
| 		"user_id": cmd.UserID,
 | ||
| 		"discount": cmd.Discount,
 | ||
| 		"scope": cmd.Scope,
 | ||
| 	}, "一键改价成功")
 | ||
| }
 | ||
| 
 | ||
| // 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, "文档删除成功")
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 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} responses.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, "获取消费记录成功")
 | ||
| }
 | ||
| 
 | ||
| // ExportAdminWalletTransactions 导出管理端消费记录
 | ||
| // @Summary 导出管理端消费记录
 | ||
| // @Description 管理员导出消费记录,支持Excel和CSV格式
 | ||
| // @Tags 财务管理
 | ||
| // @Accept json
 | ||
| // @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
 | ||
| // @Security Bearer
 | ||
| // @Param user_ids query string false "用户ID列表,逗号分隔"
 | ||
| // @Param user_id query string false "单个用户ID"
 | ||
| // @Param transaction_id query string false "交易ID"
 | ||
| // @Param product_name query string false "产品名称"
 | ||
| // @Param product_ids query string false "产品ID列表,逗号分隔"
 | ||
| // @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 format query string false "导出格式" Enums(excel, csv) default(excel)
 | ||
| // @Success 200 {file} file "导出文件"
 | ||
| // @Failure 400 {object} map[string]interface{} "请求参数错误"
 | ||
| // @Failure 401 {object} map[string]interface{} "未认证"
 | ||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误"
 | ||
| // @Router /api/v1/admin/wallet-transactions/export [get]
 | ||
| func (h *ProductAdminHandler) ExportAdminWalletTransactions(c *gin.Context) {
 | ||
| 	// 构建筛选条件
 | ||
| 	filters := make(map[string]interface{})
 | ||
| 
 | ||
| 	// 用户ID筛选
 | ||
| 	if userIds := c.Query("user_ids"); userIds != "" {
 | ||
| 		filters["user_ids"] = userIds
 | ||
| 	} else 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
 | ||
| 	}
 | ||
| 
 | ||
| 	// 产品ID列表筛选
 | ||
| 	if productIds := c.Query("product_ids"); productIds != "" {
 | ||
| 		filters["product_ids"] = productIds
 | ||
| 	}
 | ||
| 
 | ||
| 	// 金额范围筛选
 | ||
| 	if minAmount := c.Query("min_amount"); minAmount != "" {
 | ||
| 		filters["min_amount"] = minAmount
 | ||
| 	}
 | ||
| 	if maxAmount := c.Query("max_amount"); maxAmount != "" {
 | ||
| 		filters["max_amount"] = maxAmount
 | ||
| 	}
 | ||
| 
 | ||
| 	// 获取导出格式
 | ||
| 	format := c.DefaultQuery("format", "excel")
 | ||
| 	if format != "excel" && format != "csv" {
 | ||
| 		h.responseBuilder.BadRequest(c, "不支持的导出格式")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 调用导出服务
 | ||
| 	fileData, err := h.financeAppService.ExportAdminWalletTransactions(c.Request.Context(), filters, format)
 | ||
| 	if err != nil {
 | ||
| 		h.logger.Error("导出消费记录失败", zap.Error(err))
 | ||
| 		h.responseBuilder.BadRequest(c, "导出消费记录失败")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 设置响应头
 | ||
| 	contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
 | ||
| 	filename := "消费记录.xlsx"
 | ||
| 	if format == "csv" {
 | ||
| 		contentType = "text/csv;charset=utf-8"
 | ||
| 		filename = "消费记录.csv"
 | ||
| 	}
 | ||
| 
 | ||
| 	c.Header("Content-Type", contentType)
 | ||
| 	c.Header("Content-Disposition", "attachment; filename="+filename)
 | ||
| 	c.Data(200, contentType, fileData)
 | ||
| }
 | ||
| 
 | ||
| // 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} responses.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, "获取充值记录成功")
 | ||
| }
 | ||
| 
 | ||
| // ExportAdminRechargeRecords 导出管理端充值记录
 | ||
| // @Summary 导出管理端充值记录
 | ||
| // @Description 管理员导出充值记录,支持Excel和CSV格式
 | ||
| // @Tags 财务管理
 | ||
| // @Accept json
 | ||
| // @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,text/csv
 | ||
| // @Security Bearer
 | ||
| // @Param user_ids query string false "用户ID列表,逗号分隔"
 | ||
| // @Param recharge_type query string false "充值类型" Enums(alipay, transfer, gift)
 | ||
| // @Param status query string false "状态" Enums(pending, success, failed)
 | ||
| // @Param start_time query string false "开始时间" format(date-time)
 | ||
| // @Param end_time query string false "结束时间" format(date-time)
 | ||
| // @Param format query string false "导出格式" Enums(excel, csv) default(excel)
 | ||
| // @Success 200 {file} file "导出文件"
 | ||
| // @Failure 400 {object} map[string]interface{} "请求参数错误"
 | ||
| // @Failure 401 {object} map[string]interface{} "未认证"
 | ||
| // @Failure 500 {object} map[string]interface{} "服务器内部错误"
 | ||
| // @Router /api/v1/admin/recharge-records/export [get]
 | ||
| func (h *ProductAdminHandler) ExportAdminRechargeRecords(c *gin.Context) {
 | ||
| 	// 解析查询参数
 | ||
| 	filters := make(map[string]interface{})
 | ||
| 
 | ||
| 	// 用户ID筛选
 | ||
| 	if userIds := c.Query("user_ids"); userIds != "" {
 | ||
| 		filters["user_ids"] = userIds
 | ||
| 	}
 | ||
| 
 | ||
| 	// 充值类型筛选
 | ||
| 	if rechargeType := c.Query("recharge_type"); rechargeType != "" {
 | ||
| 		filters["recharge_type"] = rechargeType
 | ||
| 	}
 | ||
| 
 | ||
| 	// 状态筛选
 | ||
| 	if status := c.Query("status"); status != "" {
 | ||
| 		filters["status"] = status
 | ||
| 	}
 | ||
| 
 | ||
| 	// 时间范围筛选
 | ||
| 	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
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	// 获取导出格式,默认为excel
 | ||
| 	format := c.DefaultQuery("format", "excel")
 | ||
| 	if format != "excel" && format != "csv" {
 | ||
| 		h.responseBuilder.BadRequest(c, "不支持的导出格式")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 调用应用服务导出数据
 | ||
| 	fileData, err := h.financeAppService.ExportAdminRechargeRecords(c.Request.Context(), filters, format)
 | ||
| 	if err != nil {
 | ||
| 		h.logger.Error("导出充值记录失败", zap.Error(err))
 | ||
| 		h.responseBuilder.BadRequest(c, "导出充值记录失败")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 设置响应头
 | ||
| 	contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
 | ||
| 	filename := "充值记录.xlsx"
 | ||
| 	if format == "csv" {
 | ||
| 		contentType = "text/csv;charset=utf-8"
 | ||
| 		filename = "充值记录.csv"
 | ||
| 	}
 | ||
| 
 | ||
| 	c.Header("Content-Type", contentType)
 | ||
| 	c.Header("Content-Disposition", "attachment; filename="+filename)
 | ||
| 	c.Data(200, contentType, fileData)
 | ||
| }
 | ||
| 
 | ||
| // GetAdminApiCalls 获取管理端API调用记录
 | ||
| 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 userIds := c.Query("user_ids"); userIds != "" {
 | ||
| 		filters["user_ids"] = userIds
 | ||
| 	}
 | ||
| 
 | ||
| 	// 产品ID筛选
 | ||
| 	if productIds := c.Query("product_ids"); productIds != "" {
 | ||
| 		filters["product_ids"] = productIds
 | ||
| 	}
 | ||
| 
 | ||
| 	// 时间范围筛选
 | ||
| 	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
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	// 构建分页选项
 | ||
| 	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调用记录成功")
 | ||
| }
 | ||
| 
 | ||
| // ExportAdminApiCalls 导出管理端API调用记录
 | ||
| func (h *ProductAdminHandler) ExportAdminApiCalls(c *gin.Context) {
 | ||
| 	// 解析查询参数
 | ||
| 	filters := make(map[string]interface{})
 | ||
| 
 | ||
| 	// 用户ID筛选
 | ||
| 	if userIds := c.Query("user_ids"); userIds != "" {
 | ||
| 		filters["user_ids"] = userIds
 | ||
| 	}
 | ||
| 
 | ||
| 	// 产品ID筛选
 | ||
| 	if productIds := c.Query("product_ids"); productIds != "" {
 | ||
| 		filters["product_ids"] = productIds
 | ||
| 	}
 | ||
| 
 | ||
| 	// 时间范围筛选
 | ||
| 	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
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	// 获取导出格式,默认为excel
 | ||
| 	format := c.DefaultQuery("format", "excel")
 | ||
| 	if format != "excel" && format != "csv" {
 | ||
| 		h.responseBuilder.BadRequest(c, "不支持的导出格式")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 调用应用服务导出数据
 | ||
| 	fileData, err := h.apiAppService.ExportAdminApiCalls(c.Request.Context(), filters, format)
 | ||
| 	if err != nil {
 | ||
| 		h.logger.Error("导出API调用记录失败", zap.Error(err))
 | ||
| 		h.responseBuilder.BadRequest(c, "导出API调用记录失败")
 | ||
| 		return
 | ||
| 	}
 | ||
| 
 | ||
| 	// 设置响应头
 | ||
| 	contentType := "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
 | ||
| 	filename := "API调用记录.xlsx"
 | ||
| 	if format == "csv" {
 | ||
| 		contentType = "text/csv;charset=utf-8"
 | ||
| 		filename = "API调用记录.csv"
 | ||
| 	}
 | ||
| 
 | ||
| 	c.Header("Content-Type", contentType)
 | ||
| 	c.Header("Content-Disposition", "attachment; filename="+filename)
 | ||
| 	c.Data(200, contentType, fileData)
 | ||
| }
 |