特性: 新增输入强度校验组件

This commit is contained in:
fifteen 2024-01-25 10:41:48 +08:00
parent 10ac766489
commit ebc737b8bb
2 changed files with 148 additions and 0 deletions

View File

@ -0,0 +1,76 @@
.inputStrength {
width: 100%;
:deep(.#{'el'}-input__clear) {
margin-left: 5px;
}
&-input {
&_icon {
cursor: pointer;
}
}
&-line {
background-color: var(--el-text-color-disabled);
border-radius: var(--el-border-radius-base);
position: relative;
margin-bottom: 6px;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
height: 6px;
&::before,
&::after {
position: absolute;
z-index: 10;
display: block;
width: 20%;
height: inherit;
background-color: transparent;
border-color: var(--el-color-white);
border-style: solid;
border-width: 0 5px;
content: '';
}
&::before {
left: 20%;
}
&::after {
right: 20%;
}
&_visual {
position: absolute;
width: 0;
height: inherit;
background-color: transparent;
border-radius: inherit;
transition: width 0.5s ease-in-out, background 0.25s;
&[data-score='0'] {
width: 20%;
background-color: var(--el-color-danger);
}
&[data-score='1'] {
width: 40%;
background-color: var(--el-color-danger);
}
&[data-score='2'] {
width: 60%;
background-color: var(--el-color-warning);
}
&[data-score='3'] {
width: 80%;
background-color: var(--el-color-success);
}
&[data-score='4'] {
width: 100%;
background-color: var(--el-color-success);
}
}
}
}

View File

@ -0,0 +1,72 @@
<template>
<div class="inputStrength">
<el-input v-model="inputValue" placeholder="请输入密码" :type="textType" v-bind="$attrs" class="inputStrength-input">
<template #suffix>
<div class="inputStrength-input_icon" @click="changeTextType">
<svg-icon :icon-class="passwordType ? 'eye' : 'eye-open'" />
</div>
</template>
</el-input>
<div v-if="strength" class="inputStrength-line">
<div class="inputStrength-line_visual" :data-score="getPasswordStrength"></div>
</div>
</div>
</template>
<script lang="ts" setup>
import { watch, unref, ref, computed, PropType } from 'vue'
import type { ZxcvbnResult } from '@zxcvbn-ts/core'
import { zxcvbn } from '@zxcvbn-ts/core'
const props = defineProps({
//
strength: {
type: Boolean as PropType<boolean>,
default: false,
},
modelValue: {
type: String as PropType<string>,
default: '',
},
})
const emits = defineEmits(['update:modelValue'])
//
const inputValue = ref(props.modelValue)
//
const textType = ref<'password' | 'text'>('password')
//
const changeTextType = () => {
textType.value = unref(textType) === 'text' ? 'password' : 'text'
}
//icon
const passwordType = computed(() => unref(textType) === 'password')
//
const getPasswordStrength = computed(() => {
const value = unref(inputValue)
const zxcvbnRef = zxcvbn(inputValue.value) as ZxcvbnResult
return value ? zxcvbnRef.score : -1
})
watch(
() => props.modelValue,
(val: string) => {
if (val === unref(inputValue)) return
inputValue.value = val
},
)
watch(
() => inputValue.value,
(val: string) => {
emits('update:modelValue', val)
},
)
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>