package logic import ( "context" "strconv" "time" "lone-services/pkg/modelbase" "lone-services/pkg/utils" "lone-services/pkg/validate" user "lone-services/rpc/user/pb" "lone-services/services/user/internal/dao" "lone-services/services/user/internal/model" "lone-services/services/user/internal/svc" "lone-services/services/user/validator" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" ) type UpdateLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewUpdateLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateLogic { return &UpdateLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } func (l *UpdateLogic) Update(in *user.UpdateReq) (*user.Response, error) { var req validator.UpdateValidator if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { return outResponse(utils.ErrorParams, msg), nil } if req.Birthday != utils.StringEmpty { if _, err := time.ParseInLocation("2006-01-02", req.Birthday, time.Local); err != nil { return outResponse(utils.ErrorParams, "生日格式不正确"), nil } } loginUser := utils.GetUserFromCtx(l.ctx) if loginUser.ID < utils.NumberOne { return failResponse(utils.ErrorNoLoginInfo), nil } row, err := loadEnabledUser(loginUser.ID) if err != nil { l.Errorf("update load user: %v", err) return failResponse(utils.ErrorNotFund), nil } userUpdates := map[string]interface{}{} if req.Name != utils.StringEmpty { userUpdates["name"] = req.Name } if req.Avatar != utils.StringEmpty { userUpdates["avatar"] = req.Avatar } if req.Gender > utils.NumberZero { userUpdates["gender"] = uint8(req.Gender) } if req.Birthday != utils.StringEmpty { userUpdates["birthday"] = req.Birthday } if req.Mobile != utils.StringEmpty { enc, encErr := utils.EncryptPhone(req.Mobile) if encErr != nil { l.Errorf("update encrypt mobile: %v", encErr) return failResponse(utils.ErrorEncryptAesError), nil } if enc != row.Mobile { occupied, occErr := findUserByMobile(enc) if occErr != nil { l.Errorf("update mobile unique: %v", occErr) return failResponse(utils.Fail), nil } if occupied != nil && occupied.Id != row.Id { return failResponse(utils.ErrorDataIsExist), nil } userUpdates["mobile"] = enc } } detailUpdates := map[string]interface{}{} if req.RealName != utils.StringEmpty { detailUpdates["real_name"] = req.RealName } if len(userUpdates) == utils.NumberZero && len(detailUpdates) == utils.NumberZero { return outResponse(utils.ErrorParams, "没有需要更新的字段"), nil } txErr := l.svcCtx.DB.WithContext(l.ctx).Transaction(func(tx *gorm.DB) error { if len(userUpdates) > utils.NumberZero { userModel := model.UserModel{}.Init() userModel.Base = userModel.Base.WithTX(tx) if _, err := userModel.Edit(modelbase.Params{ Eq: map[string]string{"id": strconv.FormatInt(row.Id, utils.NumberTen)}, }, userUpdates); err != nil { return err } } if err := ensureUserDetail(tx, row.Id); err != nil { return err } if len(detailUpdates) > utils.NumberZero { detailModel := model.UserDetailModel{}.Init() detailModel.Base = detailModel.Base.WithTX(tx) if _, err := detailModel.Edit(modelbase.Params{ Eq: map[string]string{"user_id": strconv.FormatInt(row.Id, utils.NumberTen)}, }, detailUpdates); err != nil { return err } } return nil }) if txErr != nil { l.Errorf("update tx: %v", txErr) return failResponse(utils.Fail), nil } return okResponse(nil), nil } func findUserByMobile(encryptMobile string) (*dao.UserRow, error) { var row dao.UserRow err := model.UserModel{}.Init().GetOne(modelbase.Params{ Eq: map[string]string{"mobile": encryptMobile}, }, &row) if err != nil { return nil, err } if row.Id < utils.NumberOne { return nil, nil } return &row, nil }