| 
									
										
										
										
											2025-09-21 18:27:25 +08:00
										 |  |  |  | package admin_promotion | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"context" | 
					
						
							|  |  |  |  | 	"crypto/rand" | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"math/big" | 
					
						
							|  |  |  |  | 	"time" | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-30 17:44:18 +08:00
										 |  |  |  | 	"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" | 
					
						
							| 
									
										
										
										
											2025-09-21 18:27:25 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"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 | 
					
						
							|  |  |  |  | } |