Files
aida_front/src/component/LoginPage/verificationCodeInput.vue

152 lines
3.6 KiB
Vue
Raw Normal View History

2023-01-06 16:00:15 +08:00
<template>
<div id="app">
<div class="captcha">
<input v-for="(c, index) in getCtData" :key="index"
type="text"
2023-01-06 16:00:15 +08:00
v-model="getCtData[index]" ref="input"
inputmode="numeric"
pattern="[0-9]*"
2023-01-06 16:00:15 +08:00
@input="e => {onInput(e.target.value, index)}"
@keydown="e => {onKeydown(e, index)}"
@keypress="e => {onKeypress(e)}"
2023-01-06 16:00:15 +08:00
@focus="onFocus"
:disabled="loading"
>
</div>
</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
props:['ct'],
data() {
return {
loading: false,
}
},
computed: {
getCtData(){
return this.ct
},
ctSize() {
return this.getCtData.length;
},
cIndex() {
let i = this.getCtData.findIndex(item => item === '');
i = (i + this.ctSize) % this.ctSize;
return i;
},
lastCode() {
return this.getCtData[this.ctSize - 1];
}
},
watch: {
cIndex() {
this.resetCaret();
},
2024-11-22 09:20:25 +08:00
lastCode(newVal,oldVal) {
if (newVal && newVal != oldVal) {
2023-01-06 16:00:15 +08:00
this.$refs.input[this.ctSize - 1].blur();
this.sendCaptcha();
}
}
},
mounted() {
this.resetCaret();
},
methods: {
onInput(val, index) {
console.log('input',val,index)
// val = val.replace(/[^0-9]/g, '');
val = String(val).replace(/\D/g, '');
this.getCtData[index] = val
2023-01-06 16:00:15 +08:00
if (index == this.ctSize - 1) {
this.getCtData[this.ctSize - 1] = val[0]; // 最后一个码,只允许输入一个字符。
} else if(val.length > 1) {
let i = index;
for (i = index; i < this.ctSize && i - index < val.length; i++) {
this.getCtData[i] = val[i];
}
this.resetCaret();
}else if(!(val+'')){
this.getCtData[index] = ''
}
},
// 重置光标位置。
resetCaret() {
this.$refs.input[this.ctSize-1].focus();
},
onFocus() {
// 监听 focus 事件,将光标重定位到“第一个空白符的位置”。
let index = this.getCtData.findIndex(item => item === '');
index = (index + this.ctSize) % this.ctSize;
this.$refs.input[index].focus();
},
onKeypress(e) {
// 只允许输入数字0-9
const char = String.fromCharCode(e.which);
if (!/[0-9]/.test(char)) {
e.preventDefault();
}
},
onKeydown(e, index) {
// 处理删除键
if (e.key === 'Backspace' || e.key === 'Delete') {
const val = e.target.value;
if (val === '') {
// 删除上一个input里的值并对其focus。
if (index > 0) {
this.getCtData[index - 1] = '';
this.$refs.input[index - 1].focus();
}
2023-01-06 16:00:15 +08:00
}
}
// 阻止其他非数字字符
else if (e.key && !/[0-9]/.test(e.key) && !['Backspace', 'Delete', 'Tab', 'Enter', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {
e.preventDefault();
}
2023-01-06 16:00:15 +08:00
},
sendCaptcha() {
let password = this.getCtData.map(item => item).join('');
this.$emit('sendCaptcha',password)
},
reset() {
// 重置。一般是验证码错误时触发。
this.getCtData = this.getCtData.map(item => '');
this.resetCaret();
}
}
})
</script>
<style scoped lang="less">
.captcha {
display: flex;
justify-content: space-between;
}
input {
2025-08-22 10:27:48 +08:00
width: 8.7rem;
height: 8.7rem;
2023-01-06 16:00:15 +08:00
border: 0.1rem solid #B4BED7;
2025-08-22 10:27:48 +08:00
border-radius: 2rem;
2023-01-06 16:00:15 +08:00
text-align: center;
font-size: 2.4rem;
2025-08-22 10:27:48 +08:00
line-height: 8.7rem;
2023-01-06 16:00:15 +08:00
outline: none;
}
input:last-of-type {
margin-right: 0;
}
input:disabled {
color: #000;
background-color: #fff;
}
.msg {
text-align: center;
}
</style>