package admin import ( "net/http" "strconv" "bindbox-game/internal/code" "bindbox-game/internal/pkg/core" "bindbox-game/internal/repository/mysql/model" ) type dailyLivestreamStats struct { Date string `json:"date"` // 日期 TotalRevenue int64 `json:"total_revenue"` // 营收 TotalRefund int64 `json:"total_refund"` // 退款 TotalCost int64 `json:"total_cost"` // 成本 NetProfit int64 `json:"net_profit"` // 净利润 ProfitMargin float64 `json:"profit_margin"` // 利润率 OrderCount int64 `json:"order_count"` // 订单数 RefundCount int64 `json:"refund_count"` // 退款单数 } type livestreamStatsResponse struct { TotalRevenue int64 `json:"total_revenue"` // 总营收(分) TotalRefund int64 `json:"total_refund"` // 总退款(分) TotalCost int64 `json:"total_cost"` // 总成本(分) NetProfit int64 `json:"net_profit"` // 净利润(分) OrderCount int64 `json:"order_count"` // 订单数 RefundCount int64 `json:"refund_count"` // 退款数 ProfitMargin float64 `json:"profit_margin"` // 利润率 % Daily []dailyLivestreamStats `json:"daily"` // 每日明细 } // GetLivestreamStats 获取直播间盈亏统计 // @Summary 获取直播间盈亏统计 // @Description 计算逻辑:净利润 = (营收 - 退款) - 奖品成本。营收 = 抽奖次数 * 门票价格。成本 = 中奖奖品成本总和。 // @Tags 管理端.直播间 // @Accept json // @Produce json // @Param id path integer true "活动ID" // @Success 200 {object} livestreamStatsResponse // @Failure 400 {object} code.Failure // @Router /api/admin/livestream/activities/{id}/stats [get] // @Security LoginVerifyToken func (h *handler) GetLivestreamStats() core.HandlerFunc { return func(ctx core.Context) { id, err := strconv.ParseInt(ctx.Param("id"), 10, 64) if err != nil || id <= 0 { ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的活动ID")) return } req := new(struct { StartTime string `form:"start_time"` EndTime string `form:"end_time"` }) _ = ctx.ShouldBindQuery(req) startTime, endTime := parseLivestreamDateRange(req.StartTime, req.EndTime, false) var activity model.LivestreamActivities if err := h.repo.GetDbR().Where("id = ?", id).First(&activity).Error; err != nil { ctx.AbortWithError(core.Error(http.StatusNotFound, code.ServerError, "活动不存在")) return } metrics, err := h.buildLivestreamMetrics(livestreamMetricsFilter{ ActivityID: id, StartTime: startTime, EndTime: endTime, }, int64(activity.TicketPrice)) if err != nil { ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error())) return } ctx.Payload(&livestreamStatsResponse{ TotalRevenue: metrics.TotalRevenue, TotalRefund: metrics.TotalRefund, TotalCost: metrics.TotalCost, NetProfit: metrics.NetProfit, OrderCount: metrics.OrderCount, RefundCount: metrics.RefundCount, ProfitMargin: metrics.ProfitMargin, Daily: metrics.Daily, }) } }