vue 登陆页密码框小眼睛

37 阅读4分钟

业务页


<el-form-item label="原始密码:" prop="oldPass">
      <el-input v-model.trim="userInfoForm.oldPass" :type="isShowEye.oldPass" maxlength="100" />
      <span
        class="show-pwd"
        @click="isShowPass('oldPass')"
      >
        <HideSvg 
          v-if="isShowEye.oldPass"
          class="hide-svg"
        />
        <ViewSvg class="view-svg" v-else />
      </span>
</el-form-item>
<el-form-item label="新密码:" prop="newPass">
      <el-input v-model.trim="userInfoForm.newPass"  maxlength="100" :type="isShowEye.newPass"  />
      <span
        class="show-pwd"
        @click="isShowPass('newPass')"
      >
        <HideSvg 
          v-if="isShowEye.newPass"
          class="hide-svg"
        />
        <ViewSvg class="view-svg" v-else />
      </span>
</el-form-item>
<el-form-item label="重复密码:" prop="repPassword">
      <el-input v-model.trim="userInfoForm.repPassword" :type="isShowEye.confirmPassword" maxlength="100" />
      <span
        class="show-pwd"
        @click="isShowPass('confirmPassword')"
      >
        <HideSvg 
          v-if="isShowEye.confirmPassword"
          class="hide-svg"
        />
        <ViewSvg class="view-svg" v-else />
      </span>
</el-form-item>

import ViewSvg  from './ViewSvg.vue'
import HideSvg  from './HideSvg.vue'

 //小眼睛
isShowEye :{
  oldPass: 'password',
  newPass: 'password',
  confirmPassword: 'password',
}
components: {
  ViewSvg,
  HideSvg
},

isShowPass (val) {
    if(val === 'oldPass'){
      this.isShowEye.oldPass = this.isShowEye.oldPass === 'password'? '' : 'password'
    }
    if(val === 'newPass'){
      this.isShowEye.newPass = this.isShowEye.newPass === 'password'? '' : 'password'
    }
    if(val === 'confirmPassword'){
      this.isShowEye.confirmPassword = this.isShowEye.confirmPassword === 'password'? '' : 'password'
    }
    
    // nextTick(() => {
    //   confirmPasswordRef.value?.focus()
    // })
}
<style lang="scss" scoped>
.show-pwd {
  position: absolute;
  right: 13px;
  cursor: pointer;
  user-select: none;
  font-size: 16px;
  width: 1.3em;
  height: 1.3em;
  .hide-svg{
    position: absolute;
    top: 3px;
  }
  .view-svg{
    position: absolute;
    top: 5px;
  }
}
</style>

HideSvg.vue

