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