package user import ( "context" "errors" "fmt" "github.com/saas-mingyang/mingyang-admin-common/utils/sonyflake" "github.com/saas-mingyang/mingyang-admin-common/utils/uuidx" "github.com/zeromicro/go-zero/core/logx" "mingyang-admin-app-rpc/ent" "mingyang-admin-app-rpc/ent/user" "mingyang-admin-app-rpc/internal/svc" "mingyang-admin-app-rpc/types/app" "time" ) type User struct { client *ent.Client svcCtx *svc.ServiceContext logx.Logger } func NewUser(ctx context.Context, svcCtx *svc.ServiceContext) *User { return &User{ client: svcCtx.DB, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } // CreateUser 创建用户 func (u *User) CreateUser(ctx context.Context, req *CreateUserData) (*app.UserInfo, error) { tx, err := u.client.Tx(ctx) if err != nil { return nil, fmt.Errorf("starting transaction: %w", err) } defer func() { if err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { err = fmt.Errorf("%w, rollback error: %v", err, rollbackErr) } } }() // 1. 检查用户名、邮箱、手机号是否已存在 exists, err := tx.User.Query(). Where( user.Or( user.UsernameEQ(req.Username), user.EmailEQ(req.Email), user.MobileEQ(req.Mobile), ), ).Exist(ctx) if err != nil { fmt.Printf("error: %v", err) return nil, fmt.Errorf("checking existing user: %w", err) } if exists { return nil, errors.New("username, email or phone already exists") } // 2. 创建用户 userObj, err := tx.User. Create(). SetID(sonyflake.NextID()). SetUsername(req.Username). SetEmail(req.Email). SetMobile(req.Mobile). SetGender(req.Gender). SetSalt(uuidx.NewUUID().String()). SetPasswordHash(req.PasswordHash). SetNickname(req.Nickname). SetRegistrationSource(req.RegistrationSource). SetMetadata(req.Metadata). Save(ctx) if err != nil { fmt.Printf("error: %v", err) return nil, fmt.Errorf("creating user: %w", err) } // 4. 提交事务 if err := tx.Commit(); err != nil { return nil, fmt.Errorf("committing transaction: %w", err) } gender := userObj.Gender.String() accountStatus := userObj.AccountStatus.String() return &app.UserInfo{ Id: &userObj.ID, Username: &userObj.Username, Email: &userObj.Email, Nickname: &userObj.Nickname, Avatar: userObj.Avatar, PasswordHash: &userObj.PasswordHash, Salt: &userObj.Salt, Mobile: userObj.Mobile, Gender: &gender, AccountStatus: &accountStatus, IsVerified: &userObj.IsVerified, RegistrationSource: &userObj.RegistrationSource, }, nil } type CreateUserData struct { UserId *uint64 Username string Email string Mobile string PasswordHash string Nickname string Gender user.Gender RegistrationSource string Metadata map[string]interface{} ThirdPartyAuth *ThirdPartyAuthData } type ThirdPartyAuthData struct { UserID uint64 Openid string Unionid string AccessToken *string RefreshToken *string AccessTokenExpiry *time.Time UserInfo map[string]interface{} }