<template>
  <div>
    <svg width="24px"
         height="24px"
         viewBox="0 0 24 24"
         version="1.1"
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink"
    >
      <title>编组 5</title>
      <g id="1"
         stroke="none"
         stroke-width="1"
         fill="none"
         fill-rule="evenodd"
      >
        <g id="登录"
           transform="translate(-1109, -516)"
        >
          <g id="编组-5"
             transform="translate(1109, 516)"
          >
            <g id="编组"
               transform="translate(3, 12)"
               fill="#A8A8A8"
               fill-rule="nonzero"
            >
              <path d="M11.6008268,8 C11.2363797,8 10.9168969,7.73309069 10.8435342,7.366697 L10.3749594,5.0300273 L10.2471662,5.04215954 C9.8353884,5.08340916 9.41414439,5.10524719 8.99763346,5.10524719 C8.59295523,5.10524719 8.18354392,5.08583561 7.78359876,5.04701244 L7.65580564,5.03488019 L7.18959738,7.366697 C7.11623466,7.73309069 6.79675184,8 6.43230478,8 C6.38024091,8 6.32581051,7.9951471 6.27611318,7.98301486 C6.0725908,7.93933879 5.89983342,7.82044283 5.78387299,7.6433121 C5.6702791,7.46618138 5.63004793,7.25508038 5.67264564,7.04640582 L6.12938774,4.76797088 L5.99686154,4.73400061 C5.29873242,4.55686988 4.61480254,4.3166515 3.96163768,4.02062481 L3.86460956,3.97694874 L2.09207157,6.1607522 C1.94534613,6.34273582 1.72762451,6.4470731 1.49570365,6.4470731 C1.31348012,6.4470731 1.1383562,6.38155899 1.00109692,6.26266303 C0.672147949,5.98362147 0.627183701,5.48134668 0.901702268,5.14407037 L2.47071787,3.21019108 L2.33582513,3.1204125 C1.57616599,2.62056415 0.863837638,2.02851077 0.222505468,1.36366394 C0.0781465662,1.21322414 -0.00231577248,1.01182894 0,0.800727934 C0.00241730626,0.589626934 0.0828796449,0.390658174 0.229605086,0.24021838 C0.376330527,0.0922050349 0.568020216,0.00970579315 0.773909142,0.00970579315 C0.982164606,0.00970579315 1.17858737,0.0946314832 1.32531282,0.245071277 C2.07313926,1.02153473 2.92036035,1.67424932 3.84567725,2.18865635 L3.85987648,2.1959357 L3.87644226,2.2007886 C3.98293653,2.22990598 4.08233118,2.28328784 4.1675266,2.35608129 L4.1793593,2.36578708 L4.19355853,2.37306642 C5.09521004,2.8292387 6.05602502,3.15438277 7.05470464,3.33879284 L7.06417079,3.34121929 L7.07363695,3.34121929 C7.1186012,3.34364574 7.16119891,3.34849864 7.20143008,3.35820443 C7.22272893,3.36305732 7.24639433,3.36791022 7.27005972,3.37518957 L7.27952588,3.37761601 L7.28899203,3.38004246 C7.84986187,3.46982105 8.42493093,3.51592357 8.99763346,3.51592357 C9.60346754,3.51592357 10.2116682,3.46496815 10.803303,3.36305732 L10.8080361,3.36305732 C10.8127692,3.36305732 10.8175022,3.36063088 10.8222353,3.36063088 L10.8269684,3.35820443 C10.8530003,3.35335153 10.8790323,3.34849864 10.9050642,3.34607219 L10.9145304,3.34607219 C11.9652738,3.15680922 12.9757861,2.80982712 13.9176688,2.31483167 L13.9247684,2.30997877 L13.9318681,2.30512587 C13.9768323,2.27600849 14.0241631,2.24931756 14.0714939,2.22990598 L14.0785935,2.22747953 L14.0856931,2.22262663 C15.0370419,1.70094025 15.9079284,1.03366697 16.6746872,0.237791932 C16.8214126,0.08492569 17.0178354,0 17.2260909,0 C17.4296132,0 17.6236695,0.0800727934 17.7680284,0.228086139 C17.9147538,0.376099484 17.9975827,0.575068244 18,0.788595693 C18.0023158,0.999696694 17.9218534,1.2010919 17.7774945,1.3515317 C17.1430619,2.01153449 16.4399398,2.5981987 15.6807406,3.10100091 L15.5458479,3.1907795 L17.1290627,5.14164392 C17.4012148,5.47892023 17.3562505,5.97876858 17.0296681,6.26023658 C16.8900423,6.37913254 16.7149184,6.44464665 16.5350614,6.44464665 C16.3031405,6.44464665 16.0854189,6.34030937 15.9386934,6.15832575 L14.1566893,3.9599636 L14.0572946,4.00606612 C13.4064963,4.30451926 12.724933,4.54716409 12.0291704,4.72429481 L11.8966442,4.75826509 L12.3533863,7.04397938 C12.395984,7.25265393 12.3557528,7.46375493 12.2421589,7.64088565 C12.1285651,7.81801638 11.9534411,7.93933879 11.7522853,7.98058841 C11.707321,7.9951471 11.6552572,8 11.6008268,8 L11.6008268,8 Z"
                    id="路径"
              ></path>
            </g>
            <rect id="矩形备份-4"
                  x="0"
                  y="0"
                  width="24"
                  height="24"
            ></rect>
          </g>
        </g>
      </g>
    </svg>
  </div>
</template>

ViewSvg.vue

