137 lines
3.8 KiB
Go
137 lines
3.8 KiB
Go
package admin_promotion
|
||
|
||
import (
|
||
"context"
|
||
"crypto/rand"
|
||
"fmt"
|
||
"math/big"
|
||
"time"
|
||
|
||
"qnc-server/app/main/api/internal/svc"
|
||
"qnc-server/app/main/api/internal/types"
|
||
"qnc-server/app/main/model"
|
||
"qnc-server/common/ctxdata"
|
||
"qnc-server/common/xerr"
|
||
|
||
"github.com/pkg/errors"
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||
)
|
||
|
||
type CreatePromotionLinkLogic struct {
|
||
logx.Logger
|
||
ctx context.Context
|
||
svcCtx *svc.ServiceContext
|
||
}
|
||
|
||
func NewCreatePromotionLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreatePromotionLinkLogic {
|
||
return &CreatePromotionLinkLogic{
|
||
Logger: logx.WithContext(ctx),
|
||
ctx: ctx,
|
||
svcCtx: svcCtx,
|
||
}
|
||
}
|
||
|
||
// 生成6位随机字符串(大小写字母和数字)
|
||
func generateRandomString() (string, error) {
|
||
const (
|
||
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||
length = 6
|
||
)
|
||
|
||
result := make([]byte, length)
|
||
for i := 0; i < length; i++ {
|
||
num, err := rand.Int(rand.Reader, big.NewInt(int64(len(chars))))
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
result[i] = chars[num.Int64()]
|
||
}
|
||
return string(result), nil
|
||
}
|
||
|
||
func (l *CreatePromotionLinkLogic) CreatePromotionLink(req *types.CreatePromotionLinkReq) (resp *types.CreatePromotionLinkResp, err error) {
|
||
// 获取当前用户ID
|
||
adminUserId, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
|
||
if getUidErr != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建推广链接, 获取用户信息失败, %+v", getUidErr)
|
||
}
|
||
|
||
// 生成唯一URL
|
||
var url string
|
||
maxRetries := 5 // 最大重试次数
|
||
for i := 0; i < maxRetries; i++ {
|
||
// 生成6位随机字符串
|
||
randomStr, err := generateRandomString()
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建推广链接, 生成随机字符串失败, %+v", err)
|
||
}
|
||
|
||
// 检查URL是否已存在
|
||
existLink, err := l.svcCtx.AdminPromotionLinkModel.FindOneByUrl(l.ctx, randomStr)
|
||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建推广链接, 检查URL是否存在失败, %+v", err)
|
||
}
|
||
|
||
if existLink != nil {
|
||
continue // URL已存在,继续尝试
|
||
}
|
||
|
||
// URL可用
|
||
url = randomStr
|
||
break
|
||
}
|
||
|
||
if url == "" {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建推广链接失败, 多次尝试生成唯一URL均失败")
|
||
}
|
||
url = fmt.Sprintf("%s/%s", l.svcCtx.Config.AdminPromotion.URLDomain, url)
|
||
// 创建推广链接
|
||
link := &model.AdminPromotionLink{
|
||
Name: req.Name,
|
||
Url: url,
|
||
AdminUserId: adminUserId,
|
||
}
|
||
|
||
var linkId int64
|
||
err = l.svcCtx.AdminPromotionLinkModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||
result, err := l.svcCtx.AdminPromotionLinkModel.Insert(l.ctx, session, link)
|
||
if err != nil {
|
||
return fmt.Errorf("创建推广链接失败, %+v", err)
|
||
}
|
||
|
||
linkId, err = result.LastInsertId()
|
||
if err != nil {
|
||
return fmt.Errorf("获取推广链接ID失败, %+v", err)
|
||
}
|
||
|
||
// 创建总统计记录
|
||
totalStats := &model.AdminPromotionLinkStatsTotal{
|
||
LinkId: linkId,
|
||
}
|
||
_, err = l.svcCtx.AdminPromotionLinkStatsTotalModel.Insert(l.ctx, session, totalStats)
|
||
if err != nil {
|
||
return fmt.Errorf("创建推广链接总统计记录失败, %+v", err)
|
||
}
|
||
|
||
// 创建统计历史记录
|
||
historyStats := &model.AdminPromotionLinkStatsHistory{
|
||
LinkId: linkId,
|
||
StatsDate: time.Now().Truncate(24 * time.Hour),
|
||
}
|
||
_, err = l.svcCtx.AdminPromotionLinkStatsHistoryModel.Insert(l.ctx, session, historyStats)
|
||
if err != nil {
|
||
return fmt.Errorf("创建推广链接统计历史记录失败, %+v", err)
|
||
}
|
||
return nil
|
||
})
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建推广链接失败, %+v", err)
|
||
}
|
||
|
||
return &types.CreatePromotionLinkResp{
|
||
Id: linkId,
|
||
Url: url,
|
||
}, nil
|
||
}
|