diff --git a/internal/logic/tenant/email.go b/internal/logic/tenant/email.go index 887e7c0..01a42a1 100644 --- a/internal/logic/tenant/email.go +++ b/internal/logic/tenant/email.go @@ -128,6 +128,11 @@ func (s *sTenant) ChangeEmail(ctx context.Context, req *v1.TenantChangeEmailReq) userID := middleware.GetUserID(ctx) newEmail := strings.TrimSpace(strings.ToLower(req.NewEmail)) + // Reject no-op: block if the new email equals the user's current email. + if err := rejectSameEmail(ctx, userID, newEmail); err != nil { + return nil, err + } + // Verify code for new email err := common.VerifyCode(ctx, newEmail, req.Code, "change_email") if err != nil { @@ -209,6 +214,11 @@ func (s *sTenant) SendChangeEmailCode(ctx context.Context, req *v1.TenantSendCha userID := middleware.GetUserID(ctx) newEmail := strings.TrimSpace(strings.ToLower(req.NewEmail)) + // Reject no-op: block if the new email equals the user's current email. + if err := rejectSameEmail(ctx, userID, newEmail); err != nil { + return nil, err + } + // Pre-check: reject early if the email is already used by another member in this tenant. count, err := dao.TntUsers.Ctx(ctx). Where("tenant_id", tenantID). @@ -227,3 +237,25 @@ func (s *sTenant) SendChangeEmailCode(ctx context.Context, req *v1.TenantSendCha } return nil, nil } + +// rejectSameEmail blocks a no-op email change: if newEmail equals the user's +// current email there's nothing to do, so refuse before sending a code (and a +// pointless notification email) or performing an identical update. A user with +// no email yet (NULL/empty) may still set any valid address. +func rejectSameEmail(ctx context.Context, userID int64, newEmail string) error { + if newEmail == "" { + return nil + } + var me struct { + Email string `json:"email"` + } + if err := dao.TntUsers.Ctx(ctx).Where("id", userID).Fields("email").Scan(&me); err != nil { + if err = common.IgnoreScanNoRows(err); err != nil { + return err + } + } + if me.Email != "" && me.Email == newEmail { + return common.NewBadRequestError("新邮箱与当前邮箱一致,无需修改") + } + return nil +} diff --git a/web/tenant/src/utils/request.ts b/web/tenant/src/utils/request.ts index f220baa..1a313cd 100644 --- a/web/tenant/src/utils/request.ts +++ b/web/tenant/src/utils/request.ts @@ -16,7 +16,7 @@ interface ApiError { /** Request config extension — set _suppressErrorMsg to skip auto error toast */ declare module 'axios' { - interface InternalAxiosRequestConfig { + interface AxiosRequestConfig { _suppressErrorMsg?: boolean } } diff --git a/web/tenant/src/views/settings/ProfilePage.vue b/web/tenant/src/views/settings/ProfilePage.vue index f713980..e9053b7 100644 --- a/web/tenant/src/views/settings/ProfilePage.vue +++ b/web/tenant/src/views/settings/ProfilePage.vue @@ -161,7 +161,7 @@ async function sendEmailCode() { try { await request.post('/tenant/email/send-change-email-code', { new_email: emailForm.new_email, - }) + }, { _suppressErrorMsg: true }) emailCooldown.value = 60 emailCooldownTimer = setInterval(() => { emailCooldown.value-- @@ -171,7 +171,7 @@ async function sendEmailCode() { } }, 1000) } catch (e: any) { - emailError.value = e?.response?.data?.message || '验证码发送失败' + emailError.value = e?.message || '验证码发送失败' } finally { emailSending.value = false } @@ -192,7 +192,7 @@ async function handleChangeEmail() { await request.post('/tenant/email/change-email', { new_email: emailForm.new_email, code: emailForm.code, - }) + }, { _suppressErrorMsg: true }) if (userInfo.value) { userInfo.value.email = emailForm.new_email } @@ -202,7 +202,7 @@ async function handleChangeEmail() { emailCooldownTimer = null } } catch (e: any) { - emailError.value = e?.response?.data?.message || '设置失败' + emailError.value = e?.message || '设置失败' } finally { emailSaving.value = false }