parent
8cf37080f4
commit
2789086138
|
@ -13,6 +13,7 @@
|
|||
"axios": "0.27.2",
|
||||
"clipboard": "2.0.11",
|
||||
"core-js": "3.23.5",
|
||||
"crypto-js": "^4.1.1",
|
||||
"e-icon-picker": "^1.1.7",
|
||||
"echarts": "5.3.3",
|
||||
"element-ui": "2.15.8",
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,270 @@
|
|||
<template>
|
||||
<div
|
||||
style="position: relative"
|
||||
>
|
||||
<div class="verify-img-out">
|
||||
<div
|
||||
class="verify-img-panel"
|
||||
:style="{'width': setSize.imgWidth,
|
||||
'height': setSize.imgHeight,
|
||||
'background-size' : setSize.imgWidth + ' '+ setSize.imgHeight,
|
||||
'margin-bottom': vSpace + 'px'}"
|
||||
>
|
||||
<div v-show="showRefresh" class="verify-refresh" style="z-index:3" @click="refresh">
|
||||
<i class="iconfont icon-refresh" />
|
||||
</div>
|
||||
<img
|
||||
ref="canvas"
|
||||
:src="pointBackImgBase?('data:image/png;base64,'+pointBackImgBase):defaultImg"
|
||||
alt=""
|
||||
style="width:100%;height:100%;display:block"
|
||||
@click="bindingClick?canvasClick($event):undefined"
|
||||
>
|
||||
|
||||
<div
|
||||
v-for="(tempPoint, index) in tempPoints"
|
||||
:key="index"
|
||||
class="point-area"
|
||||
:style="{
|
||||
'background-color':'#1abd6c',
|
||||
color:'#fff',
|
||||
'z-index':9999,
|
||||
width:'20px',
|
||||
height:'20px',
|
||||
'text-align':'center',
|
||||
'line-height':'20px',
|
||||
'border-radius': '50%',
|
||||
position:'absolute',
|
||||
top:parseInt(tempPoint.y-10) + 'px',
|
||||
left:parseInt(tempPoint.x-10) + 'px'
|
||||
}"
|
||||
>
|
||||
{{ index + 1 }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{'width': setSize.imgWidth,
|
||||
'color': barAreaColor,
|
||||
'border-color': barAreaBorderColor,
|
||||
'line-height':barSize.height}"
|
||||
>
|
||||
<span class="verify-msg">{{ text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel">
|
||||
// 文字
|
||||
import { resetSize } from './../utils/util'
|
||||
import { aesEncrypt } from './../utils/ase'
|
||||
import { reqGet, reqCheck } from './../api/index'
|
||||
|
||||
export default {
|
||||
name: 'VerifyPoints',
|
||||
props: {
|
||||
captchaType: {
|
||||
type: String,
|
||||
default: 'clickWord'
|
||||
},
|
||||
// 弹出式pop,固定fixed
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'pop'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '2'
|
||||
},
|
||||
// 间隔
|
||||
vSpace: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
imgSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '155px'
|
||||
}
|
||||
}
|
||||
},
|
||||
barSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '40px'
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
secretKey: '', // 后端返回的ase加密秘钥
|
||||
checkNum: 3, // 默认需要点击的字数
|
||||
fontPos: [], // 选中的坐标信息
|
||||
checkPosArr: [], // 用户点击的坐标
|
||||
num: 1, // 点击的记数
|
||||
pointBackImgBase: '', // 后端获取到的背景图片
|
||||
poinTextList: [], // 后端返回的点击字体顺序
|
||||
backToken: '', // 后端返回的token值
|
||||
setSize: {
|
||||
imgHeight: 0,
|
||||
imgWidth: 0,
|
||||
barHeight: 0,
|
||||
barWidth: 0
|
||||
},
|
||||
tempPoints: [],
|
||||
text: '',
|
||||
barAreaColor: undefined,
|
||||
barAreaBorderColor: undefined,
|
||||
showRefresh: true,
|
||||
bindingClick: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
resetSize() {
|
||||
return resetSize
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// type变化则全面刷新
|
||||
type: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 禁止拖拽
|
||||
this.$el.onselectstart = function() {
|
||||
return false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 加载页面
|
||||
this.fontPos.splice(0, this.fontPos.length)
|
||||
this.checkPosArr.splice(0, this.checkPosArr.length)
|
||||
this.num = 1
|
||||
this.getPictrue()
|
||||
this.$nextTick(() => {
|
||||
this.setSize = this.resetSize(this) // 重新设置宽度高度
|
||||
this.$parent.$emit('ready', this)
|
||||
})
|
||||
},
|
||||
canvasClick(e) {
|
||||
this.checkPosArr.push(this.getMousePos(this.$refs.canvas, e))
|
||||
if (this.num === this.checkNum) {
|
||||
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e))
|
||||
// 按比例转换坐标值
|
||||
this.checkPosArr = this.pointTransfrom(this.checkPosArr, this.setSize)
|
||||
// 等创建坐标执行完
|
||||
setTimeout(() => {
|
||||
// 发送后端请求
|
||||
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify(this.checkPosArr), this.secretKey) : this.backToken + '---' + JSON.stringify(this.checkPosArr)
|
||||
const data = {
|
||||
captchaType: this.captchaType,
|
||||
'pointJson': this.secretKey ? aesEncrypt(JSON.stringify(this.checkPosArr), this.secretKey) : JSON.stringify(this.checkPosArr),
|
||||
'token': this.backToken
|
||||
}
|
||||
reqCheck(data).then(ret => {
|
||||
const res = ret.data
|
||||
if (res.repCode === '0000') {
|
||||
this.barAreaColor = '#4cae4c'
|
||||
this.barAreaBorderColor = '#5cb85c'
|
||||
this.text = '验证成功'
|
||||
this.bindingClick = false
|
||||
if (this.mode === 'pop') {
|
||||
setTimeout(() => {
|
||||
this.$parent.clickShow = false
|
||||
}, 700)
|
||||
}
|
||||
this.$parent.closeBox()
|
||||
this.$parent.$emit('success', { captchaVerification })
|
||||
} else {
|
||||
this.$parent.$emit('error', this)
|
||||
this.barAreaColor = '#d9534f'
|
||||
this.barAreaBorderColor = '#d9534f'
|
||||
this.text = '验证失败'
|
||||
setTimeout(() => {
|
||||
this.refresh()
|
||||
}, 700)
|
||||
}
|
||||
})
|
||||
}, 400)
|
||||
}
|
||||
if (this.num < this.checkNum) {
|
||||
this.num = this.createPoint(this.getMousePos(this.$refs.canvas, e))
|
||||
}
|
||||
},
|
||||
|
||||
// 获取坐标
|
||||
getMousePos: function(obj, e) {
|
||||
var x = e.offsetX
|
||||
var y = e.offsetY
|
||||
return { x, y }
|
||||
},
|
||||
// 创建坐标点
|
||||
createPoint: function(pos) {
|
||||
this.tempPoints.push(Object.assign({}, pos))
|
||||
return ++this.num
|
||||
},
|
||||
refresh: function() {
|
||||
this.tempPoints.splice(0, this.tempPoints.length)
|
||||
this.barAreaColor = '#000'
|
||||
this.barAreaBorderColor = '#ddd'
|
||||
this.bindingClick = true
|
||||
this.fontPos.splice(0, this.fontPos.length)
|
||||
this.checkPosArr.splice(0, this.checkPosArr.length)
|
||||
this.num = 1
|
||||
this.getPictrue()
|
||||
this.text = '验证失败'
|
||||
this.showRefresh = true
|
||||
},
|
||||
|
||||
// 请求背景图片和验证图片
|
||||
getPictrue() {
|
||||
const data = {
|
||||
captchaType: this.captchaType,
|
||||
clientUid: localStorage.getItem('point'),
|
||||
ts: Date.now() // 现在的时间戳
|
||||
}
|
||||
reqGet(data).then(ret => {
|
||||
const res = ret.data
|
||||
if (res.repCode === '0000') {
|
||||
this.pointBackImgBase = res.repData.originalImageBase64
|
||||
this.backToken = res.repData.token
|
||||
this.secretKey = res.repData.secretKey
|
||||
this.poinTextList = res.repData.wordList
|
||||
this.text = '请依次点击【' + this.poinTextList.join(',') + '】'
|
||||
} else {
|
||||
this.text = res.repMsg
|
||||
}
|
||||
|
||||
// 判断接口请求次数是否失效
|
||||
if (res.repCode === '6201') {
|
||||
this.pointBackImgBase = null
|
||||
}
|
||||
}).catch(() => {
|
||||
})
|
||||
},
|
||||
// 坐标转换函数
|
||||
pointTransfrom(pointArr, imgSize) {
|
||||
var newPointArr = pointArr.map(p => {
|
||||
const x = Math.round(310 * p.x / parseInt(imgSize.imgWidth))
|
||||
const y = Math.round(155 * p.y / parseInt(imgSize.imgHeight))
|
||||
return { x, y }
|
||||
})
|
||||
return newPointArr
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,377 @@
|
|||
<template>
|
||||
<div style="position: relative;">
|
||||
<div
|
||||
v-if="type === '2'"
|
||||
class="verify-img-out"
|
||||
:style="{height: (parseInt(setSize.imgHeight) + vSpace) + 'px'}"
|
||||
>
|
||||
<div
|
||||
class="verify-img-panel"
|
||||
:style="{width: setSize.imgWidth,
|
||||
height: setSize.imgHeight,}"
|
||||
>
|
||||
<img :src="backImgBase?('data:image/png;base64,'+backImgBase):defaultImg" alt="" style="width:100%;height:100%;display:block">
|
||||
<div v-show="showRefresh" class="verify-refresh" @click="refresh"><i class="iconfont icon-refresh" />
|
||||
</div>
|
||||
<transition name="tips">
|
||||
<span v-if="tipWords" class="verify-tips" :class="passFlag ?'suc-bg':'err-bg'">{{ tipWords }}</span>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 公共部分 -->
|
||||
<div
|
||||
class="verify-bar-area"
|
||||
:style="{width: setSize.imgWidth,
|
||||
height: barSize.height,
|
||||
'line-height':barSize.height}"
|
||||
>
|
||||
<span class="verify-msg" v-text="text" />
|
||||
<div
|
||||
class="verify-left-bar"
|
||||
:style="{width: (leftBarWidth!==undefined)?leftBarWidth: barSize.height, height: barSize.height, 'border-color': leftBarBorderColor, transaction: transitionWidth}"
|
||||
>
|
||||
<span class="verify-msg" v-text="finishText" />
|
||||
<div
|
||||
class="verify-move-block"
|
||||
:style="{width: barSize.height, height: barSize.height, 'background-color': moveBlockBackgroundColor, left: moveBlockLeft, transition: transitionLeft}"
|
||||
@touchstart="start"
|
||||
@mousedown="start"
|
||||
>
|
||||
<i
|
||||
:class="['verify-icon iconfont', iconClass]"
|
||||
:style="{color: iconColor}"
|
||||
/>
|
||||
<div
|
||||
v-if="type === '2'"
|
||||
class="verify-sub-block"
|
||||
:style="{'width':Math.floor(parseInt(setSize.imgWidth)*47/310)+ 'px',
|
||||
'height': setSize.imgHeight,
|
||||
'top':'-' + (parseInt(setSize.imgHeight) + vSpace) + 'px',
|
||||
'background-size': setSize.imgWidth + ' ' + setSize.imgHeight,
|
||||
}"
|
||||
>
|
||||
<img :src="'data:image/png;base64,'+blockBackImgBase" alt="" style="width:100%;height:100%;display:block">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="text/babel">
|
||||
// 滑动
|
||||
import { aesEncrypt } from './../utils/ase'
|
||||
import { resetSize } from './../utils/util'
|
||||
import { reqGet, reqCheck } from './../api/index'
|
||||
|
||||
export default {
|
||||
name: 'VerifySlide',
|
||||
props: {
|
||||
captchaType: {
|
||||
type: String,
|
||||
default: 'blockPuzzle'
|
||||
},
|
||||
// 弹出式pop,固定fixed
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'pop'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: '2'
|
||||
},
|
||||
vSpace: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
explain: {
|
||||
type: String,
|
||||
default: '向右滑动完成验证'
|
||||
},
|
||||
imgSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '155px'
|
||||
}
|
||||
}
|
||||
},
|
||||
blockSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '50px',
|
||||
height: '50px'
|
||||
}
|
||||
}
|
||||
},
|
||||
barSize: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
width: '310px',
|
||||
height: '40px'
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
secretKey: '', // 后端返回的加密秘钥 字段
|
||||
passFlag: '', // 是否通过的标识
|
||||
backImgBase: '', // 验证码背景图片
|
||||
blockBackImgBase: '', // 验证滑块的背景图片
|
||||
backToken: '', // 后端返回的唯一token值
|
||||
startMoveTime: '', // 移动开始的时间
|
||||
endMovetime: '', // 移动结束的时间
|
||||
tipsBackColor: '', // 提示词的背景颜色
|
||||
tipWords: '',
|
||||
text: '',
|
||||
finishText: '',
|
||||
setSize: {
|
||||
imgHeight: 0,
|
||||
imgWidth: 0,
|
||||
barHeight: 0,
|
||||
barWidth: 0
|
||||
},
|
||||
top: 0,
|
||||
left: 0,
|
||||
moveBlockLeft: undefined,
|
||||
leftBarWidth: undefined,
|
||||
// 移动中样式
|
||||
moveBlockBackgroundColor: undefined,
|
||||
leftBarBorderColor: '#ddd',
|
||||
iconColor: undefined,
|
||||
iconClass: 'icon-right',
|
||||
status: false, // 鼠标状态
|
||||
isEnd: false, // 是否验证完成
|
||||
showRefresh: true,
|
||||
transitionLeft: '',
|
||||
transitionWidth: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
barArea() {
|
||||
return this.$el.querySelector('.verify-bar-area')
|
||||
},
|
||||
resetSize() {
|
||||
return resetSize
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// type变化则全面刷新
|
||||
type: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 禁止拖拽
|
||||
this.$el.onselectstart = function() {
|
||||
return false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.text = this.explain
|
||||
this.getPictrue()
|
||||
this.$nextTick(() => {
|
||||
const setSize = this.resetSize(this) // 重新设置宽度高度
|
||||
for (const key in setSize) {
|
||||
this.$set(this.setSize, key, setSize[key])
|
||||
}
|
||||
this.$parent.$emit('ready', this)
|
||||
})
|
||||
|
||||
var _this = this
|
||||
|
||||
window.removeEventListener('touchmove', function(e) {
|
||||
_this.move(e)
|
||||
})
|
||||
window.removeEventListener('mousemove', function(e) {
|
||||
_this.move(e)
|
||||
})
|
||||
|
||||
// 鼠标松开
|
||||
window.removeEventListener('touchend', function() {
|
||||
_this.end()
|
||||
})
|
||||
window.removeEventListener('mouseup', function() {
|
||||
_this.end()
|
||||
})
|
||||
|
||||
window.addEventListener('touchmove', function(e) {
|
||||
_this.move(e)
|
||||
})
|
||||
window.addEventListener('mousemove', function(e) {
|
||||
_this.move(e)
|
||||
})
|
||||
|
||||
// 鼠标松开
|
||||
window.addEventListener('touchend', function() {
|
||||
_this.end()
|
||||
})
|
||||
window.addEventListener('mouseup', function() {
|
||||
_this.end()
|
||||
})
|
||||
},
|
||||
|
||||
// 鼠标按下
|
||||
start: function(e) {
|
||||
e = e || window.event
|
||||
var x
|
||||
if (!e.touches) { // 兼容PC端
|
||||
x = e.clientX
|
||||
} else { // 兼容移动端
|
||||
x = e.touches[0].pageX
|
||||
}
|
||||
this.startLeft = Math.floor(x - this.barArea.getBoundingClientRect().left)
|
||||
this.startMoveTime = +new Date() // 开始滑动的时间
|
||||
if (this.isEnd === false) {
|
||||
this.text = ''
|
||||
this.moveBlockBackgroundColor = '#337ab7'
|
||||
this.leftBarBorderColor = '#337AB7'
|
||||
this.iconColor = '#fff'
|
||||
e.stopPropagation()
|
||||
this.status = true
|
||||
}
|
||||
},
|
||||
// 鼠标移动
|
||||
move: function(e) {
|
||||
e = e || window.event
|
||||
if (this.status && this.isEnd === false) {
|
||||
var x
|
||||
if (!e.touches) { // 兼容PC端
|
||||
x = e.clientX
|
||||
} else { // 兼容移动端
|
||||
x = e.touches[0].pageX
|
||||
}
|
||||
var bar_area_left = this.barArea.getBoundingClientRect().left
|
||||
var move_block_left = x - bar_area_left // 小方块相对于父元素的left值
|
||||
if (move_block_left >= this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2) {
|
||||
move_block_left = this.barArea.offsetWidth - parseInt(parseInt(this.blockSize.width) / 2) - 2
|
||||
}
|
||||
if (move_block_left <= 0) {
|
||||
move_block_left = parseInt(parseInt(this.blockSize.width) / 2)
|
||||
}
|
||||
// 拖动后小方块的left值
|
||||
this.moveBlockLeft = (move_block_left - this.startLeft) + 'px'
|
||||
this.leftBarWidth = (move_block_left - this.startLeft) + 'px'
|
||||
}
|
||||
},
|
||||
|
||||
// 鼠标松开
|
||||
end: function() {
|
||||
this.endMovetime = +new Date()
|
||||
var _this = this
|
||||
// 判断是否重合
|
||||
if (this.status && this.isEnd === false) {
|
||||
var moveLeftDistance = parseInt((this.moveBlockLeft || '').replace('px', ''))
|
||||
moveLeftDistance = moveLeftDistance * 310 / parseInt(this.setSize.imgWidth)
|
||||
const data = {
|
||||
captchaType: this.captchaType,
|
||||
'pointJson': this.secretKey ? aesEncrypt(JSON.stringify({ x: moveLeftDistance, y: 5.0 }), this.secretKey) : JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||
'token': this.backToken
|
||||
}
|
||||
reqCheck(data).then(ret => {
|
||||
const res = ret.data
|
||||
if (res.repCode === '0000') {
|
||||
this.moveBlockBackgroundColor = '#5cb85c'
|
||||
this.leftBarBorderColor = '#5cb85c'
|
||||
this.iconColor = '#fff'
|
||||
this.iconClass = 'icon-check'
|
||||
this.showRefresh = false
|
||||
this.isEnd = true
|
||||
if (this.mode === 'pop') {
|
||||
setTimeout(() => {
|
||||
this.$parent.clickShow = false
|
||||
}, 1500)
|
||||
}
|
||||
this.passFlag = true
|
||||
this.tipWords = `${((this.endMovetime - this.startMoveTime) / 1000).toFixed(2)}s验证成功`
|
||||
var captchaVerification = this.secretKey ? aesEncrypt(this.backToken + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 }), this.secretKey) : this.backToken + '---' + JSON.stringify({ x: moveLeftDistance, y: 5.0 })
|
||||
setTimeout(() => {
|
||||
this.tipWords = ''
|
||||
this.$parent.closeBox()
|
||||
this.$parent.$emit('success', { captchaVerification })
|
||||
}, 700)
|
||||
} else {
|
||||
this.moveBlockBackgroundColor = '#d9534f'
|
||||
this.leftBarBorderColor = '#d9534f'
|
||||
this.iconColor = '#fff'
|
||||
this.iconClass = 'icon-close'
|
||||
this.passFlag = false
|
||||
setTimeout(function() {
|
||||
_this.refresh()
|
||||
}, 1000)
|
||||
this.$parent.$emit('error', this)
|
||||
this.tipWords = '验证失败'
|
||||
setTimeout(() => {
|
||||
this.tipWords = ''
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
this.status = false
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
this.showRefresh = true
|
||||
this.finishText = ''
|
||||
|
||||
this.transitionLeft = 'left .3s'
|
||||
this.moveBlockLeft = 0
|
||||
|
||||
this.leftBarWidth = undefined
|
||||
this.transitionWidth = 'width .3s'
|
||||
|
||||
this.leftBarBorderColor = '#ddd'
|
||||
this.moveBlockBackgroundColor = '#fff'
|
||||
this.iconColor = '#000'
|
||||
this.iconClass = 'icon-right'
|
||||
this.isEnd = false
|
||||
|
||||
this.getPictrue()
|
||||
setTimeout(() => {
|
||||
this.transitionWidth = ''
|
||||
this.transitionLeft = ''
|
||||
this.text = this.explain
|
||||
}, 300)
|
||||
},
|
||||
|
||||
// 请求背景图片和验证图片
|
||||
getPictrue() {
|
||||
const data = {
|
||||
captchaType: this.captchaType,
|
||||
clientUid: localStorage.getItem('slider'),
|
||||
ts: Date.now() // 现在的时间戳
|
||||
}
|
||||
reqGet(data).then(ret => {
|
||||
const res = ret.data
|
||||
if (res.repCode === '0000') {
|
||||
this.backImgBase = res.repData.originalImageBase64
|
||||
this.blockBackImgBase = res.repData.jigsawImageBase64
|
||||
this.backToken = res.repData.token
|
||||
this.secretKey = res.repData.secretKey
|
||||
} else {
|
||||
this.tipWords = res.repMsg
|
||||
}
|
||||
|
||||
// 判断接口请求次数是否失效
|
||||
if (res.repCode === '6201') {
|
||||
this.backImgBase = null
|
||||
this.blockBackImgBase = null
|
||||
}
|
||||
}).catch(() => {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import request from '@/utils/request'
|
||||
// 登录退出
|
||||
const url = '/admin/admin.Login/'
|
||||
|
||||
// 获取验证图片以及token
|
||||
export function reqGet(params) {
|
||||
return request({
|
||||
url: url + 'captcha',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
}
|
||||
|
||||
// 滑动或者点选验证
|
||||
export function reqCheck(data) {
|
||||
return request({
|
||||
url: url + 'captcha',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,11 @@
|
|||
import CryptoJS from 'crypto-js'
|
||||
/**
|
||||
* @word 要加密的内容
|
||||
* @keyWord String 服务器随机返回的关键字
|
||||
* */
|
||||
export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') {
|
||||
var key = CryptoJS.enc.Utf8.parse(keyWord)
|
||||
var srcs = CryptoJS.enc.Utf8.parse(word)
|
||||
var encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
|
||||
return encrypted.toString()
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
export function resetSize(vm) {
|
||||
var img_width, img_height, bar_width, bar_height // 图片的宽度、高度,移动条的宽度、高度
|
||||
|
||||
var parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
|
||||
var parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
|
||||
|
||||
if (vm.imgSize.width.indexOf('%') !== -1) {
|
||||
img_width = parseInt(this.imgSize.width) / 100 * parentWidth + 'px'
|
||||
} else {
|
||||
img_width = this.imgSize.width
|
||||
}
|
||||
|
||||
if (vm.imgSize.height.indexOf('%') !== -1) {
|
||||
img_height = parseInt(this.imgSize.height) / 100 * parentHeight + 'px'
|
||||
} else {
|
||||
img_height = this.imgSize.height
|
||||
}
|
||||
|
||||
if (vm.barSize.width.indexOf('%') !== -1) {
|
||||
bar_width = parseInt(this.barSize.width) / 100 * parentWidth + 'px'
|
||||
} else {
|
||||
bar_width = this.barSize.width
|
||||
}
|
||||
|
||||
if (vm.barSize.height.indexOf('%') !== -1) {
|
||||
bar_height = parseInt(this.barSize.height) / 100 * parentHeight + 'px'
|
||||
} else {
|
||||
bar_height = this.barSize.height
|
||||
}
|
||||
|
||||
return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height }
|
||||
}
|
||||
|
||||
export const _code_chars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
|
||||
export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
|
||||
export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']
|
|
@ -5,9 +5,18 @@
|
|||
<el-switch v-model="model.captcha_switch" :active-value="1" :inactive-value="0" />
|
||||
<span style="margin-left:180px">开启后,后台登录需要输入验证码。</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="验证码方式" prop="captcha_mode">
|
||||
<el-select v-model="model.captcha_mode" placeholder="" @change="moldChange">
|
||||
<el-option v-for="item in mold" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<span>字符:输入字符;行为:滑动或点击。</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="验证码类型" prop="captcha_type">
|
||||
<el-select v-model="model.captcha_type" placeholder="">
|
||||
<el-option v-for="item in type" :key="item.value" :label="item.label" :value="item.value" />
|
||||
<el-select v-if="model.captcha_mode==1" v-model="model.captcha_type" placeholder="">
|
||||
<el-option v-for="item in typestr" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-select v-else v-model="model.captcha_type" placeholder="">
|
||||
<el-option v-for="item in typeaj" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
|
@ -32,15 +41,24 @@ export default {
|
|||
loading: false,
|
||||
model: {
|
||||
captcha_switch: 0,
|
||||
captcha_mode: 1,
|
||||
captcha_type: 1
|
||||
},
|
||||
rules: {},
|
||||
type: [
|
||||
mold: [
|
||||
{ value: 1, label: '字符' },
|
||||
{ value: 2, label: '行为' }
|
||||
],
|
||||
typestr: [
|
||||
{ value: 1, label: '数字' },
|
||||
{ value: 2, label: '字母' },
|
||||
{ value: 3, label: '数字字母' },
|
||||
{ value: 4, label: '算术' },
|
||||
{ value: 5, label: '中文' }
|
||||
],
|
||||
typeaj: [
|
||||
{ value: 1, label: '滑动' },
|
||||
{ value: 2, label: '文字' }
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -79,6 +97,9 @@ export default {
|
|||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
moldChange(value) {
|
||||
this.model.captcha_type = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<el-form-item prop="password">
|
||||
<el-input v-model="model.password" type="password" placeholder="请输入密码" prefix-icon="el-icon-lock" autocomplete="on" clearable show-password />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="captcha_switch" prop="captcha_code">
|
||||
<el-form-item v-if="captcha_switch && captcha_src" prop="captcha_code">
|
||||
<el-col :span="13">
|
||||
<el-input v-model="model.captcha_code" placeholder="请输入验证码" prefix-icon="el-icon-picture" autocomplete="off" clearable />
|
||||
</el-col>
|
||||
|
@ -24,18 +24,29 @@
|
|||
<el-image class="login-captcha" :src="captcha_src" fit="fill" alt="验证码" title="点击刷新验证码" @click="captcha" />
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px" @click.native.prevent="handleLogin">登录</el-button>
|
||||
<AjCaptcha
|
||||
v-if="captcha_switch && captcha_mode==2"
|
||||
ref="ajcaptcha"
|
||||
mode="pop"
|
||||
:captcha-type="captcha_type"
|
||||
:img-size="{ width: '330px', height: '155px' }"
|
||||
@success="ajcaptchaSuccess"
|
||||
/>
|
||||
|
||||
<el-button v-if="captcha_switch && captcha_mode==2" :loading="loading" type="primary" style="width:100%;margin-bottom:30px" @click="ajcaptchaShow">登录</el-button>
|
||||
<el-button v-else :loading="loading" type="primary" style="width:100%;margin-bottom:30px" @click.native.prevent="handleLogin">登录</el-button>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AjCaptcha from '@/components/AjCaptcha'
|
||||
import { captcha, setting } from '@/api/admin/login'
|
||||
import { delNotice } from '@/utils/settings'
|
||||
|
||||
export default {
|
||||
name: 'AdminLogin',
|
||||
components: {},
|
||||
components: { AjCaptcha },
|
||||
data() {
|
||||
return {
|
||||
name: '登录',
|
||||
|
@ -44,6 +55,8 @@ export default {
|
|||
redirect: undefined,
|
||||
otherQuery: {},
|
||||
captcha_switch: 0,
|
||||
captcha_mode: 1,
|
||||
captcha_type: 'blockPuzzle',
|
||||
captcha_src: '',
|
||||
logo_url: '',
|
||||
login_bg_url: '',
|
||||
|
@ -51,7 +64,8 @@ export default {
|
|||
username: '',
|
||||
password: '',
|
||||
captcha_id: '',
|
||||
captcha_code: ''
|
||||
captcha_code: '',
|
||||
ajcaptcha: {}
|
||||
},
|
||||
rules: {
|
||||
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
|
||||
|
@ -81,31 +95,53 @@ export default {
|
|||
// 验证码
|
||||
captcha() {
|
||||
captcha().then(res => {
|
||||
this.captchaSet(res)
|
||||
this.captchaData(res.data)
|
||||
})
|
||||
},
|
||||
captchaSet(res) {
|
||||
captchaData(data) {
|
||||
this.model.captcha_id = ''
|
||||
this.model.captcha_code = ''
|
||||
if (res.data.captcha_switch) {
|
||||
this.captcha_src = res.data.captcha_src
|
||||
this.model.captcha_id = res.data.captcha_id
|
||||
if (data.captcha_switch) {
|
||||
if (data.captcha_mode === 1) {
|
||||
this.captcha_src = data.captcha_src
|
||||
this.model.captcha_id = data.captcha_id
|
||||
}
|
||||
}
|
||||
this.captcha_switch = res.data.captcha_switch
|
||||
this.captcha_switch = data.captcha_switch
|
||||
this.captcha_mode = data.captcha_mode
|
||||
if (data.captcha_type === 1) {
|
||||
this.captcha_type = 'blockPuzzle'
|
||||
} else {
|
||||
this.captcha_type = 'clickWord'
|
||||
}
|
||||
},
|
||||
ajcaptchaSuccess(params) {
|
||||
this.model.ajcaptcha = params
|
||||
this.handleLogin()
|
||||
},
|
||||
ajcaptchaShow() {
|
||||
this.$refs['ref'].validate(valid => {
|
||||
if (valid) {
|
||||
this.$refs.ajcaptcha.show()
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
// 设置
|
||||
setting() {
|
||||
this.model.captcha_id = ''
|
||||
this.model.captcha_code = ''
|
||||
setting().then(res => {
|
||||
this.captchaSet(res)
|
||||
this.login_bg_url = res.data.login_bg_url
|
||||
this.system_name = res.data.system_name
|
||||
this.logo_url = res.data.logo_url
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'systemName', value: res.data.system_name })
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'pageTitle', value: res.data.page_title })
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'logoUrl', value: res.data.logo_url })
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'faviconUrl', value: res.data.favicon_url })
|
||||
const data = res.data
|
||||
this.captchaData(data)
|
||||
this.login_bg_url = data.login_bg_url
|
||||
this.system_name = data.system_name
|
||||
this.logo_url = data.logo_url
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'systemName', value: data.system_name })
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'pageTitle', value: data.page_title })
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'logoUrl', value: data.logo_url })
|
||||
this.$store.dispatch('settings/changeSetting', { key: 'faviconUrl', value: data.favicon_url })
|
||||
})
|
||||
},
|
||||
// 登录
|
||||
|
|
Loading…
Reference in New Issue