实现效果
实现过程
校验
//密码格式校验
const validateUppercase = (rule, value, callback) => {if (!/[A-Z]/.test(value)) {callback(new Error('密码必须包含至少一个大写字母'));} else {callback();}
};
const validateNumber = (rule, value, callback) => {if (!/\d/.test(value)) {callback(new Error('密码必须包含至少一个数字'));} else {callback();}
};
const validateSpecialCharacter = (rule, value, callback) => {if (!/[~`!@#$%^&*()_\-+={}[\]|;:,<>.?/]/.test(value)) {callback(new Error('密码必须包含至少一个特殊字符'));} else {callback();}
};
源代码
<template><div class="registerform"><h1>注册账户</h1><div class="registerWarp"><el-formlabel-position="top"label-width="100px":model="form"ref="ruleFormRef":rules="rulesForm"hide-required-asteriskclass="register-form"><el-form-item label="邮箱" prop="email"><el-input v-model="form.email" placeholder="电子邮箱" /></el-form-item><el-form-item label="密码" prop="pwd"><el-inputv-model="form.pwd"type="password"show-passwordplaceholder="登录密码"@focus="showTooltip"@blur="hideTooltip"@input="handleInput"/><!-tips提示-><div class="pwdTips" v-show="isPwdShowTips"><p><imgv-show="!isCheck1"src="@/assets/images/register/check-0.svg"/><imgv-show="isCheck1"src="@/assets/images/register/check-1.svg"/><span>6-24个字符</span></p><p><imgv-show="!isCheck2"src="@/assets/images/register/check-0.svg"/><imgv-show="isCheck2"src="@/assets/images/register/check-1.svg"/><span>至少一个大写字母</span></p><p><imgv-show="!isCheck3"src="@/assets/images/register/check-0.svg"/><imgv-show="isCheck3"src="@/assets/images/register/check-1.svg"/><span>至少一个数字</span></p><p><imgv-show="!isCheck4"src="@/assets/images/register/check-0.svg"/><imgv-show="isCheck4"src="@/assets/images/register/check-1.svg"/><span>至少一个特殊字符</span></p><p>特殊字符支持:~`!@#$%^&*()_-+={}[]|;:,<>.?/</p></div></el-form-item><el-form-item><template #label><div class="item-label"><span>填写邀请ID(选填)</span><img:class="{ active: isIdShow }"@click="isIdShow = !isIdShow"src="@/assets/images/register/right-jian.svg"/></div></template><el-inputv-show="isIdShow"v-model="form.parentShortId"placeholder="填写邀请用户ID"/></el-form-item><el-form-item><div class="form-bottom"><div class="promise">点击注册即表示同意<span>服务协议</span>和<span>隐私条款</span></div><divclass="submit-btn"type="primary"@click="submitForm(ruleFormRef)">注册</div><div class="switch-login">已有账户?<span @click="goPath('/login')">去登录</span></div></div></el-form-item></el-form></div></div>
</template><script setup>
import { ref, reactive, defineEmits, watch } from 'vue';
import { emailCodeSend } from '@/api/user';
import { EmailSceneTypeMap } from '@/views/Login/const.js';
import { debounce } from '@/utils';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
const router = useRouter();
const store = useStore();const goPath = (r) => {router.push({path: r});
};
const isIdShow = ref(false);
const ruleFormRef = ref(null);
const form = reactive({email: '',pwd: '',code: '',parentShortId: '',captcha: '123456'
});// 发送验证码
const getEmailCode = debounce(async (val) => {try {await store.dispatch('app/showLoading');let params = {scene: EmailSceneTypeMap['REGISTER'],email: val,captcha: '123456'};const { data } = await emailCodeSend(params);console.log(data);if (data.code == 'Success') {store.dispatch('app/showToast',{msg: '验证码已发送',type: 'success'},{ root: true });emits('stepRouter', { step: 2, form });return data.data.sec;}} catch (error) {console.log('getEmailCode-Error', error);} finally {await store.dispatch('app/hideLoading');}
}, 300);// 密码提示
const isPwdShowTips = ref(false);
const showTooltip = () => {console.log('showTooltip');isPwdShowTips.value = true;handleInput(form.pwd);
};const hideTooltip = () => {console.log('hideTooltip');isPwdShowTips.value = false;
};// 输入框校验
const isCheck1 = ref(false);
const isCheck2 = ref(false);
const isCheck3 = ref(false);
const isCheck4 = ref(false);
const handleInput = (value) => {console.log('handleInput');if (value.length < 6 || value.length > 24) {isCheck1.value = false;} else {isCheck1.value = true;}if (!/[A-Z]/.test(value)) {isCheck2.value = false;} else {isCheck2.value = true;}if (!/\d/.test(value)) {isCheck3.value = false;} else {isCheck3.value = true;}if (!/[~`!@#$%^&*()_\-+={}[\]|;:,<>.?/]/.test(value)) {isCheck4.value = false;} else {isCheck4.value = true;}
};//密码格式校验
const validateUppercase = (rule, value, callback) => {if (!/[A-Z]/.test(value)) {callback(new Error('密码必须包含至少一个大写字母'));} else {callback();}
};
const validateNumber = (rule, value, callback) => {if (!/\d/.test(value)) {callback(new Error('密码必须包含至少一个数字'));} else {callback();}
};
const validateSpecialCharacter = (rule, value, callback) => {if (!/[~`!@#$%^&*()_\-+={}[\]|;:,<>.?/]/.test(value)) {callback(new Error('密码必须包含至少一个特殊字符'));} else {callback();}
};
const rulesForm = reactive({email: [{ required: true, message: '请输入邮箱', trigger: 'blur' },{ type: 'email', message: '邮箱输入格式错误', trigger: 'blur' }],pwd: [{ required: true, message: '请输入密码', trigger: 'blur' },{ min: 6, max: 24, message: '密码长度为6-24个字符', trigger: 'blur' },{ validator: validateUppercase, trigger: 'blur' },{ validator: validateNumber, trigger: 'blur' },{ validator: validateSpecialCharacter, trigger: 'blur' }]
});const emits = defineEmits(['stepRouter']);const submitForm = (formEl) => {if (!formEl) return;formEl.validate((valid) => {if (valid) {console.log('submit!');getEmailCode(form.email);// emits('stepRouter', { step: 2, form });} else {console.log('error submit!');return false;}});
};
</script><style lang="less" scoped>
.registerform {h1 {color: #000;font-family: PingFang SC;font-size: 40px;font-style: normal;font-weight: 600;line-height: normal;margin-bottom: 40px;}.registerWarp {.register-form {
//提示.pwdTips {position: absolute;top: 51px;width: 480px;min-height: 210px;flex-shrink: 0;background-color: #fff;z-index: 1;border-radius: 5px;box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.15);padding: 20px;p {display: flex;align-items: center;color: #000;font-family: PingFang SC;font-size: 14px;font-weight: 400;padding-bottom: 10px;img {margin-right: 11px;}&:last-child {color: #909090;font-family: PingFang SC;font-size: 12px;font-weight: 500;padding-bottom: 0;}}}&.el-form {:deep(.el-form-item__label) {color: #000;font-family: PingFang SC;font-size: 14px;font-style: normal;font-weight: 400;line-height: normal;margin-bottom: 0;}.el-form-item {position: relative;margin-top: 20px;.form-bottom {.promise {color: #000;font-family: PingFang SC;font-size: 14px;font-style: normal;font-weight: 400;line-height: normal;span {color: #3183ff;}}.submit-btn {width: 480px;height: 48px;border-radius: 40px;background: #090909;color: #fff;font-family: PingFang SC;font-size: 14px;font-style: normal;font-weight: 400;line-height: normal;display: flex;justify-content: center;align-items: center;margin-top: 20px;margin-bottom: 30px;user-select: none;cursor: pointer;}.switch-login {color: #000;font-family: PingFang SC;font-size: 14px;font-style: normal;font-weight: 400;line-height: normal;text-align: center;span {color: #3183ff;cursor: pointer;}}}.item-label {display: flex;justify-content: space-between;img {width: 11px;height: 11px;transform: rotate(90deg);transition: transform 0.3s ease;cursor: pointer;&.active {transform: rotate(270deg);}}}.el-input {width: 480px;height: 40px;background: #ffffff;margin-top: 10px;border: 1px solid #ebebeb;border-radius: 4px;::placeholder {font-size: 14px;line-height: 20px;color: #c8c8c8;}}:deep(.el-input__inner) {color: #000;}}}}}
}
</style>