296 lines
5.6 KiB
Vue
296 lines
5.6 KiB
Vue
<template>
|
||
<view class="content">
|
||
<!-- 添加ColorUI自定义导航栏 -->
|
||
<cu-custom :isBack="true">
|
||
<view slot="backText">返回</view>
|
||
<view slot="content">忘记密码</view>
|
||
</cu-custom>
|
||
|
||
<view class="list">
|
||
<view class="tishi">若您忘记了密码,可在此重新设置新密码。</view>
|
||
<view class="list-call">
|
||
<image class="img" src="/static/index/phone.png"></image>
|
||
<input class="sl-input" type="number" v-model="phone" maxlength="11" placeholder="请输入手机号" />
|
||
</view>
|
||
<view class="list-call">
|
||
<image class="img" src="/static/index/lock.png"></image>
|
||
<input class="sl-input" type="text" v-model="password" maxlength="32" placeholder="请输入新密码" :password="!showPassword" />
|
||
<text class="eye-icon" :class="{'eye-active': showPassword}" @tap="togglePassword"></text>
|
||
</view>
|
||
<view class="list-call">
|
||
<!-- <image class="img" src="/static/index/code.png"></image> -->
|
||
<!-- <input class="sl-input" type="number" v-model="code" maxlength="4" placeholder="验证码" /> -->
|
||
<view class="yzm" :class="{ yzms: second > 0 }" @tap="getCode">{{codeText}}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="padding-lr">
|
||
<view class="button-login" hover-class="button-hover" @tap="handleReset">
|
||
<text>修改密码</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onUnmounted } from 'vue';
|
||
|
||
// 响应式数据
|
||
const phone = ref('');
|
||
const password = ref('');
|
||
const code = ref('');
|
||
const second = ref(0);
|
||
const showPassword = ref(false);
|
||
let timer = null;
|
||
|
||
// 计算属性
|
||
const codeText = computed(() => {
|
||
if (second.value === 0) {
|
||
return '获取验证码';
|
||
} else {
|
||
const secondStr = second.value < 10 ? `0${second.value}` : second.value;
|
||
return `重新获取${secondStr}`;
|
||
}
|
||
});
|
||
|
||
// 方法定义
|
||
const togglePassword = () => {
|
||
showPassword.value = !showPassword.value;
|
||
};
|
||
|
||
const getCode = () => {
|
||
if (phone.value.length !== 11) {
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: '手机号不正确'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (second.value > 0) {
|
||
return;
|
||
}
|
||
|
||
second.value = 60;
|
||
startCountdown();
|
||
|
||
// 发送验证码请求
|
||
uni.request({
|
||
url: 'http://example.com/api/code',
|
||
data: {
|
||
phone: phone.value,
|
||
type: 'forget'
|
||
},
|
||
method: 'POST',
|
||
dataType: 'json',
|
||
success: (res) => {
|
||
if (res.data.code != 200) {
|
||
uni.showToast({
|
||
title: res.data.msg || '获取验证码失败',
|
||
icon: 'none'
|
||
});
|
||
second.value = 0;
|
||
clearCountdown();
|
||
} else {
|
||
uni.showToast({
|
||
title: res.data.msg || '验证码已发送'
|
||
});
|
||
}
|
||
},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: '网络请求失败',
|
||
icon: 'none'
|
||
});
|
||
second.value = 0;
|
||
clearCountdown();
|
||
}
|
||
});
|
||
};
|
||
|
||
const startCountdown = () => {
|
||
clearCountdown();
|
||
timer = setInterval(() => {
|
||
second.value--;
|
||
if (second.value === 0) {
|
||
clearCountdown();
|
||
}
|
||
}, 1000);
|
||
};
|
||
|
||
const clearCountdown = () => {
|
||
if (timer) {
|
||
clearInterval(timer);
|
||
timer = null;
|
||
}
|
||
};
|
||
|
||
const handleReset = () => {
|
||
if (phone.value.length !== 11) {
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: '手机号不正确'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (password.value.length < 6) {
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: '密码不正确'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (code.value.length !== 4) {
|
||
uni.showToast({
|
||
icon: 'none',
|
||
title: '验证码不正确'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 修改密码请求
|
||
uni.request({
|
||
url: 'http://example.com/api/forget',
|
||
data: {
|
||
phone: phone.value,
|
||
password: password.value,
|
||
code: code.value
|
||
},
|
||
method: 'POST',
|
||
dataType: 'json',
|
||
success: (res) => {
|
||
if (res.data.code != 200) {
|
||
uni.showToast({
|
||
title: res.data.msg || '修改密码失败',
|
||
icon: 'none'
|
||
});
|
||
} else {
|
||
uni.showToast({
|
||
title: res.data.msg || '修改密码成功'
|
||
});
|
||
|
||
// 延时返回登录页
|
||
setTimeout(() => {
|
||
uni.navigateBack();
|
||
}, 1500);
|
||
}
|
||
},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: '网络请求失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
};
|
||
|
||
// 组件卸载时清除定时器
|
||
onUnmounted(() => {
|
||
clearCountdown();
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
page {
|
||
background-color: #FFFFFF;
|
||
}
|
||
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
background-color: #FFFFFF;
|
||
}
|
||
|
||
.tishi {
|
||
color: #999999;
|
||
font-size: 28rpx;
|
||
line-height: 50rpx;
|
||
margin-bottom: 50rpx;
|
||
}
|
||
|
||
.list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding-top: 50rpx;
|
||
padding-left: 70rpx;
|
||
padding-right: 70rpx;
|
||
|
||
.list-call {
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
height: 100rpx;
|
||
color: #333333;
|
||
background: #F5F7FB;
|
||
border-radius: 16rpx;
|
||
border: 2rpx solid #F5F7FB;
|
||
margin-top: 30rpx;
|
||
padding: 0 30rpx;
|
||
|
||
.img {
|
||
width: 30rpx;
|
||
height: 36rpx;
|
||
}
|
||
|
||
.sl-input {
|
||
flex: 1;
|
||
text-align: left;
|
||
font-size: 32rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
|
||
.eye-icon {
|
||
font-size: 36rpx;
|
||
color: #999;
|
||
&::before {
|
||
content: '\e69c'; /* 闭眼图标的unicode */
|
||
}
|
||
|
||
&.eye-active {
|
||
color: #3D83F6;
|
||
&::before {
|
||
content: '\e69d'; /* 睁眼图标的unicode */
|
||
}
|
||
}
|
||
}
|
||
|
||
.yzm {
|
||
width: 200rpx;
|
||
height: 60rpx;
|
||
text-align: center;
|
||
font-size: 30rpx;
|
||
color: #3D83F6;
|
||
&.yzms {
|
||
color: #999999;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.padding-lr {
|
||
padding-left: 70rpx;
|
||
padding-right: 70rpx;
|
||
}
|
||
|
||
.button-login {
|
||
color: #FFFFFF;
|
||
font-size: 34rpx;
|
||
width: 100%;
|
||
height: 100rpx;
|
||
background: linear-gradient(90deg, #3E95F1 0%, #4269F5 100%);
|
||
border-radius: 50rpx;
|
||
line-height: 100rpx;
|
||
text-align: center;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
margin-top: 130rpx;
|
||
}
|
||
|
||
.button-hover {
|
||
opacity: 0.8;
|
||
}
|
||
</style> |