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