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