springboot+vue前后端分离项目-项目搭建10-验证码功能
本次演示的验证码功能只涉及前端,而且功能简单
1. 新建vue/src/components/ValidCode.vue
<template> <div class="ValidCode disabled-select" :style="`width:${width}; height:${height}`" @click="refreshCode" > <span v-for="(item, index) in codelist" :key="index" :style="getStyle(item)" >{{ item.code }}</span> </div> </template> <script> export default { name: "ValidCode", model: { prop: 'value', event: 'input' }, props: { width: { type: String, default: '100px' }, height: { type: String, default: '40px' }, length: { type: Number, default: 4 }, refresh: { type: Number } }, data(){ return{ codelist: [] } }, watch: { refresh(){ this.createdCode() } }, mounted() { this.createdCode() }, methods: { refreshCode(){ this.createdCode() }, createdCode(){ const len = this.length const codeList = [] const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' const charsLen = chars.length //生成 for (let i = 0; i < len; i++){ const rgb = [Math.round(Math.random() * 220),Math.round(Math.random() * 240),Math.round(Math.random() * 220)] codeList.push({ code: chars.charAt(Math.floor(Math.random() * charsLen)), color: `rgb(${rgb})`, fontSize: `${10 + (+[Math.floor(Math.random() * 10)] + 6)}px`, padding: `${[Math.floor(Math.random() * 10)]}px`, transform: `rotate(${Math.floor(Math.random() * 90) - Math.floor(Math.random() * 90)}deg)` }) } // 指向 this.codelist = codeList // 将当前数据派发出去 // console.log(codeList.map(item +> item.code).join('')) this.$emit('input', codeList.map(item => item.code).join('')) }, getStyle (data) { return `color: ${data.color}; font-size: ${data.fontSize}; padding: ${data.padding}: transform: ${data.transform}` } } } </script> <style scoped> .ValidCode{ display: flex; justify-content: center; align-items: center; cursor: pointer; } .ValidCode span{ display: inline-block; } </style>
2. vue/src/views/LoginView.vue里引用
<template> <div style="width: 100%; height: 100vh; background-color: darkslateblue; overflow: hidden"> <div style="width: 400px; margin: 150px auto"> <div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0">欢迎登录</div> <el-form label-position="right" :model="form" size="normal" :rules="rules" ref="form"> <el-form-item prop="username"> <el-input :prefix-icon="Avatar" v-model="form.username" placeholder="请输入账号"/> </el-form-item> <el-form-item prop="password"> <el-input :prefix-icon="Lock" v-model="form.password" show-password placeholder="请输入密码"/> </el-form-item> <el-form-item> <div style="display: flex"> <el-input :prefix-icon="Key" v-model="form.validCode" style="width: 50%" placeholder="请输入验证码"/> <ValidCode @input="createValidCode"/> </div> </el-form-item> <el-form-item> <el-radio v-model="form.role" :label="1">管理员</el-radio> <el-radio v-model="form.role" :label="2">普通用户</el-radio> </el-form-item> <el-form-item> <el-button style="width: 100%;" type="primary" @click="login">登 录</el-button> </el-form-item> </el-form> </div> </div> </template> <script> import request from "@/utils/request"; import ValidCode from "@/components/ValidCode.vue"; export default { name: "LoginView", components: { ValidCode }, data(){ return { form: {role: 1}, rules: { username: [ { required: true, message: '请输入用户名', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' } ] }, validCode: '' } }, created() { sessionStorage.removeItem("user") }, methods: { // 接收验证码组件提交的4位验证码 createValidCode(data){ this.validCode = data }, login() { this.$refs.form.validate((valid) => { if(valid){ if(!this.form.validCode) { this.$message.error("请填写验证码") return } if(this.form.validCode.toLowerCase() !== this.validCode.toLowerCase()) { this.$message.error("验证码错误") return } request.post("/user/login", this.form).then(res => { console.log(res) if (res.code === '0') { this.$message({ type: "success", message: "登录成功" }) sessionStorage.setItem("user", JSON.stringify(res.data)) this.$router.push("/user") //登陆成功后跳转到主页 } else { this.$message({ type: "error", message: res.msg }) } }) } }); } } } </script> <script setup> import { Avatar,Lock,Key } from '@element-plus/icons-vue' </script> <style scoped> </style>
效果:
以上仅供参考,如有疑问,留言联系
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通