166 lines
4.3 KiB
Vue
166 lines
4.3 KiB
Vue
<script setup lang="ts">
|
||
definePageMeta({
|
||
layout: 'login',
|
||
})
|
||
//导入yup
|
||
import * as yup from 'yup'
|
||
import {useToast} from "vue-toastification";
|
||
import Vcode from 'vue3-puzzle-vcode';
|
||
//创建表单
|
||
const form = reactive({
|
||
password: '',
|
||
confirmPassword: ''
|
||
})
|
||
const userId = useRoute().query.id;
|
||
const isShow=ref(false);
|
||
const toast=useToast()
|
||
const schema = yup.object().shape({
|
||
password: yup.string()
|
||
.required('密码为必填项')
|
||
.min(8, '密码至少需要8个字符')
|
||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/, '密码必须包含至少一个小写字母、一个大写字母、一个数字和一个特殊字符(如 @$!%*?&)')
|
||
.test('no-chinese', '密码不能包含中文字符', (value) => {
|
||
if (!value) return true; // 如果密码为空,不进行此测试
|
||
return !/[\u4e00-\u9fa5]/.test(value);
|
||
}),
|
||
confirmPassword: yup.string()
|
||
.required('确认密码为必填项')
|
||
.oneOf([yup.ref('password')], '两次输入的密码不一致')
|
||
.min(8, '确认密码至少需要8个字符')
|
||
.test('no-chinese', '确认密码不能包含中文字符', (value) => {
|
||
if (!value) return true; // 如果确认密码为空,不进行此测试
|
||
return !/[\u4e00-\u9fa5]/.test(value);
|
||
})
|
||
});
|
||
//表单提交事件
|
||
const handleSubmit = async () => {
|
||
try {
|
||
await schema.validate(form,{abortEarly: false})
|
||
// 表单验证通过,处理登录逻辑
|
||
isShow.value = true;
|
||
} catch (error:any) {
|
||
//收集每个错误
|
||
error.inner.forEach((e: any) => {
|
||
toast.error(e.message)
|
||
})
|
||
}
|
||
}
|
||
const onSuccess=()=>{
|
||
$fetch('/Api/Account/ChangePassword', {
|
||
method: 'GET',
|
||
params:{
|
||
userId:userId,
|
||
NewPassword:form.password,
|
||
token:useCookie('tokenPassword').value??""
|
||
},
|
||
baseURL: useRuntimeConfig().public.baseUrl,
|
||
}).then((res) => {
|
||
//清除临时token
|
||
useCookie('tokenPassword').value = ""
|
||
toast.success(res)
|
||
setTimeout(()=>{
|
||
navigateTo("/SignIn")
|
||
},2000)
|
||
}).finally(()=>{
|
||
isShow.value=false
|
||
}).catch(err=>{
|
||
toast.error(err.response._data)
|
||
})
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="change-password-layout">
|
||
<Vcode :show="isShow" @success="onSuccess"/>
|
||
<NuxtLink href="/signIn">< 返回</NuxtLink>
|
||
<div class="info" v-if="userId">
|
||
<h1>修改你的密码 👍</h1>
|
||
<h2>当前账号密码已过期,请重新设置以继续登录</h2>
|
||
</div >
|
||
<form class="form-box" @submit.prevent="handleSubmit" v-if="userId">
|
||
<div class="form-item">
|
||
<label>新的密码</label>
|
||
<input placeholder="最少8位" required type="password" minlength="8" v-model="form.password">
|
||
</div>
|
||
<div class="form-item">
|
||
<label>确认密码</label>
|
||
<input placeholder="最少8位" required type="password" minlength="8" v-model="form.confirmPassword">
|
||
</div>
|
||
<button type="submit">提交</button>
|
||
</form>
|
||
<h1 v-else>!错误的请求</h1>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
@import "../base";
|
||
.change-password-layout{
|
||
display: grid;
|
||
grid-template-rows: repeat(3,auto);
|
||
gap: 48px;
|
||
*{
|
||
@include SC_Font
|
||
}
|
||
}
|
||
.info{
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 28px;
|
||
h1{
|
||
color: #0C1421;
|
||
text-align: center;
|
||
font-size: 36px;
|
||
font-style: normal;
|
||
font-weight: 800;
|
||
line-height: 100%; /* 36px */
|
||
letter-spacing: 0.36px;
|
||
}
|
||
h2{
|
||
color: #313957;
|
||
font-size: 20px;
|
||
font-style: normal;
|
||
font-weight: 400;
|
||
line-height: 160%; /* 32px */
|
||
letter-spacing: 0.2px;
|
||
}
|
||
}
|
||
.form-box{
|
||
display: flex;
|
||
gap: 24px;
|
||
flex-direction: column;
|
||
.form-item{
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
label{
|
||
color: #0C1421;
|
||
font-feature-settings: 'clig' off, 'liga' off;
|
||
font-size: 16px;
|
||
font-style: normal;
|
||
font-weight: 400;
|
||
line-height: 100%; /* 16px */
|
||
letter-spacing: 0.16px;
|
||
}
|
||
input{
|
||
padding: 16px;
|
||
border-radius: 12px;
|
||
border: 1px solid #D4D7E3;
|
||
background: #F7FBFF;
|
||
}
|
||
}
|
||
button{
|
||
display: flex;
|
||
padding: 16px 0;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: 12px;
|
||
background: #162D3A;
|
||
color: #FFF;
|
||
text-align: center;
|
||
font-size: 20px;
|
||
font-weight: 400;
|
||
line-height: 100%; /* 20px */
|
||
letter-spacing: 2px;
|
||
}
|
||
}
|
||
</style> |