672 lines
22 KiB
Go
672 lines
22 KiB
Go
package admin
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
"bindbox-game/internal/code"
|
|
"bindbox-game/internal/pkg/core"
|
|
"bindbox-game/internal/pkg/validation"
|
|
"bindbox-game/internal/repository/mysql/model"
|
|
"bindbox-game/internal/service/livestream"
|
|
)
|
|
|
|
// ========== 直播间活动管理 ==========
|
|
|
|
type createLivestreamActivityRequest struct {
|
|
Name string `json:"name" binding:"required"`
|
|
StreamerName string `json:"streamer_name"`
|
|
StreamerContact string `json:"streamer_contact"`
|
|
DouyinProductID string `json:"douyin_product_id"`
|
|
TicketPrice int64 `json:"ticket_price"`
|
|
StartTime string `json:"start_time"`
|
|
EndTime string `json:"end_time"`
|
|
}
|
|
|
|
type livestreamActivityResponse struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
StreamerName string `json:"streamer_name"`
|
|
StreamerContact string `json:"streamer_contact"`
|
|
AccessCode string `json:"access_code"`
|
|
DouyinProductID string `json:"douyin_product_id"`
|
|
TicketPrice int64 `json:"ticket_price"`
|
|
Status int32 `json:"status"`
|
|
StartTime string `json:"start_time,omitempty"`
|
|
EndTime string `json:"end_time,omitempty"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
// CreateLivestreamActivity 创建直播间活动
|
|
// @Summary 创建直播间活动
|
|
// @Description 创建新的直播间活动,自动生成唯一访问码
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param RequestBody body createLivestreamActivityRequest true "请求参数"
|
|
// @Success 200 {object} livestreamActivityResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities [post]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) CreateLivestreamActivity() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
req := new(createLivestreamActivityRequest)
|
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
input := livestream.CreateActivityInput{
|
|
Name: req.Name,
|
|
StreamerName: req.StreamerName,
|
|
StreamerContact: req.StreamerContact,
|
|
DouyinProductID: req.DouyinProductID,
|
|
TicketPrice: req.TicketPrice,
|
|
}
|
|
|
|
if req.StartTime != "" {
|
|
if t, err := time.ParseInLocation("2006-01-02 15:04:05", req.StartTime, time.Local); err == nil {
|
|
input.StartTime = &t
|
|
}
|
|
}
|
|
if req.EndTime != "" {
|
|
if t, err := time.ParseInLocation("2006-01-02 15:04:05", req.EndTime, time.Local); err == nil {
|
|
input.EndTime = &t
|
|
}
|
|
}
|
|
|
|
activity, err := h.livestream.CreateActivity(ctx.RequestContext(), input)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(&livestreamActivityResponse{
|
|
ID: activity.ID,
|
|
Name: activity.Name,
|
|
StreamerName: activity.StreamerName,
|
|
StreamerContact: activity.StreamerContact,
|
|
AccessCode: activity.AccessCode,
|
|
DouyinProductID: activity.DouyinProductID,
|
|
TicketPrice: activity.TicketPrice,
|
|
Status: activity.Status,
|
|
CreatedAt: activity.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
})
|
|
}
|
|
}
|
|
|
|
type updateLivestreamActivityRequest struct {
|
|
Name string `json:"name"`
|
|
StreamerName string `json:"streamer_name"`
|
|
StreamerContact string `json:"streamer_contact"`
|
|
DouyinProductID string `json:"douyin_product_id"`
|
|
TicketPrice *int64 `json:"ticket_price"`
|
|
Status *int32 `json:"status"`
|
|
StartTime string `json:"start_time"`
|
|
EndTime string `json:"end_time"`
|
|
}
|
|
|
|
// UpdateLivestreamActivity 更新直播间活动
|
|
// @Summary 更新直播间活动
|
|
// @Description 更新直播间活动信息
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path integer true "活动ID"
|
|
// @Param RequestBody body updateLivestreamActivityRequest true "请求参数"
|
|
// @Success 200 {object} simpleMessageResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{id} [put]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) UpdateLivestreamActivity() 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(updateLivestreamActivityRequest)
|
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
input := livestream.UpdateActivityInput{
|
|
Name: req.Name,
|
|
StreamerName: req.StreamerName,
|
|
StreamerContact: req.StreamerContact,
|
|
DouyinProductID: req.DouyinProductID,
|
|
TicketPrice: req.TicketPrice,
|
|
Status: req.Status,
|
|
}
|
|
|
|
if req.StartTime != "" {
|
|
if t, err := time.ParseInLocation("2006-01-02 15:04:05", req.StartTime, time.Local); err == nil {
|
|
input.StartTime = &t
|
|
}
|
|
}
|
|
if req.EndTime != "" {
|
|
if t, err := time.ParseInLocation("2006-01-02 15:04:05", req.EndTime, time.Local); err == nil {
|
|
input.EndTime = &t
|
|
}
|
|
}
|
|
|
|
if err := h.livestream.UpdateActivity(ctx.RequestContext(), id, input); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(&simpleMessageResponse{Message: "操作成功"})
|
|
}
|
|
}
|
|
|
|
type listLivestreamActivitiesRequest struct {
|
|
Page int `form:"page"`
|
|
PageSize int `form:"page_size"`
|
|
Status *int32 `form:"status"`
|
|
}
|
|
|
|
type listLivestreamActivitiesResponse struct {
|
|
List []livestreamActivityResponse `json:"list"`
|
|
Total int64 `json:"total"`
|
|
Page int `json:"page"`
|
|
PageSize int `json:"page_size"`
|
|
}
|
|
|
|
// ListLivestreamActivities 直播间活动列表
|
|
// @Summary 直播间活动列表
|
|
// @Description 获取直播间活动列表
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param page query int false "页码" default(1)
|
|
// @Param page_size query int false "每页数量" default(20)
|
|
// @Param status query int false "状态过滤"
|
|
// @Success 200 {object} listLivestreamActivitiesResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities [get]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) ListLivestreamActivities() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
req := new(listLivestreamActivitiesRequest)
|
|
if err := ctx.ShouldBindForm(req); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
if req.Page <= 0 {
|
|
req.Page = 1
|
|
}
|
|
if req.PageSize <= 0 {
|
|
req.PageSize = 20
|
|
}
|
|
|
|
list, total, err := h.livestream.ListActivities(ctx.RequestContext(), req.Page, req.PageSize, req.Status)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
res := &listLivestreamActivitiesResponse{
|
|
List: make([]livestreamActivityResponse, len(list)),
|
|
Total: total,
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
}
|
|
|
|
for i, a := range list {
|
|
item := livestreamActivityResponse{
|
|
ID: a.ID,
|
|
Name: a.Name,
|
|
StreamerName: a.StreamerName,
|
|
StreamerContact: a.StreamerContact,
|
|
AccessCode: a.AccessCode,
|
|
DouyinProductID: a.DouyinProductID,
|
|
TicketPrice: a.TicketPrice,
|
|
Status: a.Status,
|
|
CreatedAt: a.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
}
|
|
if !a.StartTime.IsZero() {
|
|
item.StartTime = a.StartTime.Format("2006-01-02 15:04:05")
|
|
}
|
|
if !a.EndTime.IsZero() {
|
|
item.EndTime = a.EndTime.Format("2006-01-02 15:04:05")
|
|
}
|
|
res.List[i] = item
|
|
}
|
|
|
|
ctx.Payload(res)
|
|
}
|
|
}
|
|
|
|
// GetLivestreamActivity 获取直播间活动详情
|
|
// @Summary 获取直播间活动详情
|
|
// @Description 根据ID获取直播间活动详情
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path integer true "活动ID"
|
|
// @Success 200 {object} livestreamActivityResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{id} [get]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) GetLivestreamActivity() 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
|
|
}
|
|
|
|
activity, err := h.livestream.GetActivity(ctx.RequestContext(), id)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusNotFound, code.ServerError, "活动不存在"))
|
|
return
|
|
}
|
|
|
|
res := &livestreamActivityResponse{
|
|
ID: activity.ID,
|
|
Name: activity.Name,
|
|
StreamerName: activity.StreamerName,
|
|
StreamerContact: activity.StreamerContact,
|
|
AccessCode: activity.AccessCode,
|
|
DouyinProductID: activity.DouyinProductID,
|
|
TicketPrice: activity.TicketPrice,
|
|
Status: activity.Status,
|
|
CreatedAt: activity.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
}
|
|
if !activity.StartTime.IsZero() {
|
|
res.StartTime = activity.StartTime.Format("2006-01-02 15:04:05")
|
|
}
|
|
if !activity.EndTime.IsZero() {
|
|
res.EndTime = activity.EndTime.Format("2006-01-02 15:04:05")
|
|
}
|
|
|
|
ctx.Payload(res)
|
|
}
|
|
}
|
|
|
|
// DeleteLivestreamActivity 删除直播间活动
|
|
// @Summary 删除直播间活动
|
|
// @Description 删除指定直播间活动
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path integer true "活动ID"
|
|
// @Success 200 {object} simpleMessageResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{id} [delete]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) DeleteLivestreamActivity() 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
|
|
}
|
|
|
|
if err := h.livestream.DeleteActivity(ctx.RequestContext(), id); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(&simpleMessageResponse{Message: "删除成功"})
|
|
}
|
|
}
|
|
|
|
// ========== 直播间奖品管理 ==========
|
|
|
|
type createLivestreamPrizeRequest struct {
|
|
Name string `json:"name"`
|
|
Image string `json:"image"`
|
|
Level int32 `json:"level"`
|
|
Weight int32 `json:"weight"`
|
|
Quantity int32 `json:"quantity"`
|
|
ProductID int64 `json:"product_id"`
|
|
CostPrice int64 `json:"cost_price"`
|
|
}
|
|
|
|
type livestreamPrizeResponse struct {
|
|
ID int64 `json:"id"`
|
|
Name string `json:"name"`
|
|
Image string `json:"image"`
|
|
Level int32 `json:"level"`
|
|
Weight int32 `json:"weight"`
|
|
Quantity int32 `json:"quantity"`
|
|
Remaining int64 `json:"remaining"`
|
|
ProductID int64 `json:"product_id"`
|
|
CostPrice int64 `json:"cost_price"`
|
|
Sort int32 `json:"sort"`
|
|
}
|
|
|
|
// CreateLivestreamPrizes 批量创建奖品
|
|
// @Summary 批量创建直播间奖品
|
|
// @Description 为指定活动批量创建奖品
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param activity_id path integer true "活动ID"
|
|
// @Param RequestBody body []createLivestreamPrizeRequest true "奖品列表"
|
|
// @Success 200 {object} simpleMessageResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{activity_id}/prizes [post]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) CreateLivestreamPrizes() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
activityID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
|
|
if err != nil || activityID <= 0 {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的活动ID"))
|
|
return
|
|
}
|
|
|
|
var req []createLivestreamPrizeRequest
|
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
var inputs []livestream.CreatePrizeInput
|
|
for _, p := range req {
|
|
inputs = append(inputs, livestream.CreatePrizeInput{
|
|
Name: p.Name,
|
|
Image: p.Image,
|
|
Weight: p.Weight,
|
|
Quantity: p.Quantity,
|
|
Level: p.Level,
|
|
ProductID: p.ProductID,
|
|
CostPrice: p.CostPrice,
|
|
})
|
|
}
|
|
|
|
if err := h.livestream.CreatePrizes(ctx.RequestContext(), activityID, inputs); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(&simpleMessageResponse{Message: "创建成功"})
|
|
}
|
|
}
|
|
|
|
// ListLivestreamPrizes 获取活动奖品列表
|
|
// @Summary 获取直播间活动奖品列表
|
|
// @Description 获取指定活动的所有奖品
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param activity_id path integer true "活动ID"
|
|
// @Success 200 {object} []livestreamPrizeResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{activity_id}/prizes [get]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) ListLivestreamPrizes() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
activityID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
|
|
if err != nil || activityID <= 0 {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的活动ID"))
|
|
return
|
|
}
|
|
|
|
prizes, err := h.livestream.ListPrizes(ctx.RequestContext(), activityID)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
res := make([]livestreamPrizeResponse, len(prizes))
|
|
for i, p := range prizes {
|
|
res[i] = livestreamPrizeResponse{
|
|
ID: p.ID,
|
|
Name: p.Name,
|
|
Image: p.Image,
|
|
Weight: p.Weight,
|
|
Quantity: p.Quantity,
|
|
Remaining: int64(p.Remaining),
|
|
Level: p.Level,
|
|
ProductID: p.ProductID,
|
|
CostPrice: p.CostPrice,
|
|
Sort: p.Sort,
|
|
}
|
|
}
|
|
|
|
ctx.Payload(res)
|
|
}
|
|
}
|
|
|
|
// DeleteLivestreamPrize 删除奖品
|
|
// @Summary 删除直播间奖品
|
|
// @Description 删除指定奖品
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param prize_id path integer true "奖品ID"
|
|
// @Success 200 {object} simpleMessageResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/prizes/{prize_id} [delete]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) DeleteLivestreamPrize() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
prizeID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
|
|
if err != nil || prizeID <= 0 {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的奖品ID"))
|
|
return
|
|
}
|
|
|
|
if err := h.livestream.DeletePrize(ctx.RequestContext(), prizeID); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(&simpleMessageResponse{Message: "删除成功"})
|
|
}
|
|
}
|
|
|
|
// ========== 直播间中奖记录 ==========
|
|
|
|
type livestreamDrawLogResponse struct {
|
|
ID int64 `json:"id"`
|
|
ActivityID int64 `json:"activity_id"`
|
|
PrizeID int64 `json:"prize_id"`
|
|
PrizeName string `json:"prize_name"`
|
|
Level int32 `json:"level"`
|
|
DouyinOrderID int64 `json:"douyin_order_id"` // 关联ID
|
|
ShopOrderID string `json:"shop_order_id"` // 店铺订单号
|
|
LocalUserID int64 `json:"local_user_id"`
|
|
DouyinUserID string `json:"douyin_user_id"`
|
|
UserNickname string `json:"user_nickname"` // 用户昵称
|
|
SeedHash string `json:"seed_hash"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
type listLivestreamDrawLogsResponse struct {
|
|
List []livestreamDrawLogResponse `json:"list"`
|
|
Total int64 `json:"total"`
|
|
Page int `json:"page"`
|
|
PageSize int `json:"page_size"`
|
|
}
|
|
|
|
type listLivestreamDrawLogsRequest struct {
|
|
Page int `form:"page"`
|
|
PageSize int `form:"page_size"`
|
|
StartTime string `form:"start_time"`
|
|
EndTime string `form:"end_time"`
|
|
Keyword string `form:"keyword"`
|
|
}
|
|
|
|
// ListLivestreamDrawLogs 获取中奖记录
|
|
// @Summary 获取直播间中奖记录
|
|
// @Description 获取指定活动的中奖记录,支持时间范围和关键词筛选
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param activity_id path integer true "活动ID"
|
|
// @Param page query int false "页码" default(1)
|
|
// @Param page_size query int false "每页数量" default(20)
|
|
// @Param start_time query string false "开始时间 (YYYY-MM-DD)"
|
|
// @Param end_time query string false "结束时间 (YYYY-MM-DD)"
|
|
// @Param keyword query string false "搜索关键词 (昵称/订单号/奖品名称)"
|
|
// @Success 200 {object} listLivestreamDrawLogsResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{activity_id}/draw_logs [get]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) ListLivestreamDrawLogs() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
activityID, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
|
|
if err != nil || activityID <= 0 {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的活动ID"))
|
|
return
|
|
}
|
|
|
|
req := new(listLivestreamDrawLogsRequest)
|
|
_ = ctx.ShouldBindForm(req)
|
|
|
|
page := req.Page
|
|
pageSize := req.PageSize
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if pageSize <= 0 {
|
|
pageSize = 20
|
|
}
|
|
|
|
// 解析时间范围
|
|
var startTime, endTime *time.Time
|
|
if req.StartTime != "" {
|
|
if t, err := time.ParseInLocation("2006-01-02", req.StartTime, time.Local); err == nil {
|
|
startTime = &t
|
|
}
|
|
}
|
|
if req.EndTime != "" {
|
|
if t, err := time.ParseInLocation("2006-01-02", req.EndTime, time.Local); err == nil {
|
|
// 结束时间设为当天结束
|
|
end := t.Add(24*time.Hour - time.Nanosecond)
|
|
endTime = &end
|
|
}
|
|
}
|
|
|
|
// 使用底层 GORM 直接查询以支持 keyword
|
|
db := h.repo.GetDbR().Model(&model.LivestreamDrawLogs{}).Where("activity_id = ?", activityID)
|
|
|
|
if startTime != nil {
|
|
db = db.Where("created_at >= ?", startTime)
|
|
}
|
|
if endTime != nil {
|
|
db = db.Where("created_at <= ?", endTime)
|
|
}
|
|
if req.Keyword != "" {
|
|
keyword := "%" + req.Keyword + "%"
|
|
db = db.Where("(user_nickname LIKE ? OR shop_order_id LIKE ? OR prize_name LIKE ?)", keyword, keyword, keyword)
|
|
}
|
|
|
|
var total int64
|
|
db.Count(&total)
|
|
|
|
var logs []model.LivestreamDrawLogs
|
|
if err := db.Order("id DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&logs).Error; err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
res := &listLivestreamDrawLogsResponse{
|
|
List: make([]livestreamDrawLogResponse, len(logs)),
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
}
|
|
|
|
for i, log := range logs {
|
|
res.List[i] = livestreamDrawLogResponse{
|
|
ID: log.ID,
|
|
ActivityID: log.ActivityID,
|
|
PrizeID: log.PrizeID,
|
|
PrizeName: log.PrizeName,
|
|
Level: log.Level,
|
|
DouyinOrderID: log.DouyinOrderID,
|
|
ShopOrderID: log.ShopOrderID,
|
|
LocalUserID: log.LocalUserID,
|
|
DouyinUserID: log.DouyinUserID,
|
|
UserNickname: log.UserNickname,
|
|
SeedHash: log.SeedHash,
|
|
CreatedAt: log.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
}
|
|
}
|
|
|
|
ctx.Payload(res)
|
|
}
|
|
}
|
|
|
|
// ========== 直播间承诺管理 ==========
|
|
|
|
type livestreamCommitmentSummaryResponse struct {
|
|
SeedVersion int32 `json:"seed_version"`
|
|
Algo string `json:"algo"`
|
|
HasSeed bool `json:"has_seed"`
|
|
LenSeed int `json:"len_seed_master"`
|
|
LenHash int `json:"len_seed_hash"`
|
|
}
|
|
|
|
// GenerateLivestreamCommitment 生成直播间活动承诺
|
|
// @Summary 生成直播间活动承诺
|
|
// @Description 为直播间活动生成可验证的承诺种子
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path integer true "活动ID"
|
|
// @Success 200 {object} map[string]int32
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{id}/commitment/generate [post]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) GenerateLivestreamCommitment() 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
|
|
}
|
|
|
|
version, err := h.livestream.GenerateCommitment(ctx.RequestContext(), id)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(map[string]int32{"seed_version": version})
|
|
}
|
|
}
|
|
|
|
// GetLivestreamCommitmentSummary 获取直播间活动承诺摘要
|
|
// @Summary 获取直播间活动承诺摘要
|
|
// @Description 获取直播间活动的承诺状态信息
|
|
// @Tags 管理端.直播间
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path integer true "活动ID"
|
|
// @Success 200 {object} livestreamCommitmentSummaryResponse
|
|
// @Failure 400 {object} code.Failure
|
|
// @Router /api/admin/livestream/activities/{id}/commitment/summary [get]
|
|
// @Security LoginVerifyToken
|
|
func (h *handler) GetLivestreamCommitmentSummary() 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
|
|
}
|
|
|
|
summary, err := h.livestream.GetCommitmentSummary(ctx.RequestContext(), id)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(&livestreamCommitmentSummaryResponse{
|
|
SeedVersion: summary.SeedVersion,
|
|
Algo: summary.Algo,
|
|
HasSeed: summary.HasSeed,
|
|
LenSeed: summary.LenSeed,
|
|
LenHash: summary.LenHash,
|
|
})
|
|
}
|
|
}
|