wangzhibo
4 天以前 10595d8632f959d0954d1939243196f4eed02372
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<template>
    <view
        class="cl-captcha"
        :class="{
            'is-border': border,
        }"
    >
        <input
            class="cl-captcha__input"
            v-model="value"
            type="number"
            :focus="focus"
            :maxlength="len"
            @focus="onFocus"
            @blur="onBlur"
            @input="onInput"
        />
 
        <view class="cl-captcha__code">
            <view
                class="cl-captcha__item"
                :style="{
                    height: parseRpx(height),
                    margin: `0 ${parseRpx(gutter)}`,
                    backgroundColor,
                }"
                v-for="(_, index) in list"
                :key="index"
            >
                <text class="cl-captcha__value">{{ value[index] }}</text>
                <view class="cl-captcha__cursor" v-if="value.length == index && isFocus"></view>
            </view>
        </view>
    </view>
</template>
 
<script lang="ts">
import { computed, defineComponent, ref, watch } from "vue";
import { parseRpx } from "/@/cool/utils";
 
export default defineComponent({
    name: "cl-captcha",
 
    props: {
        // 绑定值
        modelValue: String,
        // 是否自动聚焦
        focus: Boolean,
        // 验证码高度
        height: {
            type: [String, Number],
            default: 140,
        },
        // 验证码位数
        len: {
            type: Number,
            default: 4,
        },
        // 间隔
        gutter: {
            type: Number,
            default: 20,
        },
        // 带边框
        border: Boolean,
        // 背景色
        backgroundColor: {
            type: String,
            default: "#ebecee",
        },
    },
 
    emits: ["update:modelValue", "done"],
 
    setup(props, { emit }) {
        const value = ref();
 
        // 是否聚焦
        const isFocus = ref(props.focus);
 
        // 头条小程序下,无法 v-for 数字
        const list = computed(() => new Array(props.len).fill(1));
 
        watch(
            () => props.modelValue,
            (val) => {
                value.value = val || "";
            },
            {
                immediate: true,
            },
        );
 
        function onFocus() {
            isFocus.value = true;
        }
 
        function onBlur() {
            isFocus.value = false;
        }
 
        function onInput(e: any) {
            const val = e.detail.value;
 
            emit("update:modelValue", val);
 
            if (val.length === props.len) {
                emit("done", val);
            }
        }
 
        return {
            value,
            isFocus,
            list,
            parseRpx,
            onFocus,
            onBlur,
            onInput,
        };
    },
});
</script>