【实战分享】分享一个完整的Vue3+Element Plus的手机验证码登录页面源码

  • 原创
  • 作者:程序员三丰
  • 发布时间:2025-07-30 11:16
  • 浏览量:238
继上一篇文章分享的获取验证码功能倒计时的vue3组合式函数,本文分享一个完整的手机验证码登录页面源代码。

效果截图


在线DEMO

源代码

下面的代码块就是一个完整的Vue3+Element Plus的实现的手机验证码登录页面的源代码,支持表单验证,可以直接CV拿来用在自己的项目中。(注意:需要将页面样式中的背景图片换成自己喜欢的图片即可)

<template>
    <div class="page-container">
        <div class="page-container-content">
            <div class="login-box">
                <h2>欢迎登录</h2>
                <el-form ref="formRef" :model="formModel" :rules="formRules">
                    <el-form-item prop="phone">
                        <el-input
                            size="large"
                            v-model="formModel.phone"
                            clearable
                            type="number"
                            placeholder="请输入手机号"
                            @input="onPhoneInput"
                        />
                    </el-form-item>
                    <el-form-item prop="code">
                        <el-row style="width: 100%">
                            <el-col :span="14">
                                <el-input
                                    size="large"
                                    v-model="formModel.code"
                                    clearable
                                    type="number"
                                    @input="onCodeInput"
                                    placeholder="6位短信验证码"
                                />
                            </el-col>
                            <el-col :span="10" style="padding-left: 10px">
                                <el-button size="large" type="primary" plain style="width: 100%" :disabled="countDownWorking" @click="onGetCodeClick">
                                    {{ countDownText }}
                                </el-button>
                            </el-col>
                        </el-row>
                    </el-form-item>
                    <el-button type="primary" size="large" round class="login-submit-btn" @click="submit(formRef)">
                        登录
                    </el-button>
                </el-form>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { ref, reactive } from 'vue'
import type { FormInstance, FormRules } from 'element-plus'
import { useCountDown } from '/@/utils/countDown'

const { startCountDown, countDownText, countDownWorking, showLog } = useCountDown()

showLog.value = true

const onGetCodeClick = () => {
    formRef
        .value!.validateField('phone')
        .then((valid) => {
            if (valid) {
                startCountDown()
            }
        })
        .catch(() => {})
}

interface FormModelType {
    phone: string
    code: string
}

const { t } = useI18n()
const formRef = ref<FormInstance>()
const formModel = reactive<FormModelType>({
    phone: '',
    code: '',
})

const checkPhone = (rule: any, value: any, callback: any) => {
    if (!value || value.trim() === '') {
        callback(new Error('请输入手机号'))
    } else if (!/^(1[3-9])\d{9}$/.test(value.toString())) {
        callback(new Error('手机号格式不正确'))
    } else {
        callback()
    }
}

const formRules = reactive<FormRules<FormModelType>>({
    phone: [{ validator: checkPhone }],
    code: [{ required: true, message: '请输入验证码' }],
})

const submit = async (formEl: FormInstance | undefined) => {
    if (!formEl) return

    await formEl.validate((valid, fields) => {
        if (valid) {
            console.log('submit')
        } else {
            console.log('error submit', fields)
        }
    })
}

const onPhoneInput = (value: string) => {
    formModel.phone = value.slice(0, 11)
}

const onCodeInput = (value: string) => {
    formModel.code = value.slice(0, 6)
}
</script>

<style scoped lang="scss">
.page-container {
    background: #f5f5f5 url(/@/assets/login-bg-snowmountain.jpg) no-repeat center;
    background-attachment: fixed;
    background-size: cover;
    height: 100vh;

    .page-container-content {
        width: 86%;
        height: 100%;
        margin: 0 auto;
        position: relative;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;

        .login-box {
            overflow: hidden;
            width: 430px;
            min-height: 440px;
            padding: 0;
            background: rgba(255, 255, 255, 0.88);
            box-shadow: 3px 5px 13px 0px #3b3838;
            position: relative;
            z-index: 9;
            padding: 30px;
            display: flex;
            flex-direction: column;
            justify-content: center;

            h2 {
                position: relative;
                color: var(--el-color-primary);
                text-align: center;
                margin-bottom: 64px;
                letter-spacing: 10px;
                padding-left: 10px;

                &::after {
                    content: '';
                    position: absolute;
                    bottom: -16px;
                    left: 41%;
                    width: 18%;
                    height: 2px;
                    background-color: var(--el-color-primary);
                }
            }

            :deep(.el-form-item) {
                margin-bottom: 24px;
            }

            .login-submit-btn {
                margin-top: 10px;
                width: 100%;
                :deep(span) {
                    letter-spacing: 12px;
                    margin-left: 12px; // 解决letter-spacing导致按钮文本不居中的问题
                }
            }
        }
    }
}

// 自适应
@media screen and (max-width: 1024px) {
}
@media screen and (max-width: 375px) {
}
@media screen and (max-height: 650px) {
}

// 暗黑模式样式处理
@at-root html.dark {}
</style>

尾语

感谢阅读,以上便是本文所有内容,希望对您有所帮助!

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/91.html

文章归档

推荐文章

buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3