From 673d58023f4c0fe8633a107238ec8b577496717a Mon Sep 17 00:00:00 2001 From: Crunchy <3114200645@qq.com> Date: 星期四, 07 十一月 2024 10:28:30 +0800 Subject: [PATCH] 添加登录验证码 --- src/page/login/LoginCode.vue | 131 +++++++++++++++++++++++++++++++++++++++++++ src/page/login/userlogin.vue | 49 ++++++++++++++- 2 files changed, 175 insertions(+), 5 deletions(-) diff --git a/src/page/login/LoginCode.vue b/src/page/login/LoginCode.vue new file mode 100644 index 0000000..e2b4d40 --- /dev/null +++ b/src/page/login/LoginCode.vue @@ -0,0 +1,131 @@ +<template> + <div class="s-canvas" @click="$emit('refresh')"> + <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas> + </div> +</template> +<script> +export default { + name: 'LoginCode', + props: { + identifyCode: { + // 榛樿娉ㄥ唽鐮� + type: String, + default: '1234', + }, + fontSizeMin: { + // 瀛椾綋鏈�灏忓�� + type: Number, + default: 25, + }, + fontSizeMax: { + // 瀛椾綋鏈�澶у�� + type: Number, + default: 35, + }, + backgroundColorMin: { + // 楠岃瘉鐮佸浘鐗囪儗鏅壊鏈�灏忓�� + type: Number, + default: 200, + }, + backgroundColorMax: { + // 楠岃瘉鐮佸浘鐗囪儗鏅壊鏈�澶у�� + type: Number, + default: 220, + }, + dotColorMin: { + // 鑳屾櫙骞叉壈鐐规渶灏忓�� + type: Number, + default: 60, + }, + dotColorMax: { + // 鑳屾櫙骞叉壈鐐规渶澶у�� + type: Number, + default: 120, + }, + contentWidth: { + // 瀹瑰櫒瀹藉害 + type: Number, + default: 90, + }, + contentHeight: { + // 瀹瑰櫒楂樺害 + type: Number, + default: 38, + }, + }, + methods: { + // 鐢熸垚涓�涓殢鏈烘暟 + randomNum(min, max) { + return Math.floor(Math.random() * (max - min) + min) + }, + + // 鐢熸垚涓�涓殢鏈虹殑棰滆壊 + randomColor(min, max) { + const r = this.randomNum(min, max) + const g = this.randomNum(min, max) + const b = this.randomNum(min, max) + return 'rgb(' + r + ',' + g + ',' + b + ')' + }, + // 鐢诲浘 + drawPic() { + const canvas = document.getElementById('s-canvas') + // 鍒涘缓涓�涓�2D瀵硅薄浣滀负涓婁笅鏂囥�� + const ctx = canvas.getContext('2d') + ctx.textBaseline = 'bottom' + // 缁樺埗鑳屾櫙 + ctx.fillStyle = '#e6ecfd' + ctx.fillRect(0, 0, this.contentWidth, this.contentHeight) + // 缁樺埗鏂囧瓧 + for (let i = 0; i < this.identifyCode.length; i++) { + this.drawText(ctx, this.identifyCode[i], i) + } + this.drawLine(ctx) + this.drawDot(ctx) + }, + // 鍦ㄧ敾甯冧笂鏄剧ず鏁版嵁 + drawText(ctx, txt, i) { + ctx.fillStyle = this.randomColor(50, 160) // 闅忔満鐢熸垚瀛椾綋棰滆壊 + ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei' // 闅忔満鐢熸垚瀛椾綋澶у皬 + const x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1)) + const y = this.randomNum(this.fontSizeMax, this.contentHeight - 5) + var deg = this.randomNum(-30, 30) + // 淇敼鍧愭爣鍘熺偣鍜屾棆杞搴� + ctx.translate(x, y) + ctx.rotate((deg * Math.PI) / 180) + ctx.fillText(txt, 0, 0) + // 鎭㈠鍧愭爣鍘熺偣鍜屾棆杞搴� + ctx.rotate((-deg * Math.PI) / 180) + ctx.translate(-x, -y) + }, + + // 缁樺埗骞叉壈绾� + drawLine(ctx) { + for (let i = 0; i < 4; i++) { + ctx.strokeStyle = this.randomColor(100, 200) + ctx.beginPath() + ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) + ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) + ctx.stroke() + } + }, + + // 缁樺埗骞叉壈鐐� + drawDot(ctx) { + for (let i = 0; i < 30; i++) { + ctx.fillStyle = this.randomColor(0, 255) + ctx.beginPath() + ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI) + ctx.fill() + } + }, + }, + watch: { + identifyCode() { + this.drawPic() + }, + }, + mounted() { + this.drawPic() + }, +} +</script> diff --git a/src/page/login/userlogin.vue b/src/page/login/userlogin.vue index 179116e..928a509 100644 --- a/src/page/login/userlogin.vue +++ b/src/page/login/userlogin.vue @@ -35,6 +35,25 @@ <i slot="prefix" class="iconfont icon-mima"></i> </el-input> </el-form-item> + <el-form-item prop="loginCode"> + <el-col :span="16"> + <el-input + v-model="loginCode" + size="small" + auto-complete="off" + placeholder="璇疯緭鍏ラ獙璇佺爜" + @keyup.enter.native="handleLogin" + > + </el-input> + </el-col> + <el-col :span="6" :offset="2"> + <login-code + :key="refreshKey" + :identifyCode="loginCodeValue" + @refresh="refreshLoginValueCode" + /> + </el-col> + </el-form-item> <el-form-item> <el-button type="primary" @@ -51,16 +70,14 @@ </template> <script> -import { randomLenNum } from '@/util/util' import { mapGetters } from 'vuex' -import { getCode } from '@/api/code' -import Verify from '@/components/verifition/Verify' import { getSsoAuthUrl } from '@/api/login' +import LoginCode from '@/page/login/LoginCode.vue' export default { name: 'Userlogin', components: { - Verify + LoginCode }, data() { return { @@ -89,7 +106,12 @@ ] }, passwordType: 'password', - SSO: window.location.hash + SSO: window.location.hash, + loginCode: null, + loginCodeValue: Math.random() + .toString(36) + .substr(2, 4), + refreshKey: 0 } }, created() { @@ -112,11 +134,21 @@ : (this.passwordType = '') }, handleLogin() { + if (!this.loginCode) { + this.$message.error('璇疯緭鍏ラ獙璇佺爜') + return + } + if (this.loginCode.toLowerCase() !== this.loginCodeValue) { + this.$message.error('楠岃瘉鐮佷笉姝g‘') + return + } this.$refs.loginForm.validate((valid) => { if (valid) { this.$store.dispatch('LoginByUsername', this.loginForm).then(() => { this.$router.push({ path: this.tagWel.value }) }) + } else { + this.refreshLoginValueCode() } }) }, @@ -127,6 +159,13 @@ this.$router.push({ path: this.tagWel.value }) }) } + }, + // 鍒锋柊楠岃瘉鐮� + refreshLoginValueCode() { + this.loginCodeValue = Math.random() + .toString(36) + .substr(2, 4) + this.refreshKey++ } } } -- Gitblit v1.9.3