2024-07-02 14:28:15 +08:00
|
|
|
|
<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: ''
|
|
|
|
|
})
|
2024-07-02 16:08:07 +08:00
|
|
|
|
const userId = useRoute().query.id;
|
2024-07-02 14:28:15 +08:00
|
|
|
|
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:{
|
2024-07-02 16:08:07 +08:00
|
|
|
|
userId:userId,
|
2024-07-02 14:28:15 +08:00
|
|
|
|
NewPassword:form.password,
|
2024-07-02 16:08:07 +08:00
|
|
|
|
token:useCookie('tokenPassword').value??""
|
2024-07-02 14:28:15 +08:00
|
|
|
|
},
|
|
|
|
|
baseURL: useRuntimeConfig().public.baseUrl,
|
|
|
|
|
}).then((res) => {
|
|
|
|
|
//清除临时token
|
2024-07-02 16:08:07 +08:00
|
|
|
|
useCookie('tokenPassword').value = ""
|
2024-07-02 14:28:15 +08:00
|
|
|
|
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>
|
2024-07-02 16:08:07 +08:00
|
|
|
|
<div class="info" v-if="userId">
|
2024-07-02 14:28:15 +08:00
|
|
|
|
<h1>修改你的密码 👍</h1>
|
|
|
|
|
<h2>当前账号密码已过期,请重新设置以继续登录</h2>
|
2024-07-02 16:08:07 +08:00
|
|
|
|
</div >
|
|
|
|
|
<form class="form-box" @submit.prevent="handleSubmit" v-if="userId">
|
2024-07-02 14:28:15 +08:00
|
|
|
|
<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>
|
2024-07-02 16:08:07 +08:00
|
|
|
|
<h1 v-else>!错误的请求</h1>
|
2024-07-02 14:28:15 +08:00
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2024-07-02 16:08:07 +08:00
|
|
|
|
@import "../base";
|
2024-07-02 14:28:15 +08:00
|
|
|
|
.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>
|