提交 | 用户 | 时间
|
820397
|
1 |
<script lang="ts" setup> |
H |
2 |
import { propTypes } from '@/utils/propTypes' |
|
3 |
import { useConfigGlobal } from '@/hooks/web/useConfigGlobal' |
|
4 |
import type { ZxcvbnResult } from '@zxcvbn-ts/core' |
|
5 |
import { zxcvbn } from '@zxcvbn-ts/core' |
|
6 |
import { useDesign } from '@/hooks/web/useDesign' |
|
7 |
|
|
8 |
defineOptions({ name: 'InputPassword' }) |
|
9 |
|
|
10 |
const { getPrefixCls } = useDesign() |
|
11 |
|
|
12 |
const prefixCls = getPrefixCls('input-password') |
|
13 |
|
|
14 |
const props = defineProps({ |
|
15 |
// 是否显示密码强度 |
|
16 |
strength: propTypes.bool.def(false), |
|
17 |
modelValue: propTypes.string.def('') |
|
18 |
}) |
|
19 |
|
|
20 |
watch( |
|
21 |
() => props.modelValue, |
|
22 |
(val: string) => { |
|
23 |
if (val === unref(valueRef)) return |
|
24 |
valueRef.value = val |
|
25 |
} |
|
26 |
) |
|
27 |
|
|
28 |
const { configGlobal } = useConfigGlobal() |
|
29 |
|
|
30 |
const emit = defineEmits(['update:modelValue']) |
|
31 |
|
|
32 |
// 设置input的type属性 |
|
33 |
const textType = ref<'password' | 'text'>('password') |
|
34 |
|
|
35 |
const changeTextType = () => { |
|
36 |
textType.value = unref(textType) === 'text' ? 'password' : 'text' |
|
37 |
} |
|
38 |
|
|
39 |
// 输入框的值 |
|
40 |
const valueRef = ref(props.modelValue) |
|
41 |
|
|
42 |
// 监听 |
|
43 |
watch( |
|
44 |
() => valueRef.value, |
|
45 |
(val: string) => { |
|
46 |
emit('update:modelValue', val) |
|
47 |
} |
|
48 |
) |
|
49 |
|
|
50 |
// 获取密码强度 |
|
51 |
const getPasswordStrength = computed(() => { |
|
52 |
const value = unref(valueRef) |
|
53 |
const zxcvbnRef = zxcvbn(unref(valueRef)) as ZxcvbnResult |
|
54 |
return value ? zxcvbnRef.score : -1 |
|
55 |
}) |
|
56 |
|
|
57 |
const getIconName = computed(() => (unref(textType) === 'password' ? 'ep:hide' : 'ep:view')) |
|
58 |
</script> |
|
59 |
|
|
60 |
<template> |
|
61 |
<div :class="[prefixCls, `${prefixCls}--${configGlobal?.size}`]"> |
|
62 |
<ElInput v-model="valueRef" :type="textType" v-bind="$attrs"> |
|
63 |
<template #suffix> |
|
64 |
<Icon :icon="getIconName" class="el-input__icon cursor-pointer" @click="changeTextType" /> |
|
65 |
</template> |
|
66 |
</ElInput> |
|
67 |
<div |
|
68 |
v-if="strength" |
|
69 |
:class="`${prefixCls}__bar`" |
|
70 |
class="relative mb-6px ml-auto mr-auto mt-10px h-6px" |
|
71 |
> |
|
72 |
<div :class="`${prefixCls}__bar--fill`" :data-score="getPasswordStrength"></div> |
|
73 |
</div> |
|
74 |
</div> |
|
75 |
</template> |
|
76 |
|
|
77 |
<style lang="scss" scoped> |
|
78 |
$prefix-cls: #{$namespace}-input-password; |
|
79 |
|
|
80 |
.#{$prefix-cls} { |
|
81 |
:deep(.#{$elNamespace}-input__clear) { |
|
82 |
margin-left: 5px; |
|
83 |
} |
|
84 |
|
|
85 |
&__bar { |
|
86 |
background-color: var(--el-text-color-disabled); |
|
87 |
border-radius: var(--el-border-radius-base); |
|
88 |
|
|
89 |
&::before, |
|
90 |
&::after { |
|
91 |
position: absolute; |
|
92 |
z-index: 10; |
|
93 |
display: block; |
|
94 |
width: 20%; |
|
95 |
height: inherit; |
|
96 |
background-color: transparent; |
|
97 |
border-color: var(--el-color-white); |
|
98 |
border-style: solid; |
|
99 |
border-width: 0 5px; |
|
100 |
content: ''; |
|
101 |
} |
|
102 |
|
|
103 |
&::before { |
|
104 |
left: 20%; |
|
105 |
} |
|
106 |
|
|
107 |
&::after { |
|
108 |
right: 20%; |
|
109 |
} |
|
110 |
|
|
111 |
&--fill { |
|
112 |
position: absolute; |
|
113 |
width: 0; |
|
114 |
height: inherit; |
|
115 |
background-color: transparent; |
|
116 |
border-radius: inherit; |
|
117 |
transition: |
|
118 |
width 0.5s ease-in-out, |
|
119 |
background 0.25s; |
|
120 |
|
|
121 |
&[data-score='0'] { |
|
122 |
width: 20%; |
|
123 |
background-color: var(--el-color-danger); |
|
124 |
} |
|
125 |
|
|
126 |
&[data-score='1'] { |
|
127 |
width: 40%; |
|
128 |
background-color: var(--el-color-danger); |
|
129 |
} |
|
130 |
|
|
131 |
&[data-score='2'] { |
|
132 |
width: 60%; |
|
133 |
background-color: var(--el-color-warning); |
|
134 |
} |
|
135 |
|
|
136 |
&[data-score='3'] { |
|
137 |
width: 80%; |
|
138 |
background-color: var(--el-color-success); |
|
139 |
} |
|
140 |
|
|
141 |
&[data-score='4'] { |
|
142 |
width: 100%; |
|
143 |
background-color: var(--el-color-success); |
|
144 |
} |
|
145 |
} |
|
146 |
} |
|
147 |
|
|
148 |
&--mini > &__bar { |
|
149 |
border-radius: var(--el-border-radius-small); |
|
150 |
} |
|
151 |
} |
|
152 |
</style> |