bindbox-game/internal/api/admin/blacklist_admin.go

320 lines
9.1 KiB
Go
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package admin
import (
"net/http"
"strconv"
"bindbox-game/internal/code"
"bindbox-game/internal/pkg/core"
"bindbox-game/internal/pkg/validation"
"bindbox-game/internal/repository/mysql/model"
)
// ========== 黑名单管理 ==========
type addBlacklistRequest struct {
DouyinUserID string `json:"douyin_user_id" binding:"required"`
Reason string `json:"reason"`
}
type blacklistResponse struct {
ID int64 `json:"id"`
DouyinUserID string `json:"douyin_user_id"`
Reason string `json:"reason"`
OperatorID int64 `json:"operator_id"`
Status int32 `json:"status"`
CreatedAt string `json:"created_at"`
}
type listBlacklistRequest struct {
Page int `form:"page"`
PageSize int `form:"page_size"`
Keyword string `form:"keyword"`
}
type listBlacklistResponse struct {
List []blacklistResponse `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
// ListBlacklist 获取黑名单列表
// @Summary 获取黑名单列表
// @Description 获取抖音用户黑名单列表,支持分页和关键词搜索
// @Tags 管理端.黑名单
// @Accept json
// @Produce json
// @Param page query int false "页码" default(1)
// @Param page_size query int false "每页数量" default(20)
// @Param keyword query string false "搜索关键词(抖音ID)"
// @Success 200 {object} listBlacklistResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/blacklist [get]
// @Security LoginVerifyToken
func (h *handler) ListBlacklist() core.HandlerFunc {
return func(ctx core.Context) {
req := new(listBlacklistRequest)
if err := ctx.ShouldBindQuery(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
}
db := h.repo.GetDbR().WithContext(ctx.RequestContext()).
Table("douyin_blacklist").
Where("status = 1")
if req.Keyword != "" {
db = db.Where("douyin_user_id LIKE ?", "%"+req.Keyword+"%")
}
var total int64
if err := db.Count(&total).Error; err != nil {
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
return
}
var list []model.DouyinBlacklist
if err := db.Order("id DESC").
Offset((req.Page - 1) * req.PageSize).
Limit(req.PageSize).
Find(&list).Error; err != nil {
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
return
}
rsp := &listBlacklistResponse{
List: make([]blacklistResponse, len(list)),
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}
for i, item := range list {
rsp.List[i] = blacklistResponse{
ID: item.ID,
DouyinUserID: item.DouyinUserID,
Reason: item.Reason,
OperatorID: item.OperatorID,
Status: item.Status,
CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"),
}
}
ctx.Payload(rsp)
}
}
// AddBlacklist 添加黑名单
// @Summary 添加黑名单
// @Description 将抖音用户添加到黑名单
// @Tags 管理端.黑名单
// @Accept json
// @Produce json
// @Param body body addBlacklistRequest true "请求参数"
// @Success 200 {object} blacklistResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/blacklist [post]
// @Security LoginVerifyToken
func (h *handler) AddBlacklist() core.HandlerFunc {
return func(ctx core.Context) {
req := new(addBlacklistRequest)
if err := ctx.ShouldBindJSON(req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
// 检查是否已在黑名单
var existCount int64
h.repo.GetDbR().WithContext(ctx.RequestContext()).
Table("douyin_blacklist").
Where("douyin_user_id = ? AND status = 1", req.DouyinUserID).
Count(&existCount)
if existCount > 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "该用户已在黑名单中"))
return
}
operatorID := int64(0)
if ctx.SessionUserInfo().Id > 0 {
operatorID = int64(ctx.SessionUserInfo().Id)
}
blacklist := &model.DouyinBlacklist{
DouyinUserID: req.DouyinUserID,
Reason: req.Reason,
OperatorID: operatorID,
Status: 1,
}
if err := h.repo.GetDbW().WithContext(ctx.RequestContext()).Create(blacklist).Error; err != nil {
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
return
}
ctx.Payload(&blacklistResponse{
ID: blacklist.ID,
DouyinUserID: blacklist.DouyinUserID,
Reason: blacklist.Reason,
OperatorID: blacklist.OperatorID,
Status: blacklist.Status,
CreatedAt: blacklist.CreatedAt.Format("2006-01-02 15:04:05"),
})
}
}
// RemoveBlacklist 移除黑名单
// @Summary 移除黑名单
// @Description 将用户从黑名单中移除软删除status设为0
// @Tags 管理端.黑名单
// @Accept json
// @Produce json
// @Param id path integer true "黑名单ID"
// @Success 200 {object} simpleMessageResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/blacklist/{id} [delete]
// @Security LoginVerifyToken
func (h *handler) RemoveBlacklist() core.HandlerFunc {
return func(ctx core.Context) {
idStr := ctx.Param("id")
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "无效的ID"))
return
}
result := h.repo.GetDbW().WithContext(ctx.RequestContext()).
Table("douyin_blacklist").
Where("id = ?", id).
Update("status", 0)
if result.Error != nil {
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, result.Error.Error()))
return
}
if result.RowsAffected == 0 {
ctx.AbortWithError(core.Error(http.StatusNotFound, code.ParamBindError, "黑名单记录不存在"))
return
}
ctx.Payload(&simpleMessageResponse{Message: "移除成功"})
}
}
// CheckBlacklist 检查用户是否在黑名单
// @Summary 检查黑名单状态
// @Description 检查指定抖音用户是否在黑名单中
// @Tags 管理端.黑名单
// @Accept json
// @Produce json
// @Param douyin_user_id query string true "抖音用户ID"
// @Success 200 {object} map[string]bool
// @Failure 400 {object} code.Failure
// @Router /api/admin/blacklist/check [get]
// @Security LoginVerifyToken
func (h *handler) CheckBlacklist() core.HandlerFunc {
return func(ctx core.Context) {
douyinUserID := ctx.RequestInputParams().Get("douyin_user_id")
if douyinUserID == "" {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "抖音用户ID不能为空"))
return
}
var count int64
h.repo.GetDbR().WithContext(ctx.RequestContext()).
Table("douyin_blacklist").
Where("douyin_user_id = ? AND status = 1", douyinUserID).
Count(&count)
ctx.Payload(map[string]any{
"douyin_user_id": douyinUserID,
"is_blacklisted": count > 0,
})
}
}
// BatchAddBlacklist 批量添加黑名单
// @Summary 批量添加黑名单
// @Description 批量将抖音用户添加到黑名单
// @Tags 管理端.黑名单
// @Accept json
// @Produce json
// @Param body body batchAddBlacklistRequest true "请求参数"
// @Success 200 {object} batchAddBlacklistResponse
// @Failure 400 {object} code.Failure
// @Router /api/admin/blacklist/batch [post]
// @Security LoginVerifyToken
func (h *handler) BatchAddBlacklist() core.HandlerFunc {
return func(ctx core.Context) {
var req struct {
DouyinUserIDs []string `json:"douyin_user_ids" binding:"required"`
Reason string `json:"reason"`
}
if err := ctx.ShouldBindJSON(&req); err != nil {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
return
}
if len(req.DouyinUserIDs) == 0 {
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "抖音用户ID列表不能为空"))
return
}
// 获取操作人ID
operatorID := int64(0)
if ctx.SessionUserInfo().Id > 0 {
operatorID = int64(ctx.SessionUserInfo().Id)
}
// 查询已存在的黑名单
var existingIDs []string
h.repo.GetDbR().WithContext(ctx.RequestContext()).
Table("douyin_blacklist").
Where("douyin_user_id IN ? AND status = 1", req.DouyinUserIDs).
Pluck("douyin_user_id", &existingIDs)
existMap := make(map[string]bool)
for _, id := range existingIDs {
existMap[id] = true
}
// 过滤出需要新增的
var toAdd []model.DouyinBlacklist
for _, uid := range req.DouyinUserIDs {
if !existMap[uid] {
toAdd = append(toAdd, model.DouyinBlacklist{
DouyinUserID: uid,
Reason: req.Reason,
OperatorID: operatorID,
Status: 1,
})
}
}
addedCount := 0
if len(toAdd) > 0 {
if err := h.repo.GetDbW().WithContext(ctx.RequestContext()).Create(&toAdd).Error; err != nil {
ctx.AbortWithError(core.Error(http.StatusInternalServerError, code.ServerError, err.Error()))
return
}
addedCount = len(toAdd)
}
ctx.Payload(map[string]any{
"total_requested": len(req.DouyinUserIDs),
"added": addedCount,
"skipped": len(req.DouyinUserIDs) - addedCount,
})
}
}