137 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package admin_promotion
 | ||
| 
 | ||
| import (
 | ||
| 	"context"
 | ||
| 	"crypto/rand"
 | ||
| 	"fmt"
 | ||
| 	"math/big"
 | ||
| 	"time"
 | ||
| 
 | ||
| 	"hm-server/app/main/api/internal/svc"
 | ||
| 	"hm-server/app/main/api/internal/types"
 | ||
| 	"hm-server/app/main/model"
 | ||
| 	"hm-server/common/ctxdata"
 | ||
| 	"hm-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
 | ||
| }
 |