You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

314 lines
7.4 KiB

<template>
<div class="login-by-phone">
<div class="masker" @click="handleClose"></div>
<div class="detail-content">
<h4 class="login-text">{{ $t('login') }}</h4>
<div class="phone-group" @click="changeInputFocus('phone')">
<img src="../../assets/images/member/hpone_tip.png" alt="" class="group-icon" />
<div class="line"></div>
<input v-model="phoneRef" readonly type="text" :placeholder="$t('phoneNum')" class="input" />
</div>
<div class="pwd-box">
<div class="phone-group pwd">
<img src="../../assets/images/member/pwd.png" alt="" class="group-icon" />
<div class="line"></div>
<input v-model="msgRef" @click="changeInputFocus('msg')" readonly type="text" :placeholder="$t('enterCode')" class="input" />
</div>
<div class="button" @click="sendMsg" :class="{ active: isSended }">{{ isSended ? countDownRef + ' ' + $t('again') : $t('sendCode') }}</div>
</div>
<div class="comfirm" @click="comfirm" :class="{ active: phoneRef.length && msgRef.length }">{{ $t('denglu') }}</div>
<div class="phone-keyboard">
<div
class="num"
@click="handleNum(item === 10 ? '' : item === 11 ? 0 : item, index)"
:class="{ active: numIdx === index }"
v-for="(item, index) of 12"
:key="item"
v-html="generate(item)"
></div>
</div>
<div class="close" @click="handleClose">
<img src="../../assets/images/detail/yellow_close.png" alt="" />
</div>
</div>
</div>
</template>
<script setup>
import { ref, onBeforeUnmount } from 'vue'
import { checkPhoneNumber } from '@/utils/utils'
import Message from '@/base/Message/Message'
const emits = defineEmits(['success', 'error', 'close'])
function generate(item) {
return item === 10 ? '' : item === 11 ? 0 : item === 12 ? `<img src=${require('../../assets/images/member/del.svg')} class="del-icon" alt="" />` : item
}
const phoneRef = ref('')
const msgRef = ref('')
const inputFocusRef = ref('phone')
const numIdx = ref(-1)
const numTimer = ref(null)
function handleNum(item, index) {
clearTimeout(numTimer.value)
numIdx.value = index
numTimer.value = setTimeout(() => {
numIdx.value = -1
clearTimeout(numTimer.value)
}, 300)
if (item === 12) {
del()
return
}
if (inputFocusRef.value === 'phone') {
if (phoneRef.value.length < 11) {
phoneRef.value += item
}
}
if (inputFocusRef.value === 'msg') {
msgRef.value += item
}
}
function changeInputFocus(name) {
inputFocusRef.value = name
}
function del() {
if (inputFocusRef.value === 'phone') {
phoneRef.value = phoneRef.value.substring(0, phoneRef.value.length - 1)
}
if (inputFocusRef.value === 'msg') {
msgRef.value = msgRef.value.substring(0, msgRef.value.length - 1)
}
}
const countDownRef = ref(60)
const countDownTimer = ref(null)
const isSended = ref(false)
//发送验证码
function sendMsg() {
if (isSended.value) return
if (!checkPhoneNumber(phoneRef.value)) {
Message({ type: 'error', text: '请输入正确的手机号' })
return
}
if (!phoneRef.value.length) {
Message({ type: 'error', text: '手机号不能为空' })
return
}
isSended.value = true
inputFocusRef.value = 'msg'
countDownTimer.value = setInterval(countDown, 1000)
}
//一分钟倒计时
function countDown() {
countDownRef.value--
if (countDownRef.value <= 0) {
isSended.value = false
countDownRef.value = 60
clearInterval(countDownTimer.value)
}
}
//登录
function comfirm() {
if (!checkPhoneNumber(phoneRef.value)) {
Message({ type: 'error', text: '请输入正确的手机号' })
return
}
emits('success')
}
onBeforeUnmount(() => {
clearInterval(countDownTimer.value)
})
function handleClose() {
emits('close')
}
</script>
<style lang="scss" scoped>
.login-by-phone {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 51;
animation-duration: 0.3s;
}
.masker {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 20;
}
.detail-content {
position: relative;
width: 484px;
height: 732px;
margin: 0 auto;
margin-top: 594px;
background: #ffffff;
box-shadow: 0px 40px 60px rgba(0, 0, 0, 0.08);
border-radius: 12px;
z-index: 21;
.close {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 12px;
right: 12px;
width: 56px;
height: 56px;
background: rgba(0, 0, 0, 0.02);
border-radius: 12px;
img {
width: 56px;
height: 56px;
}
}
.login-text {
font-weight: 700;
font-size: 24px;
line-height: 28px;
margin-bottom: 40px;
padding-top: 48px;
padding-left: 72px;
font-family: 'font_bold';
color: rgba(0, 0, 0, 0.8);
}
::-webkit-input-placeholder {
font-size: 12px;
color: var(--color-0cb);
}
.pwd-box {
display: flex;
justify-content: space-between;
width: 340px;
margin-top: 12px;
margin-left: 72px;
margin-bottom: 24px;
.phone-group {
margin-left: 0;
}
.button {
width: 116px;
height: 64px;
left: 296px;
top: 192px;
text-align: center;
line-height: 64px;
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%);
border-radius: 12px;
font-weight: 700;
font-size: 14px;
color: rgba(0, 0, 0, 0.6);
font-family: 'font_bold';
}
}
.phone-group {
display: flex;
align-items: center;
width: 340px;
height: 64px;
margin-left: 72px;
background: rgba(0, 0, 0, 0.05);
border-radius: 12px;
padding-left: 20px;
&.pwd {
width: 212px;
}
.group-icon {
width: 20px;
}
.line {
width: 1px;
height: 14px;
background: rgba(0, 0, 0, 0.05);
border-radius: 1px;
margin: 0 14px;
}
}
.input {
width: 100%;
display: block;
border: none;
outline: none;
color: rgba(0, 0, 0, 0.4);
font-size: 16px;
background-color: transparent;
}
.comfirm {
width: 340px;
height: 64px;
line-height: 64px;
left: 72px;
top: 280px;
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%);
border-radius: 12px;
font-weight: 700;
font-size: 18px;
text-align: center;
color: rgba(0, 0, 0, 0.6);
font-family: 'font_bold';
margin: 0 auto;
margin-bottom: 40px;
}
.phone-keyboard {
display: grid;
grid-template-columns: repeat(3, 108px);
grid-template-rows: repeat(4, 56px);
gap: 12px 8px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.025) 100%);
padding: 40px 70px 48px 70px;
.num {
background: #ffffff;
box-shadow: inset 0px -4px 0px rgba(177, 189, 220, 0.1);
border-radius: 8px;
font-weight: 700;
font-size: 20px;
font-family: 'font_bold';
display: flex;
align-items: center;
justify-content: center;
color: rgba(0, 0, 0, 0.6);
&.active {
background: linear-gradient(90deg, #ffbd35 0%, #ffd260 100%);
box-shadow: inset 0px -4px 0px rgba(177, 189, 220, 0.1);
}
}
.del {
height: 56px;
width: 112px;
display: inline-flex;
align-items: center;
justify-content: center;
.del-icon {
width: 24px;
height: 24px;
}
}
}
}
.close {
position: absolute;
top: 24px;
width: 56px;
height: 56px;
right: 24px;
}
</style>