feat: 完成忘记密码相关功能

This commit is contained in:
fanpeng 2025-06-06 13:50:48 +08:00
parent 308e5ddf08
commit 8b542a4d9c
4 changed files with 251 additions and 7 deletions

View File

@ -68,7 +68,7 @@ export function loginRequest(data) {
// 密码登录
export function passwordLoginRequest(data) {
return request({
url: '/user/register',
url: '/user/login',
method: 'POST',
data
})
@ -83,6 +83,15 @@ export function registerRequest(data) {
})
}
// 重置密码
export function resetPasswordRequest(data) {
return request({
url: '/user/resetPassword',
method: 'POST',
data
})
}
// 注册
export function phoneLoginRequest(data) {
return request({

View File

@ -1,5 +1,239 @@
<template>
<view>忘记密码</view>
<view>
<view class="mx-6 mt-10">
<view class="mt-4 flex items-center w-full" @click="toJump('countryList')">
<view class="w-200">国家/地区</view>
<view class="text-#63b8af">
{{ country.name }}
+{{ country.code }}
</view>
</view>
<view class="mt-4">
<up-input
placeholder="请输入手机号或邮箱"
fontSize="32rpx"
:placeholderStyle="{
color: '#333333',
fontSize: '32rpx'
}"
:customStyle="{
padding: '0',
height: '80rpx'
}"
border="bottom"
clearable
v-model="username"
:maxlength="50"
@change="handleUsernameInput"
></up-input>
</view>
<view class="mt-4">
<up-input
fontSize="32rpx"
:placeholderStyle="{
color: '#333333',
fontSize: '32rpx'
}"
:customStyle="{
padding: '0',
height: '80rpx'
}"
placeholder="请输入密码"
type="password"
border="bottom"
clearable
v-model="password"
:maxlength="20"
@change="handlePasswordInput"
></up-input>
<view class="text-#999999 text-sm mt-1">
密码必须是8-20至少包括数字/字母/符号中的2种
</view>
</view>
<view class="mt-4">
<up-input
fontSize="32rpx"
:placeholderStyle="{
color: '#333333',
fontSize: '32rpx'
}"
:customStyle="{
padding: '0',
height: '80rpx'
}"
placeholder="确认密码"
type="password"
border="bottom"
clearable
v-model="confirmPassword"
:maxlength="20"
@change="handleConfirmPasswordInput"
></up-input>
</view>
<view class="mt-4 flex items-center">
<up-input
fontSize="32rpx"
:placeholderStyle="{
color: '#333333',
fontSize: '32rpx'
}"
:customStyle="{
padding: '0',
height: '80rpx'
}"
placeholder="请输入验证码"
type="number"
border="bottom"
clearable
v-model="code"
:maxlength="20"
@change="handleCodeInput"
>
<template #suffix>
<up-button @tap="getCode" :disabled="!canGetCode" color="#63b8af">
{{ tips }}
</up-button>
<up-code
:seconds="seconds"
ref="uCodeRef"
changeText="X秒后重新获取"
endText="获取验证码"
@change="codeChange"
></up-code
></template>
</up-input>
</view>
<view
class="w-full rounded-full h-88 text-center leading-[88rpx] text-white mt-6"
:class="[canResetPassword ? 'bg-#63b8af' : 'bg-#9d9da1']"
@click="register"
>
重置密码
</view>
</view>
</view>
</template>
<script setup></script>
<script setup>
import { ref, computed } from 'vue'
import { useBasicStore } from '@/stores/basic'
import { PHONE_REG, EMAIL_REG, PASSWORD_REG } from '@/constant/reg'
import { resetPasswordRequest } from '@/api/user'
const $basic = useBasicStore()
const username = ref('')
const password = ref('')
const confirmPassword = ref('')
const code = ref('')
const tips = ref('')
const seconds = ref(120)
const uCodeRef = ref(null)
const codeChange = text => {
tips.value = text
}
const getCode = () => {
if (!uCodeRef.value.canGetCode) {
return
}
const params = {
account: username.value,
codeType: 2,
countryCode: country.value.code
}
$basic.routeJump({
name: 'safeVerify',
events: {
successEvent() {
uCodeRef.value.start()
}
},
params
})
}
const country = ref({
countryId: 0,
name: '中国',
code: '86',
flag: 'https://lock.xhjcn.ltd/storage/country-flags/86.png',
abbreviation: 'CN',
group: 'Z'
})
const isValidUsername = computed(() => {
if (!username.value) return false
return EMAIL_REG.test(username.value) || PHONE_REG.test(username.value)
})
const isValidPassword = computed(() => {
if (!password.value) return false
return PASSWORD_REG.test(password.value)
})
const isValidConfirmPassword = computed(() => {
if (!confirmPassword.value) return false
return confirmPassword.value === password.value
})
const isValidCode = computed(() => {
if (!code.value) return false
return code.value.length === 6
})
const canGetCode = computed(() => {
return isValidUsername.value
})
const canResetPassword = computed(() => {
return (
isValidUsername.value &&
isValidPassword.value &&
isValidConfirmPassword.value &&
isValidCode.value
)
})
const register = async () => {
if (!canResetPassword.value) {
return
}
const res = await resetPasswordRequest({
account: username.value,
newPassword: password.value,
countryCode: country.value.code,
verificationCode: code.value
})
if (res) {
$basic.backAndToast('密码重置成功')
}
}
const handleUsernameInput = text => {
username.value = text
}
const handlePasswordInput = text => {
password.value = text
}
const handleConfirmPasswordInput = text => {
confirmPassword.value = text
}
const handleCodeInput = text => {
code.value = text
}
const toJump = path => {
$basic.routeJump({
name: path,
events: {
country(data) {
country.value = data
}
}
})
}
</script>

View File

@ -51,7 +51,7 @@
padding: '0',
height: '80rpx'
}"
placeholder="请输入内容"
placeholder="请输入密码"
type="password"
border="bottom"
clearable
@ -95,7 +95,7 @@
height: '80rpx'
}"
placeholder="请输入验证码"
type="password"
type="number"
border="bottom"
clearable
v-model="code"

View File

@ -7,7 +7,8 @@ import {
getWebUrlRequest,
loginRequest,
phoneLoginRequest,
registerRequest
registerRequest,
passwordLoginRequest
} from '@/api/user'
import { useLockStore } from '@/stores/lock'
import { setStorage, getStorage } from '@/utils/storage'
@ -82,7 +83,7 @@ export const useUserStore = defineStore('user', {
model: deviceInfo.model,
system: deviceInfo.system
}
const { code, data, message } = await registerRequest({
const { code, data, message } = await passwordLoginRequest({
username,
password,
countryCode,