<template>
  <div>
    <svg width="24px"
         height="24px"
         viewBox="0 0 24 24"
         version="1.1"
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink"
    >
      <title>编组 4</title>
      <g id="1"
         stroke="none"
         stroke-width="1"
         fill="none"
         fill-rule="evenodd"
      >
        <g id="登录备份"
           transform="translate(-1109, -516)"
        >
          <g id="编组-4"
             transform="translate(1109, 516)"
          >
            <g id="编组"
               transform="translate(3, 3)"
               fill="#A8A8A8"
               fill-rule="nonzero"
            >
              <path d="M9.00081164,16 C5.3008667,16 2.16757999,13.046806 0.629507638,11.2852517 C-0.206194212,10.3291139 -0.206194212,8.88548719 0.629507638,7.92934943 C0.922360423,7.59493671 1.22949871,7.26523403 1.54616066,6.94966147 L1.63663551,6.86017074 L0.172371583,5.07742125 C-0.0966720323,4.75007359 -0.0442918594,4.26964969 0.28427468,4.00353253 C0.422367863,3.89284663 0.591412966,3.83397115 0.769981738,3.83397115 C1.0033116,3.83397115 1.22235596,3.93759199 1.36997281,4.11657345 L2.77709473,5.82867236 L2.88899782,5.73918163 C3.46041789,5.27524286 4.04374255,4.86782455 4.62230536,4.5287018 L4.74135121,4.45805122 L3.57470191,2.41389461 C3.36518121,2.04651163 3.49851256,1.58021784 3.86755469,1.37533117 C3.98421962,1.31174566 4.11517005,1.27642037 4.24612049,1.27642037 C4.52468777,1.27642037 4.7818268,1.42478658 4.91991998,1.66499853 L6.13180671,3.78922579 L6.24609072,3.74683544 C6.86989097,3.51133353 7.49607212,3.35354725 8.10558686,3.27583162 L8.22939454,3.25934648 L8.22939454,0.7630262 C8.22939454,0.341477775 8.5746275,0 9.00081164,0 C9.42699577,0 9.77222873,0.341477775 9.77222873,0.7630262 L9.77222873,3.25463644 L9.89603641,3.27112158 C10.5079321,3.34883721 11.1341132,3.50662349 11.7555325,3.7421254 L11.8698166,3.78451575 L13.0817033,1.66028849 C13.2174156,1.42007654 13.4769355,1.27171033 13.7555028,1.27171033 C13.8864532,1.27171033 14.0174037,1.3046806 14.1340686,1.37062114 C14.5054916,1.57786282 14.6364421,2.04415661 14.4269214,2.40918457 L13.2602721,4.45334118 L13.3793179,4.52399176 C13.9578807,4.86311451 14.5412054,5.27053282 15.1126254,5.73447159 L15.2245285,5.82396232 L16.6292695,4.11186341 C16.7768864,3.93288195 16.9935498,3.82926111 17.2292606,3.82926111 C17.4054485,3.82926111 17.5792554,3.89049161 17.7149677,3.99882249 C18.0459151,4.26493965 18.0959144,4.74536356 17.8268708,5.07271122 L16.3626068,6.8554607 L16.4530817,6.94495143 C16.7673627,7.26052399 17.0768819,7.59022667 17.3697347,7.92463939 L17.3887821,7.94583456 C18.2054366,8.90197233 18.1982938,10.3314689 17.3697347,11.2805417 C15.8340433,13.046806 12.7031375,16 9.00081164,16 Z M9.00081164,4.74065352 C8.10082503,4.74065352 7.16036283,4.96673535 6.20323422,5.41183397 L6.19847239,5.41418899 L6.17704413,5.42596409 C6.14609221,5.44244922 6.11037846,5.45893435 6.0746647,5.47306447 L6.06752195,5.47541949 L6.06276012,5.47777451 C5.12944067,5.9322932 4.18183573,6.59405358 3.24613537,7.4465705 L3.24375445,7.44892552 L3.24137353,7.45128054 C3.21756436,7.47483073 3.19613611,7.49602591 3.17232694,7.51486606 L3.16756511,7.51722108 L3.16518419,7.5195761 C2.69614355,7.9505446 2.23662658,8.42390344 1.79853786,8.92552252 C1.46044765,9.31410068 1.46044765,9.89814542 1.79853786,10.2867236 C3.16518419,11.8504563 5.91514327,14.4739476 9.00081164,14.4739476 C12.08648,14.4739476 14.83882,11.8504563 16.2030854,10.2867236 C16.5411756,9.89814542 16.5411756,9.31410068 16.2030854,8.92552252 C15.7673776,8.42625846 15.3102416,7.95525464 14.8412009,7.52428613 L14.8364391,7.5195761 L14.8292963,7.51486606 C14.8054872,7.49367089 14.781678,7.47247571 14.7578688,7.44892552 L14.7554879,7.4465705 L14.7507261,7.44421548 C13.8150257,6.5964086 12.8698017,5.93464822 11.9388632,5.48248455 L11.9317204,5.48012953 L11.9245777,5.47777451 C11.8888639,5.46364439 11.8507692,5.44715926 11.8174364,5.42831911 L11.7960081,5.41654401 L11.7888654,5.41418899 C10.8412604,4.96438034 9.90079824,4.74065352 9.00081164,4.74065352 Z"
                    id="形状"
              ></path>
              <path d="M9,13 C7.3458589,13 6,11.6541411 6,10 C6,8.3458589 7.3458589,7 9,7 C10.6541411,7 12,8.3458589 12,10 C12,11.6541411 10.6541411,13 9,13 Z M9,8.52300613 C8.18558282,8.52300613 7.52300613,9.18558282 7.52300613,10 C7.52300613,10.8144172 8.18558282,11.4769939 9,11.4769939 C9.81441718,11.4769939 10.4769939,10.8144172 10.4769939,10 C10.4769939,9.18558282 9.81441718,8.52300613 9,8.52300613 Z"
                    id="形状"
              ></path>
            </g>
            <rect id="矩形"
                  x="0"
                  y="0"
                  width="24"
                  height="24"
            ></rect>
          </g>
        </g>
      </g>
    </svg>
    
  </div>
