邀请记录
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m22s

This commit is contained in:
shanshanzhong 2026-03-08 21:57:20 -07:00
parent 79a97ec569
commit f792157d6e
6 changed files with 244 additions and 0 deletions

View File

@ -0,0 +1,26 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Get admin user invite list
func GetAdminUserInviteListHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.GetAdminUserInviteListRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewGetAdminUserInviteListLogic(c.Request.Context(), svcCtx)
resp, err := l.GetAdminUserInviteList(&req)
result.HttpResult(c, resp, err)
}
}

View File

@ -0,0 +1,26 @@
package user
import (
"github.com/gin-gonic/gin"
"github.com/perfect-panel/server/internal/logic/admin/user"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/result"
)
// Get admin user invite stats
func GetAdminUserInviteStatsHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return func(c *gin.Context) {
var req types.GetAdminUserInviteStatsRequest
_ = c.ShouldBind(&req)
validateErr := svcCtx.Validate(&req)
if validateErr != nil {
result.ParamErrorResult(c, validateErr)
return
}
l := user.NewGetAdminUserInviteStatsLogic(c.Request.Context(), svcCtx)
resp, err := l.GetAdminUserInviteStats(&req)
result.HttpResult(c, resp, err)
}
}

View File

@ -644,6 +644,12 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
// Get user subcribe traffic logs
adminUserGroupRouter.GET("/subscribe/traffic_logs", adminUser.GetUserSubscribeTrafficLogsHandler(serverCtx))
// Get admin user invite stats
adminUserGroupRouter.GET("/invite/stats", adminUser.GetAdminUserInviteStatsHandler(serverCtx))
// Get admin user invite list
adminUserGroupRouter.GET("/invite/list", adminUser.GetAdminUserInviteListHandler(serverCtx))
}
authGroupRouter := router.Group("/v1/auth")

View File

@ -0,0 +1,83 @@
package user
import (
"context"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
)
type GetAdminUserInviteListLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAdminUserInviteListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAdminUserInviteListLogic {
return &GetAdminUserInviteListLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAdminUserInviteListLogic) GetAdminUserInviteList(req *types.GetAdminUserInviteListRequest) (resp *types.GetAdminUserInviteListResponse, err error) {
if req.Page < 1 {
req.Page = 1
}
if req.Size < 1 {
req.Size = 10
}
if req.Size > 100 {
req.Size = 100
}
type InvitedUser struct {
Id int64 `gorm:"column:id"`
Avatar string `gorm:"column:avatar"`
Identifier string `gorm:"column:identifier"`
Enable bool `gorm:"column:enable"`
CreatedAt int64 `gorm:"column:created_at"`
}
var total int64
baseQuery := l.svcCtx.DB.WithContext(l.ctx).
Table("user u").
Where("u.referer_id = ? AND u.deleted_at IS NULL", req.UserId)
if err = baseQuery.Count(&total).Error; err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "count invited users failed: %v", err)
}
var rows []InvitedUser
err = l.svcCtx.DB.WithContext(l.ctx).
Table("user u").
Select("u.id, u.avatar, u.enable, UNIX_TIMESTAMP(u.created_at) as created_at, COALESCE((SELECT uam.auth_identifier FROM user_auth_methods uam WHERE uam.user_id = u.id AND uam.deleted_at IS NULL ORDER BY uam.id ASC LIMIT 1), '') as identifier").
Where("u.referer_id = ? AND u.deleted_at IS NULL", req.UserId).
Order("u.created_at DESC").
Limit(req.Size).
Offset((req.Page - 1) * req.Size).
Scan(&rows).Error
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query invited users failed: %v", err)
}
list := make([]types.AdminInvitedUser, 0, len(rows))
for _, r := range rows {
list = append(list, types.AdminInvitedUser{
Id: r.Id,
Avatar: r.Avatar,
Identifier: r.Identifier,
Enable: r.Enable,
CreatedAt: r.CreatedAt,
})
}
return &types.GetAdminUserInviteListResponse{
Total: total,
List: list,
}, nil
}

View File

@ -0,0 +1,72 @@
package user
import (
"context"
"database/sql"
"github.com/perfect-panel/server/internal/svc"
"github.com/perfect-panel/server/internal/types"
"github.com/perfect-panel/server/pkg/logger"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
)
type GetAdminUserInviteStatsLogic struct {
logger.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAdminUserInviteStatsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAdminUserInviteStatsLogic {
return &GetAdminUserInviteStatsLogic{
Logger: logger.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAdminUserInviteStatsLogic) GetAdminUserInviteStats(req *types.GetAdminUserInviteStatsRequest) (resp *types.GetAdminUserInviteStatsResponse, err error) {
userId := req.UserId
// 邀请总人数
var inviteCount int64
if err = l.svcCtx.DB.WithContext(l.ctx).
Table("user").
Where("referer_id = ? AND deleted_at IS NULL", userId).
Count(&inviteCount).Error; err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "count invite users failed: %v", err)
}
// 历史累计佣金(来自 system_logs type=33 的佣金记录)
var totalCommission sql.NullInt64
if err = l.svcCtx.DB.WithContext(l.ctx).
Table("system_logs").
Select("COALESCE(SUM(JSON_EXTRACT(content, '$.amount')), 0) as total").
Where("type = ? AND object_id = ? AND JSON_EXTRACT(content, '$.type') IN (?, ?)", 33, userId, 331, 332).
Scan(&totalCommission).Error; err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "sum commission failed: %v", err)
}
// 当前佣金余额
type UserCommission struct {
Commission int64 `gorm:"column:commission"`
ReferralPercentage uint8 `gorm:"column:referral_percentage"`
OnlyFirstPurchase bool `gorm:"column:only_first_purchase"`
}
var userInfo UserCommission
if err = l.svcCtx.DB.WithContext(l.ctx).
Table("user").
Select("commission, referral_percentage, only_first_purchase").
Where("id = ?", userId).
Scan(&userInfo).Error; err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "get user commission failed: %v", err)
}
return &types.GetAdminUserInviteStatsResponse{
InviteCount: inviteCount,
TotalCommission: totalCommission.Int64,
CurrentCommission: userInfo.Commission,
ReferralPercentage: userInfo.ReferralPercentage,
OnlyFirstPurchase: userInfo.OnlyFirstPurchase,
}, nil
}

View File

@ -3199,3 +3199,34 @@ type WithdrawalLog struct {
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
type GetAdminUserInviteStatsRequest struct {
UserId int64 `form:"user_id" validate:"required"`
}
type GetAdminUserInviteStatsResponse struct {
InviteCount int64 `json:"invite_count"`
TotalCommission int64 `json:"total_commission"`
CurrentCommission int64 `json:"current_commission"`
ReferralPercentage uint8 `json:"referral_percentage"`
OnlyFirstPurchase bool `json:"only_first_purchase"`
}
type GetAdminUserInviteListRequest struct {
UserId int64 `form:"user_id" validate:"required"`
Page int `form:"page"`
Size int `form:"size"`
}
type AdminInvitedUser struct {
Id int64 `json:"id"`
Avatar string `json:"avatar"`
Identifier string `json:"identifier"`
Enable bool `json:"enable"`
CreatedAt int64 `json:"created_at"`
}
type GetAdminUserInviteListResponse struct {
Total int64 `json:"total"`
List []AdminInvitedUser `json:"list"`
}