officialAccount/pages/login/code.vue

459 lines
9.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="login-container">
<view class="title">
<image class="title-imge" src="/static/index/nu.png" />
<view class="title-font">
<view class="">您好</view>
<view class="">欢迎使用护理单元~</view>
</view>
</view>
<image class="photo-imge" src="/static/index/bgc.png" />
<image class="old-imge" src="/static/index/old.png" />
<view class="under-container">
<view class="under-container-title">
<view class="code-title">
请输入验证码
</view>
<view class="code-number">
验证码已发送至{{ phonenumber }}
</view>
</view>
<view class="captcha-container">
<view class="captcha-box">
<view v-for="(digit, index) in captcha" :key="index" class="captcha-item">
<input v-model="captcha[index]" class="captcha-input" type="number" maxlength="1"
:placeholder="index < 3 ? '' : ' '" @input="handleInput(index)"
@keydown="handleKeydown(index, $event)" :focus="focusedIndex === index" />
</view>
</view>
</view>
<view class="under-view">
<view class="right-blue" v-show="!countdown">
重新发送
</view>
<view class="right-white" v-show="countdown">
{{countdown}}S后重新发送
</view>
<view class="right-black" @click="isFadingOut=true">
收不到验证码
</view>
</view>
</view>
<!-- 遮罩 -->
<transition name="fade">
<view v-if="isFadingOut" class="overlay" @click="closeModal" :style="{ backgroundColor: maskColor }" />
</transition>
<!-- 底部弹窗 -->
<transition name="slide-up">
<view v-if="isFadingOut" class="modal">
<view class="modal-title">收不到验证码</view>
<view class="model-p">
<view class="text-view" style="font-weight: 600;">手机号可正常使用:</view>
<view class="text-view">1 是否输错手机号</view>
<view class="text-view">2 手机是否设置短信拦截/欠费/信号不好</view>
<view class="text-view">3 手机内存是否满了</view>
<view class="text-view">4 手机卡是否为物联卡而非SIM卡</view>
</view>
</view>
</transition>
</view>
</template>
<script setup>
import {
nextTick,
reactive,
ref,
onUnmounted
} from 'vue';
import {
onLoad
} from '@dcloudio/uni-app';
const phonenumber = ref("")
const captcha = ref(['', '', '', '']); // 用来存储4个小方块的验证码输入
const focusedIndex = ref(0); // 当前聚焦的小方块索引
const isFadingOut = ref(false);
// 遮罩色rgba 可调透明度
const maskColor = ref('rgba(0, 0, 0, 0.5)')
function closeModal() {
isFadingOut.value = false
}
// 输入框输入时的处理函数
const handleInput = (index) => {
if (captcha.value[index]) {
if (index < 3) {
focusedIndex.value = index + 1; // 输入后自动聚焦到下一个小方块
}
}
let isFour = true;
captcha.value.forEach(number=>{
if(!number){
isFour = false;
}
})
nextTick(()=>{
if(isFour){
submitCaptcha()
}
})
};
// 处理删除键
const handleKeydown = (index, event) => {
if (event.key === 'Backspace' && !captcha.value[index]) {
if (index > 0) {
focusedIndex.value = index - 1; // 如果当前小方块为空,则聚焦到前一个小方块
}
}
};
// 提交验证码
const submitCaptcha = () => {
const code = captcha.value.join('');
if (code.length === 4) {
console.log('提交验证码:', code);
uni.reLaunch({
url: `/pages/index/index`
});
// 执行验证码提交的逻辑
} else {
console.log('验证码未输入完整');
}
};
const getcode = () =>{
// uni.getStorage({
// key: 'serverUrl',
// success: (res) => {
// // res.data 就是你存进去的对象 { url: '...' }
// const { url } = res.data;
// console.log('取到的 serverUrl', url);
// const url = `${url}/h5Api/nuBaseInfo/list`;
// fetch(url)
// .then(res => res.json())
// .then(data => {
// secondArray.value = [...data.result]
// })
// // 后续逻辑…
// },
// fail: (err) => {
// console.error('取 serverUrl 失败', err);
// }
// });
const url = `https://www.focusnu.com/nursing-unit/sys/randomImage/${Date.now()}`;
fetch(url)
.then(res => res.json())
.then(data => {
console.log("code测试",data)
})
}
// 新增:倒计时相关
const countdown = ref(60);
let timerId = null;
// 页面卸载时清除定时器
onUnmounted(() => {
if (timerId) {
clearInterval(timerId);
}
});
onLoad((options) => {
phonenumber.value = options.phonenumber;
getcode()
// 倒计时逻辑
countdown.value = 60;
timerId = setInterval(() => {
if (countdown.value > 0) {
countdown.value--;
} else {
clearInterval(timerId);
timerId = null;
}
}, 1000);
});
</script>
<style lang="scss" scoped>
.login-container {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
background-color: rgb(239, 241, 252);
position: relative;
.title {
margin-top: 70rpx;
align-items: center;
.title-imge {
width: 100rpx;
height: 105rpx;
margin-left: 100rpx;
}
.title-font {
font-size: 35rpx;
font-weight: 600;
margin-left: 105rpx;
margin-top: 10rpx;
}
}
.photo-imge {
position: absolute;
top: 120rpx;
left: 0;
width: 100%;
height: 1100rpx;
}
.old-imge {
position: absolute;
right: 30rpx;
top: 400rpx;
width: 400rpx;
height: 400rpx;
}
.under-container {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 45vh;
background-color: #fff;
border-top-left-radius: 50rpx;
border-top-right-radius: 50rpx;
box-shadow: 10rpx 10rpx 20rpx rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
color: #5A607F;
.radio-circle {
position: relative;
margin-top: 2rpx;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
border: 2rpx solid #C0C5D9;
background-color: transparent;
}
.radio-circle-target {
position: relative;
margin-top: 2rpx;
width: 40rpx;
height: 40rpx;
border-radius: 50%;
border: 2rpx solid #C0C5D9;
background-color: transparent;
}
.radio-circle-target::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 30rpx;
height: 30rpx;
background-color: #00C9FF;
border-radius: 50%;
}
}
}
.under-container-title {
margin-top: 50rpx;
margin-bottom: 20rpx;
font-size: 25rpx;
font-weight: 500;
width: 100%;
.code-title {
margin-left: 80rpx;
font-size: 35rpx;
color: black;
font-weight: 500;
margin-bottom: 20rpx;
}
.code-number {
margin-left: 80rpx;
font-size: 28rpx;
margin-bottom: 20rpx;
}
}
.captcha-container {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20rpx;
}
.captcha-box {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
}
.captcha-item {
display: flex;
justify-content: center;
align-items: center;
}
.captcha-input {
width: 110rpx;
height: 110rpx;
border: 3rpx solid #C0C5D9;
border-radius: 30rpx;
font-size: 50rpx;
font-weight: 700;
text-align: center;
margin-right: 40rpx;
outline: none;
}
.captcha-input:focus {
border-color: #00C9FF;
}
.right-blue{
// float: right;
color: #0083FF;
margin-left: 60rpx;
}
.right-white{
color: rgb(194,198,211);
margin-left: 60rpx;
}
.right-black{
// float: right;
// color: #0083FF;
margin-right: 80rpx;
color: black;
}
.under-view{
width: 100%;
margin-top: 10rpx;
display: flex;
justify-content: space-between;
}
/* 遮罩 */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 998;
}
/* 弹窗 */
.modal {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
z-index: 999;
border-top-left-radius: 50rpx;
border-top-right-radius: 50rpx;
width: 100%;
height: 500rpx;
display: flex;
flex-direction: column;
align-items: center;
.modal-title {
font-size: 32rpx;
font-weight: 700;
margin: 50rpx 0;
margin-bottom: 30rpx;
}
.model-p {
padding: 0 50rpx;
width: 100%;
font-size: 30rpx;
}
.model-down {
display: flex;
width: 100%;
justify-content: space-between;
padding: 0 50rpx;
margin-top: 40rpx;
.model-white {
border-radius: 50rpx;
width: 300rpx;
height: 95rpx;
border: 5rpx solid rgb(0, 141, 255);
color: rgb(0, 141, 255);
font-size: 35rpx;
display: flex;
justify-content: center;
align-items: center;
}
.model-blue {
border-radius: 50rpx;
width: 300rpx;
height: 95rpx;
background: linear-gradient(to right, #00C9FF, #0076FF);
color: #fff;
font-size: 35rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
}
/* 动画:遮罩淡入淡出 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
opacity: 1;
}
/* 动画:弹窗上滑 */
.slide-up-enter-active,
.slide-up-leave-active {
transition: transform 0.3s;
}
.slide-up-enter-from,
.slide-up-leave-to {
transform: translateY(100%);
}
.slide-up-enter-to,
.slide-up-leave-from {
transform: translateY(0);
}
.text-view{
margin-bottom: 20rpx;
}
</style>