</template>

业务页总

<template>
  <el-dialog
    v-model="centerDialogVisible"
    width="404px"
    class="custom-dialog-up"
    :close-on-click-modal="false"
    :show-close="false"
    @close="closeDialog"
    style="border-radius: 20px;"
    destroy-on-close
  >
    <template #title>
      <span style="color: #0075FF;font-size: 16px;font-weight: 500;">修改密码</span>
    </template>
    <el-form
      :model="formData"
      ref="formRef"
      :rules="formRules"
    >
      <el-form-item
        label="请填写原密码:"
        prop="oldPass"
      >
        <el-input
          v-model="formData.oldPass"
          placeholder="请填写原密码"
          ref="oldPassRef"
          name="oldPass"
          autocomplete="on"
          tabindex="1"
          :type="isShowEye.oldPass"
        >
        </el-input>
        <span
          class="show-pwd"
          @click="showOldPass"
        >
          <hide-svg 
            v-if="isShowEye.oldPass"
            class="hide-svg"
          />
          <view-svg v-else />
        </span>
      </el-form-item>
      <el-form-item
        label="请填写新密码:"
        prop="newPass"
      >
        <el-input
          v-model="formData.newPass"
          placeholder="请填写新密码"
          ref="newPassRef"
          name="newPass"
          autocomplete="on"
          tabindex="2"
          :type="isShowEye.newPass"
        >
        </el-input>
        <span
          class="show-pwd"
          @click="showNewPass"
        >
          <hide-svg 
            v-if="isShowEye.newPass"
            class="hide-svg"
          />
          <view-svg v-else />
        </span>
      </el-form-item>
      <el-form-item
        label="请再次确认新密码:"
        prop="confirmPassword"
      >
        <el-input
          v-model="formData.confirmPassword"
          placeholder="请再次输入密码"
          ref="confirmPasswordRef"
          name="confirmPassword"
          autocomplete="on"
          tabindex="3"
          :type="isShowEye.confirmPassword"
        >
        </el-input>
        <span
          class="show-pwd"
          @click="showConfirmPassword"
        >
          <hide-svg 
            v-if="isShowEye.confirmPassword"
            class="hide-svg"
          />
          <view-svg v-else />
        </span>

      </el-form-item>
    </el-form>
    
    <template #footer>
      <span class="dialog-footer">
        <el-button
          type="primary"
          @click="closeDialog"
          round
        >取消</el-button>
        <el-button
          type="primary"
          @click="submit"
          :loading="submitting"
          round
        >确定</el-button>
      </span>
    </template>
    <div 
      class="close-img"
      @click="closeDialog"
    >
      <img :src="UploadClose" />
    </div>
  </el-dialog>
</template>
<script lang="ts" setup>
import { ref, nextTick, shallowRef } from 'vue'
import { ElMessage,type ElInput, type ElForm } from 'element-plus'
import { getPublicKeyApi, updatePasswordApi } from '@/api/login/index'
import { rsa_encrypt } from '@/utils/index'
import ViewSvg  from '@/assets/svg/ViewSvg.vue'
import HideSvg  from '@/assets/svg/HideSvg.vue'
import { useLogin } from '@/hooks'
import { BizResCode } from '@/types/axios/public-json-structure'
import UploadClose from '@/assets/img/upload-close.png'
const { handleLogout } = useLogin()

