StrengthMeter.vue 3.4 KB
Newer Older
V
vben 已提交
1
<template>
V
vben 已提交
2
  <div :class="prefixCls" class="relative">
V
vben 已提交
3 4 5 6 7 8 9 10 11
    <InputPassword
      v-if="showInput"
      v-bind="$attrs"
      allowClear
      :value="innerValueRef"
      @change="handleChange"
      :disabled="disabled"
    >
      <template #[item]="data" v-for="item in Object.keys($slots)">
V
vben 已提交
12
        <slot :name="item" v-bind="data"></slot>
V
vben 已提交
13 14 15 16 17 18 19 20 21 22 23 24 25
      </template>
    </InputPassword>
    <div :class="`${prefixCls}-bar`">
      <div :class="`${prefixCls}-bar--fill`" :data-score="getPasswordStrength"></div>
    </div>
  </div>
</template>

<script lang="ts">
  import { defineComponent, computed, ref, watch, unref, watchEffect } from 'vue';

  import { Input } from 'ant-design-vue';

V
Vben 已提交
26 27
  // @ts-ignore
  import { zxcvbn } from '@zxcvbn-ts/core';
V
vben 已提交
28
  import { useDesign } from '/@/hooks/web/useDesign';
V
vben 已提交
29
  import { propTypes } from '/@/utils/propTypes';
V
vben 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

  export default defineComponent({
    name: 'StrengthMeter',
    components: { InputPassword: Input.Password },
    props: {
      value: propTypes.string,
      showInput: propTypes.bool.def(true),
      disabled: propTypes.bool,
    },
    emits: ['score-change', 'change'],
    setup(props, { emit }) {
      const innerValueRef = ref('');
      const { prefixCls } = useDesign('strength-meter');

      const getPasswordStrength = computed(() => {
V
vben 已提交
45
        const { disabled } = props;
V
vben 已提交
46
        if (disabled) return -1;
V
vben 已提交
47
        const innerValue = unref(innerValueRef);
V
vben 已提交
48
        const score = innerValue ? zxcvbn(unref(innerValueRef)).score : -1;
V
vben 已提交
49 50 51 52 53 54 55 56 57 58 59
        emit('score-change', score);
        return score;
      });

      function handleChange(e: ChangeEvent) {
        innerValueRef.value = e.target.value;
      }

      watchEffect(() => {
        innerValueRef.value = props.value || '';
      });
V
vben 已提交
60

V
vben 已提交
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
      watch(
        () => unref(innerValueRef),
        (val) => {
          emit('change', val);
        }
      );

      return {
        getPasswordStrength,
        handleChange,
        prefixCls,
        innerValueRef,
      };
    },
  });
</script>
<style lang="less" scoped>
  @prefix-cls: ~'@{namespace}-strength-meter';

  .@{prefix-cls} {
    &-bar {
      position: relative;
V
vben 已提交
83
      height: 6px;
V
vben 已提交
84
      margin: 10px auto 6px;
V
Vben 已提交
85
      background-color: @disabled-color;
V
vben 已提交
86
      border-radius: 6px;
V
vben 已提交
87 88 89 90 91 92 93 94

      &::before,
      &::after {
        position: absolute;
        z-index: 10;
        display: block;
        width: 20%;
        height: inherit;
V
Vben 已提交
95
        background-color: transparent;
V
vben 已提交
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
        border-color: @white;
        border-style: solid;
        border-width: 0 5px 0 5px;
        content: '';
      }

      &::before {
        left: 20%;
      }

      &::after {
        right: 20%;
      }

      &--fill {
        position: absolute;
        width: 0;
        height: inherit;
V
Vben 已提交
114
        background-color: transparent;
V
vben 已提交
115 116 117 118 119
        border-radius: inherit;
        transition: width 0.5s ease-in-out, background 0.25s;

        &[data-score='0'] {
          width: 20%;
V
Vben 已提交
120
          background-color: darken(@error-color, 10%);
V
vben 已提交
121 122 123 124
        }

        &[data-score='1'] {
          width: 40%;
V
Vben 已提交
125
          background-color: @error-color;
V
vben 已提交
126 127 128 129
        }

        &[data-score='2'] {
          width: 60%;
V
Vben 已提交
130
          background-color: @warning-color;
V
vben 已提交
131 132 133 134
        }

        &[data-score='3'] {
          width: 80%;
V
Vben 已提交
135
          background-color: fade(@success-color, 50%);
V
vben 已提交
136 137 138 139
        }

        &[data-score='4'] {
          width: 100%;
V
Vben 已提交
140
          background-color: @success-color;
V
vben 已提交
141 142 143 144 145
        }
      }
    }
  }
</style>