const formData = ref({
  oldPass: '',
  newPass: '',
  confirmPassword: '',
})
//小眼睛
const isShowEye = ref({
  oldPass: 'password',
  newPass: 'password',
  confirmPassword: 'password',
})
//原密码
const oldPassRef = shallowRef<InstanceType<typeof ElInput>>()
function showOldPass () {
  if (isShowEye.value.oldPass === 'password') {
    isShowEye.value.oldPass = ''
  } else {
    isShowEye.value.oldPass = 'password'
  }
  nextTick(() => {
    oldPassRef.value?.focus()
  })
}
//新密码
const newPassRef = shallowRef<InstanceType<typeof ElInput>>()
function showNewPass () {
  if (isShowEye.value.newPass === 'password') {
    isShowEye.value.newPass = ''
  } else {
    isShowEye.value.newPass = 'password'
  }
  nextTick(() => {
    newPassRef.value?.focus()
  })
}
//确认密码
const confirmPasswordRef = shallowRef<InstanceType<typeof ElInput>>()
function showConfirmPassword () {
  if (isShowEye.value.confirmPassword === 'password') {
    isShowEye.value.confirmPassword = ''
  } else {
    isShowEye.value.confirmPassword = 'password'
  }
  nextTick(() => {
    confirmPasswordRef.value?.focus()
  })
}

function closeFormData () {
  formData.value = {
    oldPass: '',
    newPass: '',
    confirmPassword: '',
  }
}

const centerDialogVisible = ref(false)
function show () {
  centerDialogVisible.value = true
}
function closeDialog () {
  centerDialogVisible.value = false
  formRef.value?.resetFields()
  closeFormData()
}

const formRules = {
  oldPass: [
    { required: true, message: '请输入密码', trigger: 'blur' },
  ],
  newPass: [
    { required: true, message: '请输入新密码', trigger: 'blur' },
    { validator: checkNewPass, trigger: ['blur'] }
  ],
  confirmPassword: [
    { required: true, message: '请再次输入密码', trigger: 'blur' },
    { validator: validataConfirmPassword, trigger: ['blur'] }
  ]
}
function validataConfirmPassword (rule: unknown, value: string,cb: Function) {
  if(!value){
    cb(new Error('请再次输入密码'))
  } else if(value !== formData.value.newPass) {
    cb(new Error('两次密码不一致'))
  } else {
    cb()
  }
}
function checkNewPass (rule: unknown, value: string,cb: Function) {
  const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#¥%&*(){}])[A-Za-z\d!@#¥%&*(){}]{6,}$/
  if(!value){
    cb(new Error('请输入新密码'))
  }else if(value.length < 6 || value.length > 20){
    cb(new Error('密码长度为6-20位'))
  }else if(!regex.test(value)) {
    cb(new Error('密码需包含大小写字母、数字、特殊符号组成  特殊字符包含!@#¥%&*(){}'))
  }else {
    cb()
  }
}

const submitting = ref(false)
const formRef = shallowRef<InstanceType<typeof ElForm>>()
async function submit () {
  const isValid = await formRef?.value?.validate()
  if(isValid){
    //获取rsa加密公钥
    const publicKey = await getPublicKeyApi()
    const query={
      newPassword: rsa_encrypt(formData.value.newPass,publicKey.data),
      oldPassword:rsa_encrypt(formData.value.oldPass,publicKey.data)
    }
    updatePasswordApi(query)
      .then((res: any)=>{
        if(res.code === BizResCode.SUCCESS){
          ElMessage.success('修改成功')
          handleLogout()
        }else {
          ElMessage.error(res.message)
        }
      })
      .catch(err=>{
        ElMessage.error(err.message)
      })
  }
}
defineExpose({
  show,

})
</script>

<style lang="scss" scoped>
.custom-dialog-up {
  position: relative;
  
  :deep(.el-dialog__header) {
    padding: 0 !important;
  }
  :deep(.el-dialog__body) {
    padding: 0 !important;
  }
  .close-img {
    cursor: pointer;
    position: absolute;
    top: -40px;
    right: 0;
  }
}
::v-deep .el-form-item {
  display: block;
}

::v-deep .el-input {
  width: 343px;
  height: 40px;
  .el-input__wrapper{
    border-radius: 10px;
  }
}
.dialog-footer{
  width: 100%;
  display: flex;
  justify-content: center;
  .el-button{
    margin: 0 15px;
    padding: 10px 20px;
  }
}
.show-pwd {
  position: absolute;
  right: 34px;
  cursor: pointer;
  user-select: none;
  font-size: 16px;
  width: 1.3em;
  height: 1.3em;
  .hide-svg{
    position: absolute;
    top: -4px;
  }
}
</style>