集成登录验证码AJ-Captcha
@@ -19,6 +19,7 @@
|
|||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"css-color-function": "^1.3.3",
|
"css-color-function": "^1.3.3",
|
||||||
"echarts": "^5.4.3",
|
"echarts": "^5.4.3",
|
||||||
"element-plus": "^2.4.2",
|
"element-plus": "^2.4.2",
|
||||||
|
440
admin/src/components/verifition/Verify.vue
Normal file
297
admin/src/components/verifition/Verify/VerifyPoints.vue
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
<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
|
||||||
|
class="verify-refresh"
|
||||||
|
style="z-index: 3"
|
||||||
|
@click="refresh"
|
||||||
|
v-show="showRefresh"
|
||||||
|
>
|
||||||
|
<i class="iconfont icon-refresh"></i>
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
:src="'data:image/png;base64,' + pointBackImgBase"
|
||||||
|
ref="canvas"
|
||||||
|
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>
|
||||||
|
<!-- 'height': this.barSize.height, -->
|
||||||
|
<div
|
||||||
|
class="verify-bar-area"
|
||||||
|
:style="{
|
||||||
|
width: setSize.imgWidth,
|
||||||
|
color: this.barAreaColor,
|
||||||
|
'border-color': this.barAreaBorderColor,
|
||||||
|
'line-height': this.barSize.height
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<span class="verify-msg">{{ text }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script type="text/babel">
|
||||||
|
/**
|
||||||
|
* VerifyPoints
|
||||||
|
* @description 点选
|
||||||
|
* */
|
||||||
|
import { resetSize, _code_chars, _code_color1, _code_color2 } from './../utils/util'
|
||||||
|
import { aesEncrypt } from './../utils/ase'
|
||||||
|
import { reqGet, reqCheck } from './../api/index'
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
onMounted,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
toRefs,
|
||||||
|
watchEffect,
|
||||||
|
getCurrentInstance
|
||||||
|
} from 'vue'
|
||||||
|
export default {
|
||||||
|
name: 'VerifyPoints',
|
||||||
|
props: {
|
||||||
|
//弹出式pop,固定fixed
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'fixed'
|
||||||
|
},
|
||||||
|
captchaType: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
//间隔
|
||||||
|
vSpace: {
|
||||||
|
type: Number,
|
||||||
|
default: 5
|
||||||
|
},
|
||||||
|
imgSize: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
width: '310px',
|
||||||
|
height: '155px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
barSize: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {
|
||||||
|
width: '310px',
|
||||||
|
height: '40px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(props, context) {
|
||||||
|
const { mode, captchaType, vSpace, imgSize, barSize } = toRefs(props)
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const secretKey = ref(''), //后端返回的ase加密秘钥
|
||||||
|
checkNum = ref(3), //默认需要点击的字数
|
||||||
|
fontPos = reactive([]), //选中的坐标信息
|
||||||
|
checkPosArr = reactive([]), //用户点击的坐标
|
||||||
|
num = ref(1), //点击的记数
|
||||||
|
pointBackImgBase = ref(''), //后端获取到的背景图片
|
||||||
|
poinTextList = reactive([]), //后端返回的点击字体顺序
|
||||||
|
backToken = ref(''), //后端返回的token值
|
||||||
|
setSize = reactive({
|
||||||
|
imgHeight: 0,
|
||||||
|
imgWidth: 0,
|
||||||
|
barHeight: 0,
|
||||||
|
barWidth: 0
|
||||||
|
}),
|
||||||
|
tempPoints = reactive([]),
|
||||||
|
text = ref(''),
|
||||||
|
barAreaColor = ref(undefined),
|
||||||
|
barAreaBorderColor = ref(undefined),
|
||||||
|
showRefresh = ref(true),
|
||||||
|
bindingClick = ref(true)
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
//加载页面
|
||||||
|
fontPos.splice(0, fontPos.length)
|
||||||
|
checkPosArr.splice(0, checkPosArr.length)
|
||||||
|
num.value = 1
|
||||||
|
getPictrue()
|
||||||
|
nextTick(() => {
|
||||||
|
const { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
|
||||||
|
setSize.imgHeight = imgHeight
|
||||||
|
setSize.imgWidth = imgWidth
|
||||||
|
setSize.barHeight = barHeight
|
||||||
|
setSize.barWidth = barWidth
|
||||||
|
proxy.$parent.$emit('ready', proxy)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
// 禁止拖拽
|
||||||
|
init()
|
||||||
|
proxy.$el.onselectstart = function () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const canvas = ref(null)
|
||||||
|
const canvasClick = (e) => {
|
||||||
|
checkPosArr.push(getMousePos(canvas, e))
|
||||||
|
if (num.value == checkNum.value) {
|
||||||
|
num.value = createPoint(getMousePos(canvas, e))
|
||||||
|
//按比例转换坐标值
|
||||||
|
const arr = pointTransfrom(checkPosArr, setSize)
|
||||||
|
checkPosArr.length = 0
|
||||||
|
checkPosArr.push(...arr)
|
||||||
|
//等创建坐标执行完
|
||||||
|
setTimeout(() => {
|
||||||
|
// var flag = this.comparePos(this.fontPos, this.checkPosArr);
|
||||||
|
//发送后端请求
|
||||||
|
const captchaVerification = secretKey.value
|
||||||
|
? aesEncrypt(
|
||||||
|
backToken.value + '---' + JSON.stringify(checkPosArr),
|
||||||
|
secretKey.value
|
||||||
|
)
|
||||||
|
: backToken.value + '---' + JSON.stringify(checkPosArr)
|
||||||
|
const data = {
|
||||||
|
captchaType: captchaType.value,
|
||||||
|
pointJson: secretKey.value
|
||||||
|
? aesEncrypt(JSON.stringify(checkPosArr), secretKey.value)
|
||||||
|
: JSON.stringify(checkPosArr),
|
||||||
|
token: backToken.value
|
||||||
|
}
|
||||||
|
reqCheck(data).then((res) => {
|
||||||
|
if (res.repCode == '0000') {
|
||||||
|
barAreaColor.value = '#4cae4c'
|
||||||
|
barAreaBorderColor.value = '#5cb85c'
|
||||||
|
text.value = '验证成功'
|
||||||
|
bindingClick.value = false
|
||||||
|
if (mode.value == 'pop') {
|
||||||
|
setTimeout(() => {
|
||||||
|
proxy.$parent.clickShow = false
|
||||||
|
refresh()
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
proxy.$parent.$emit('success', { ...data })
|
||||||
|
} else {
|
||||||
|
proxy.$parent.$emit('error', proxy)
|
||||||
|
barAreaColor.value = '#d9534f'
|
||||||
|
barAreaBorderColor.value = '#d9534f'
|
||||||
|
text.value = '验证失败'
|
||||||
|
setTimeout(() => {
|
||||||
|
refresh()
|
||||||
|
}, 700)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 400)
|
||||||
|
}
|
||||||
|
if (num.value < checkNum.value) {
|
||||||
|
num.value = createPoint(getMousePos(canvas, e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//获取坐标
|
||||||
|
const getMousePos = function (obj, e) {
|
||||||
|
const x = e.offsetX
|
||||||
|
const y = e.offsetY
|
||||||
|
return { x, y }
|
||||||
|
}
|
||||||
|
//创建坐标点
|
||||||
|
const createPoint = function (pos) {
|
||||||
|
tempPoints.push(Object.assign({}, pos))
|
||||||
|
return num.value + 1
|
||||||
|
}
|
||||||
|
const refresh = function () {
|
||||||
|
tempPoints.splice(0, tempPoints.length)
|
||||||
|
barAreaColor.value = '#000'
|
||||||
|
barAreaBorderColor.value = '#ddd'
|
||||||
|
bindingClick.value = true
|
||||||
|
fontPos.splice(0, fontPos.length)
|
||||||
|
checkPosArr.splice(0, checkPosArr.length)
|
||||||
|
num.value = 1
|
||||||
|
getPictrue()
|
||||||
|
text.value = '验证失败'
|
||||||
|
showRefresh.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求背景图片和验证图片
|
||||||
|
function getPictrue() {
|
||||||
|
const data = {
|
||||||
|
captchaType: captchaType.value
|
||||||
|
}
|
||||||
|
reqGet(data).then((res) => {
|
||||||
|
if (res.repCode == '0000') {
|
||||||
|
pointBackImgBase.value = res.repData.originalImageBase64
|
||||||
|
backToken.value = res.repData.token
|
||||||
|
secretKey.value = res.repData.secretKey
|
||||||
|
poinTextList.value = res.repData.wordList
|
||||||
|
text.value = '请依次点击【' + poinTextList.value.join(',') + '】'
|
||||||
|
} else {
|
||||||
|
text.value = res.repMsg
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//坐标转换函数
|
||||||
|
const pointTransfrom = function (pointArr, imgSize) {
|
||||||
|
const 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
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
secretKey,
|
||||||
|
checkNum,
|
||||||
|
fontPos,
|
||||||
|
checkPosArr,
|
||||||
|
num,
|
||||||
|
pointBackImgBase,
|
||||||
|
poinTextList,
|
||||||
|
backToken,
|
||||||
|
setSize,
|
||||||
|
tempPoints,
|
||||||
|
text,
|
||||||
|
barAreaColor,
|
||||||
|
barAreaBorderColor,
|
||||||
|
showRefresh,
|
||||||
|
bindingClick,
|
||||||
|
init,
|
||||||
|
canvas,
|
||||||
|
canvasClick,
|
||||||
|
getMousePos,
|
||||||
|
createPoint,
|
||||||
|
refresh,
|
||||||
|
getPictrue,
|
||||||
|
pointTransfrom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
453
admin/src/components/verifition/Verify/VerifySlide.vue
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
<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="'data:image/png;base64,' + backImgBase"
|
||||||
|
alt=""
|
||||||
|
style="width: 100%; height: 100%; display: block"
|
||||||
|
/>
|
||||||
|
<div class="verify-refresh" @click="refresh" v-show="showRefresh">
|
||||||
|
<i class="iconfont icon-refresh"></i>
|
||||||
|
</div>
|
||||||
|
<transition name="tips">
|
||||||
|
<span
|
||||||
|
class="verify-tips"
|
||||||
|
v-if="tipWords"
|
||||||
|
: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"></span>
|
||||||
|
<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"></span>
|
||||||
|
<div
|
||||||
|
class="verify-move-block"
|
||||||
|
@touchstart="start"
|
||||||
|
@mousedown="start"
|
||||||
|
:style="{
|
||||||
|
width: barSize.height,
|
||||||
|
height: barSize.height,
|
||||||
|
'background-color': moveBlockBackgroundColor,
|
||||||
|
left: moveBlockLeft,
|
||||||
|
transition: transitionLeft
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
:class="['verify-icon iconfont', iconClass]"
|
||||||
|
:style="{ color: iconColor }"
|
||||||
|
></i>
|
||||||
|
<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;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script type="text/babel">
|
||||||
|
/**
|
||||||
|
* VerifySlide
|
||||||
|
* @description 滑块
|
||||||
|
* */
|
||||||
|
import { aesEncrypt } from './../utils/ase'
|
||||||
|
import { resetSize } from './../utils/util'
|
||||||
|
import { reqGet, reqCheck } from './../api/index'
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
onMounted,
|
||||||
|
reactive,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
nextTick,
|
||||||
|
toRefs,
|
||||||
|
watchEffect,
|
||||||
|
getCurrentInstance
|
||||||
|
} from 'vue'
|
||||||
|
// "captchaType":"blockPuzzle",
|
||||||
|
export default {
|
||||||
|
name: 'VerifySlide',
|
||||||
|
props: {
|
||||||
|
captchaType: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: '1'
|
||||||
|
},
|
||||||
|
//弹出式pop,固定fixed
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'fixed'
|
||||||
|
},
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(props, context) {
|
||||||
|
const { mode, captchaType, vSpace, imgSize, barSize, type, blockSize, explain } =
|
||||||
|
toRefs(props)
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const secretKey = ref(''), //后端返回的ase加密秘钥
|
||||||
|
passFlag = ref(''), //是否通过的标识
|
||||||
|
backImgBase = ref(''), //验证码背景图片
|
||||||
|
blockBackImgBase = ref(''), //验证滑块的背景图片
|
||||||
|
backToken = ref(''), //后端返回的唯一token值
|
||||||
|
startMoveTime = ref(''), //移动开始的时间
|
||||||
|
endMovetime = ref(''), //移动结束的时间
|
||||||
|
tipsBackColor = ref(''), //提示词的背景颜色
|
||||||
|
tipWords = ref(''),
|
||||||
|
text = ref(''),
|
||||||
|
finishText = ref(''),
|
||||||
|
setSize = reactive({
|
||||||
|
imgHeight: 0,
|
||||||
|
imgWidth: 0,
|
||||||
|
barHeight: 0,
|
||||||
|
barWidth: 0
|
||||||
|
}),
|
||||||
|
top = ref(0),
|
||||||
|
left = ref(0),
|
||||||
|
moveBlockLeft = ref(undefined),
|
||||||
|
leftBarWidth = ref(undefined),
|
||||||
|
// 移动中样式
|
||||||
|
moveBlockBackgroundColor = ref(undefined),
|
||||||
|
leftBarBorderColor = ref('#ddd'),
|
||||||
|
iconColor = ref(undefined),
|
||||||
|
iconClass = ref('icon-right'),
|
||||||
|
status = ref(false), //鼠标状态
|
||||||
|
isEnd = ref(false), //是够验证完成
|
||||||
|
showRefresh = ref(true),
|
||||||
|
transitionLeft = ref(''),
|
||||||
|
transitionWidth = ref(''),
|
||||||
|
startLeft = ref(0)
|
||||||
|
|
||||||
|
const barArea = computed(() => {
|
||||||
|
return proxy.$el.querySelector('.verify-bar-area')
|
||||||
|
})
|
||||||
|
function init() {
|
||||||
|
text.value = explain.value
|
||||||
|
getPictrue()
|
||||||
|
nextTick(() => {
|
||||||
|
const { imgHeight, imgWidth, barHeight, barWidth } = resetSize(proxy)
|
||||||
|
setSize.imgHeight = imgHeight
|
||||||
|
setSize.imgWidth = imgWidth
|
||||||
|
setSize.barHeight = barHeight
|
||||||
|
setSize.barWidth = barWidth
|
||||||
|
proxy.$parent.$emit('ready', proxy)
|
||||||
|
})
|
||||||
|
|
||||||
|
window.removeEventListener('touchmove', function (e) {
|
||||||
|
move(e)
|
||||||
|
})
|
||||||
|
window.removeEventListener('mousemove', function (e) {
|
||||||
|
move(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
//鼠标松开
|
||||||
|
window.removeEventListener('touchend', function () {
|
||||||
|
end()
|
||||||
|
})
|
||||||
|
window.removeEventListener('mouseup', function () {
|
||||||
|
end()
|
||||||
|
})
|
||||||
|
|
||||||
|
window.addEventListener('touchmove', function (e) {
|
||||||
|
move(e)
|
||||||
|
})
|
||||||
|
window.addEventListener('mousemove', function (e) {
|
||||||
|
move(e)
|
||||||
|
})
|
||||||
|
|
||||||
|
//鼠标松开
|
||||||
|
window.addEventListener('touchend', function () {
|
||||||
|
end()
|
||||||
|
})
|
||||||
|
window.addEventListener('mouseup', function () {
|
||||||
|
end()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
watch(type, () => {
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
// 禁止拖拽
|
||||||
|
init()
|
||||||
|
proxy.$el.onselectstart = function () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
//鼠标按下
|
||||||
|
function start(e) {
|
||||||
|
e = e || window.event
|
||||||
|
if (!e.touches) {
|
||||||
|
//兼容PC端
|
||||||
|
var x = e.clientX
|
||||||
|
} else {
|
||||||
|
//兼容移动端
|
||||||
|
var x = e.touches[0].pageX
|
||||||
|
}
|
||||||
|
console.log(barArea)
|
||||||
|
startLeft.value = Math.floor(x - barArea.value.getBoundingClientRect().left)
|
||||||
|
startMoveTime.value = +new Date() //开始滑动的时间
|
||||||
|
if (isEnd.value == false) {
|
||||||
|
text.value = ''
|
||||||
|
moveBlockBackgroundColor.value = '#337ab7'
|
||||||
|
leftBarBorderColor.value = '#337AB7'
|
||||||
|
iconColor.value = '#fff'
|
||||||
|
e.stopPropagation()
|
||||||
|
status.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//鼠标移动
|
||||||
|
function move(e) {
|
||||||
|
e = e || window.event
|
||||||
|
if (status.value && isEnd.value == false) {
|
||||||
|
let x
|
||||||
|
if (!e.touches) {
|
||||||
|
//兼容PC端
|
||||||
|
x = e.clientX
|
||||||
|
} else {
|
||||||
|
//兼容移动端
|
||||||
|
x = e.touches[0].pageX
|
||||||
|
}
|
||||||
|
const bar_area_left = barArea.value.getBoundingClientRect().left
|
||||||
|
let move_block_left = x - bar_area_left //小方块相对于父元素的left值
|
||||||
|
if (
|
||||||
|
move_block_left >=
|
||||||
|
barArea.value.offsetWidth - parseInt(parseInt(blockSize.value.width) / 2) - 2
|
||||||
|
) {
|
||||||
|
move_block_left =
|
||||||
|
barArea.value.offsetWidth -
|
||||||
|
parseInt(parseInt(blockSize.value.width) / 2) -
|
||||||
|
2
|
||||||
|
}
|
||||||
|
if (move_block_left <= 0) {
|
||||||
|
move_block_left = parseInt(parseInt(blockSize.value.width) / 2)
|
||||||
|
}
|
||||||
|
//拖动后小方块的left值
|
||||||
|
moveBlockLeft.value = move_block_left - startLeft.value + 'px'
|
||||||
|
leftBarWidth.value = move_block_left - startLeft.value + 'px'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//鼠标松开
|
||||||
|
function end() {
|
||||||
|
endMovetime.value = +new Date()
|
||||||
|
//判断是否重合
|
||||||
|
if (status.value && isEnd.value == false) {
|
||||||
|
let moveLeftDistance = parseInt((moveBlockLeft.value || '').replace('px', ''))
|
||||||
|
moveLeftDistance = (moveLeftDistance * 310) / parseInt(setSize.imgWidth)
|
||||||
|
const data = {
|
||||||
|
captchaType: captchaType.value,
|
||||||
|
pointJson: secretKey.value
|
||||||
|
? aesEncrypt(
|
||||||
|
JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||||
|
secretKey.value
|
||||||
|
)
|
||||||
|
: JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||||
|
token: backToken.value
|
||||||
|
}
|
||||||
|
reqCheck(data).then((res) => {
|
||||||
|
if (res.repCode == '0000') {
|
||||||
|
moveBlockBackgroundColor.value = '#5cb85c'
|
||||||
|
leftBarBorderColor.value = '#5cb85c'
|
||||||
|
iconColor.value = '#fff'
|
||||||
|
iconClass.value = 'icon-check'
|
||||||
|
showRefresh.value = false
|
||||||
|
isEnd.value = true
|
||||||
|
if (mode.value == 'pop') {
|
||||||
|
setTimeout(() => {
|
||||||
|
proxy.$parent.clickShow = false
|
||||||
|
refresh()
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
passFlag.value = true
|
||||||
|
tipWords.value = `${(
|
||||||
|
(endMovetime.value - startMoveTime.value) /
|
||||||
|
1000
|
||||||
|
).toFixed(2)}s验证成功`
|
||||||
|
const captchaVerification = secretKey.value
|
||||||
|
? aesEncrypt(
|
||||||
|
backToken.value +
|
||||||
|
'---' +
|
||||||
|
JSON.stringify({ x: moveLeftDistance, y: 5.0 }),
|
||||||
|
secretKey.value
|
||||||
|
)
|
||||||
|
: backToken.value +
|
||||||
|
'---' +
|
||||||
|
JSON.stringify({ x: moveLeftDistance, y: 5.0 })
|
||||||
|
setTimeout(() => {
|
||||||
|
tipWords.value = ''
|
||||||
|
proxy.$parent.closeBox()
|
||||||
|
proxy.$parent.$emit('success', { ...data })
|
||||||
|
}, 1000)
|
||||||
|
} else {
|
||||||
|
moveBlockBackgroundColor.value = '#d9534f'
|
||||||
|
leftBarBorderColor.value = '#d9534f'
|
||||||
|
iconColor.value = '#fff'
|
||||||
|
iconClass.value = 'icon-close'
|
||||||
|
passFlag.value = false
|
||||||
|
setTimeout(function () {
|
||||||
|
refresh()
|
||||||
|
}, 1000)
|
||||||
|
proxy.$parent.$emit('error', proxy)
|
||||||
|
tipWords.value = '验证失败'
|
||||||
|
setTimeout(() => {
|
||||||
|
tipWords.value = ''
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
status.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const refresh = () => {
|
||||||
|
showRefresh.value = true
|
||||||
|
finishText.value = ''
|
||||||
|
|
||||||
|
transitionLeft.value = 'left .3s'
|
||||||
|
moveBlockLeft.value = 0
|
||||||
|
|
||||||
|
leftBarWidth.value = undefined
|
||||||
|
transitionWidth.value = 'width .3s'
|
||||||
|
|
||||||
|
leftBarBorderColor.value = '#ddd'
|
||||||
|
moveBlockBackgroundColor.value = '#fff'
|
||||||
|
iconColor.value = '#000'
|
||||||
|
iconClass.value = 'icon-right'
|
||||||
|
isEnd.value = false
|
||||||
|
|
||||||
|
getPictrue()
|
||||||
|
setTimeout(() => {
|
||||||
|
transitionWidth.value = ''
|
||||||
|
transitionLeft.value = ''
|
||||||
|
text.value = explain.value
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求背景图片和验证图片
|
||||||
|
function getPictrue() {
|
||||||
|
const data = {
|
||||||
|
captchaType: captchaType.value
|
||||||
|
}
|
||||||
|
reqGet(data).then((res) => {
|
||||||
|
if (res.repCode == '0000') {
|
||||||
|
backImgBase.value = res.repData.originalImageBase64
|
||||||
|
blockBackImgBase.value = res.repData.jigsawImageBase64
|
||||||
|
backToken.value = res.repData.token
|
||||||
|
secretKey.value = res.repData.secretKey
|
||||||
|
} else {
|
||||||
|
tipWords.value = res.repMsg
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
secretKey, //后端返回的ase加密秘钥
|
||||||
|
passFlag, //是否通过的标识
|
||||||
|
backImgBase, //验证码背景图片
|
||||||
|
blockBackImgBase, //验证滑块的背景图片
|
||||||
|
backToken, //后端返回的唯一token值
|
||||||
|
startMoveTime, //移动开始的时间
|
||||||
|
endMovetime, //移动结束的时间
|
||||||
|
tipsBackColor, //提示词的背景颜色
|
||||||
|
tipWords,
|
||||||
|
text,
|
||||||
|
finishText,
|
||||||
|
setSize,
|
||||||
|
top,
|
||||||
|
left,
|
||||||
|
moveBlockLeft,
|
||||||
|
leftBarWidth,
|
||||||
|
// 移动中样式
|
||||||
|
moveBlockBackgroundColor,
|
||||||
|
leftBarBorderColor,
|
||||||
|
iconColor,
|
||||||
|
iconClass,
|
||||||
|
status, //鼠标状态
|
||||||
|
isEnd, //是够验证完成
|
||||||
|
showRefresh,
|
||||||
|
transitionLeft,
|
||||||
|
transitionWidth,
|
||||||
|
barArea,
|
||||||
|
refresh,
|
||||||
|
start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
24
admin/src/components/verifition/api/index.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 此处可直接引用自己项目封装好的 axios 配合后端联调
|
||||||
|
*/
|
||||||
|
|
||||||
|
import request from './../utils/axios' //组件内部封装的axios
|
||||||
|
// import request from "@/api/axios.js" //调用项目封装的axios
|
||||||
|
|
||||||
|
//获取验证图片 以及token
|
||||||
|
export function reqGet(data) {
|
||||||
|
return request({
|
||||||
|
url: '/captcha/get',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//滑动或者点选验证
|
||||||
|
export function reqCheck(data) {
|
||||||
|
return request({
|
||||||
|
url: '/captcha/check',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
14
admin/src/components/verifition/utils/ase.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import CryptoJS from 'crypto-js'
|
||||||
|
/**
|
||||||
|
* @word 要加密的内容
|
||||||
|
* @keyWord String 服务器随机返回的关键字
|
||||||
|
* */
|
||||||
|
export function aesEncrypt(word, keyWord = 'XwKsGlMcdPMEhR1B') {
|
||||||
|
const key = CryptoJS.enc.Utf8.parse(keyWord)
|
||||||
|
const srcs = CryptoJS.enc.Utf8.parse(word)
|
||||||
|
const encrypted = CryptoJS.AES.encrypt(srcs, key, {
|
||||||
|
mode: CryptoJS.mode.ECB,
|
||||||
|
padding: CryptoJS.pad.Pkcs7
|
||||||
|
})
|
||||||
|
return encrypted.toString()
|
||||||
|
}
|
29
admin/src/components/verifition/utils/axios.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
axios.defaults.baseURL = '/api'
|
||||||
|
|
||||||
|
const service = axios.create({
|
||||||
|
timeout: 40000,
|
||||||
|
headers: {
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Content-Type': 'application/json; charset=UTF-8'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
service.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
Promise.reject(error)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// response interceptor
|
||||||
|
service.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
const res = response.data
|
||||||
|
return res
|
||||||
|
},
|
||||||
|
(error) => {}
|
||||||
|
)
|
||||||
|
export default service
|
102
admin/src/components/verifition/utils/util.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
export function resetSize(vm) {
|
||||||
|
let img_width, img_height, bar_width, bar_height //图片的宽度、高度,移动条的宽度、高度
|
||||||
|
|
||||||
|
const parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
|
||||||
|
const parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
|
||||||
|
if (vm.imgSize.width.indexOf('%') != -1) {
|
||||||
|
img_width = (parseInt(vm.imgSize.width) / 100) * parentWidth + 'px'
|
||||||
|
} else {
|
||||||
|
img_width = vm.imgSize.width
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.imgSize.height.indexOf('%') != -1) {
|
||||||
|
img_height = (parseInt(vm.imgSize.height) / 100) * parentHeight + 'px'
|
||||||
|
} else {
|
||||||
|
img_height = vm.imgSize.height
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.barSize.width.indexOf('%') != -1) {
|
||||||
|
bar_width = (parseInt(vm.barSize.width) / 100) * parentWidth + 'px'
|
||||||
|
} else {
|
||||||
|
bar_width = vm.barSize.width
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.barSize.height.indexOf('%') != -1) {
|
||||||
|
bar_height = (parseInt(vm.barSize.height) / 100) * parentHeight + 'px'
|
||||||
|
} else {
|
||||||
|
bar_height = vm.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']
|
@@ -2,7 +2,8 @@ const config = {
|
|||||||
terminal: 1, //终端
|
terminal: 1, //终端
|
||||||
title: '后台管理系统', //网站默认标题
|
title: '后台管理系统', //网站默认标题
|
||||||
version: '1.3.3', //版本号
|
version: '1.3.3', //版本号
|
||||||
baseUrl: `${import.meta.env.VITE_APP_BASE_URL || ''}/`, //请求接口域名
|
// import.meta.env.VITE_APP_BASE_URL ||
|
||||||
|
baseUrl: '', //请求接口域名
|
||||||
urlPrefix: 'api', //请求默认前缀
|
urlPrefix: 'api', //请求默认前缀
|
||||||
timeout: 60 * 1000 //请求超时时长
|
timeout: 60 * 1000 //请求超时时长
|
||||||
}
|
}
|
||||||
|
@@ -34,16 +34,15 @@ const useUserStore = defineStore({
|
|||||||
this.perms = []
|
this.perms = []
|
||||||
},
|
},
|
||||||
login(playload: any) {
|
login(playload: any) {
|
||||||
const { account, password } = playload
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login({
|
login({
|
||||||
username: account,
|
...playload
|
||||||
password: password
|
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.token = data.token
|
this.token = data.token
|
||||||
cache.set(TOKEN_KEY, data.token)
|
cache.set(TOKEN_KEY, data.token)
|
||||||
resolve(data)
|
// resolve(data)
|
||||||
|
reject(data)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
reject(error)
|
reject(error)
|
||||||
|
@@ -10,12 +10,8 @@
|
|||||||
>
|
>
|
||||||
<div class="text-center text-3xl font-medium mb-8">{{ config.webName }}</div>
|
<div class="text-center text-3xl font-medium mb-8">{{ config.webName }}</div>
|
||||||
<el-form ref="formRef" :model="formData" size="large" :rules="rules">
|
<el-form ref="formRef" :model="formData" size="large" :rules="rules">
|
||||||
<el-form-item prop="account">
|
<el-form-item prop="username">
|
||||||
<el-input
|
<el-input v-model.trim="formData.username" placeholder="请输入账号">
|
||||||
v-model.trim="formData.account"
|
|
||||||
placeholder="请输入账号"
|
|
||||||
@keyup.enter="handleEnter"
|
|
||||||
>
|
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<icon name="el-icon-User" />
|
<icon name="el-icon-User" />
|
||||||
</template>
|
</template>
|
||||||
@@ -38,9 +34,34 @@
|
|||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<el-checkbox v-model="remAccount" label="记住账号"></el-checkbox>
|
<el-checkbox v-model="remAccount" label="记住账号"></el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<el-button type="primary" size="large" :loading="isLock" @click="lockLogin">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="large"
|
||||||
|
:loading="isLock"
|
||||||
|
@click="onShowCaptcha('blockPuzzle')"
|
||||||
|
>
|
||||||
登录
|
登录
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
<!-- <button @click="onShowCaptcha('blockPuzzle')">滑块</button>
|
||||||
|
<button @click="onShowCaptcha('clickWord')">点击文字</button> -->
|
||||||
|
<Verify
|
||||||
|
mode="pop"
|
||||||
|
:captchaType="captchaType"
|
||||||
|
:imgSize="{ width: '400px', height: '200px' }"
|
||||||
|
ref="verify"
|
||||||
|
@success="handleSuccess"
|
||||||
|
@error="
|
||||||
|
(e) => {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@ready="
|
||||||
|
(e) => {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></Verify>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,6 +79,23 @@ import cache from '@/utils/cache'
|
|||||||
import { ACCOUNT_KEY } from '@/enums/cacheEnums'
|
import { ACCOUNT_KEY } from '@/enums/cacheEnums'
|
||||||
import { PageEnum } from '@/enums/pageEnum'
|
import { PageEnum } from '@/enums/pageEnum'
|
||||||
import { useLockFn } from '@/hooks/useLockFn'
|
import { useLockFn } from '@/hooks/useLockFn'
|
||||||
|
|
||||||
|
import Verify from '@/components/verifition/Verify.vue'
|
||||||
|
|
||||||
|
const verify = ref(null)
|
||||||
|
const captchaType = ref('')
|
||||||
|
const onShowCaptcha = (type) => {
|
||||||
|
captchaType.value = type
|
||||||
|
verify.value.show()
|
||||||
|
}
|
||||||
|
let verifition = null
|
||||||
|
const handleSuccess = (res) => {
|
||||||
|
console.log(res)
|
||||||
|
console.log('sucess')
|
||||||
|
verifition = res
|
||||||
|
lockLogin(res)
|
||||||
|
}
|
||||||
|
|
||||||
const passwordRef = shallowRef<InputInstance>()
|
const passwordRef = shallowRef<InputInstance>()
|
||||||
const formRef = shallowRef<FormInstance>()
|
const formRef = shallowRef<FormInstance>()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
@@ -67,11 +105,11 @@ const router = useRouter()
|
|||||||
const remAccount = ref(false)
|
const remAccount = ref(false)
|
||||||
const config = computed(() => appStore.config)
|
const config = computed(() => appStore.config)
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
account: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
})
|
})
|
||||||
const rules = {
|
const rules = {
|
||||||
account: [
|
username: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入账号',
|
message: '请输入账号',
|
||||||
@@ -86,22 +124,18 @@ const rules = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
// 回车按键监听
|
|
||||||
const handleEnter = () => {
|
|
||||||
if (!formData.password) {
|
|
||||||
return passwordRef.value?.focus()
|
|
||||||
}
|
|
||||||
handleLogin()
|
|
||||||
}
|
|
||||||
// 登录处理
|
// 登录处理
|
||||||
const handleLogin = async () => {
|
const handleLogin = async (captchaInfo) => {
|
||||||
|
console.log('captchaInfo', captchaInfo, { ...formData, ...captchaInfo })
|
||||||
|
|
||||||
await formRef.value?.validate()
|
await formRef.value?.validate()
|
||||||
// 记住账号,缓存
|
// 记住账号,缓存
|
||||||
cache.set(ACCOUNT_KEY, {
|
cache.set(ACCOUNT_KEY, {
|
||||||
remember: remAccount.value,
|
remember: remAccount.value,
|
||||||
account: remAccount.value ? formData.account : ''
|
username: remAccount.value ? formData.username : ''
|
||||||
})
|
})
|
||||||
await userStore.login(formData)
|
await userStore.login({ ...formData, ...verifition })
|
||||||
const {
|
const {
|
||||||
query: { redirect }
|
query: { redirect }
|
||||||
} = route
|
} = route
|
||||||
@@ -114,7 +148,7 @@ onMounted(() => {
|
|||||||
const value = cache.get(ACCOUNT_KEY)
|
const value = cache.get(ACCOUNT_KEY)
|
||||||
if (value?.remember) {
|
if (value?.remember) {
|
||||||
remAccount.value = value.remember
|
remAccount.value = value.remember
|
||||||
formData.account = value.account
|
formData.username = value.username
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,181 +1,164 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="admin">
|
<div class="admin">
|
||||||
<el-card class="!border-none" shadow="never">
|
<el-card class="!border-none" shadow="never">
|
||||||
<el-form class="mb-[-16px]" :model="formData" inline>
|
<el-form class="mb-[-16px]" :model="formData" inline>
|
||||||
<el-form-item label="管理员账号">
|
<el-form-item label="管理员账号">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.username"
|
v-model="formData.username"
|
||||||
class="w-[280px]"
|
class="w-[280px]"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="resetPage"
|
@keyup.enter="resetPage"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="管理员名称">
|
<el-form-item label="管理员名称">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.nickname"
|
v-model="formData.nickname"
|
||||||
class="w-[280px]"
|
class="w-[280px]"
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="resetPage"
|
@keyup.enter="resetPage"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="管理员角色">
|
<el-form-item label="管理员角色">
|
||||||
<el-select class="w-[280px]" v-model="formData.role">
|
<el-select class="w-[280px]" v-model="formData.role">
|
||||||
<el-option label="全部" value="" />
|
<el-option label="全部" value="" />
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item, index) in optionsData.role"
|
v-for="(item, index) in optionsData.role"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||||
<el-button @click="resetParams">重置</el-button>
|
<el-button @click="resetParams">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card v-loading="pager.loading" class="mt-4 !border-none" shadow="never">
|
<el-card v-loading="pager.loading" class="mt-4 !border-none" shadow="never">
|
||||||
<el-button
|
<el-button v-perms="['system:admin:add']" type="primary" @click="handleAdd">
|
||||||
v-perms="['system:admin:add']"
|
<template #icon>
|
||||||
type="primary"
|
<icon name="el-icon-Plus" />
|
||||||
@click="handleAdd"
|
</template>
|
||||||
>
|
新增
|
||||||
<template #icon>
|
</el-button>
|
||||||
<icon name="el-icon-Plus" />
|
<div class="mt-4">
|
||||||
</template>
|
<el-table :data="pager.lists" size="large">
|
||||||
新增
|
<el-table-column label="ID" prop="id" min-width="60" />
|
||||||
</el-button>
|
<el-table-column label="头像" min-width="100">
|
||||||
<div class="mt-4">
|
<template #default="{ row }">
|
||||||
<el-table :data="pager.lists" size="large">
|
<el-avatar :size="50" :src="row.avatar"></el-avatar>
|
||||||
<el-table-column label="ID" prop="id" min-width="60" />
|
</template>
|
||||||
<el-table-column label="头像" min-width="100">
|
</el-table-column>
|
||||||
<template #default="{ row }">
|
<el-table-column label="账号" prop="username" min-width="100" />
|
||||||
<el-avatar :size="50" :src="row.avatar"></el-avatar>
|
<el-table-column label="名称" prop="nickname" min-width="100" />
|
||||||
</template>
|
<el-table-column label="角色" prop="role" min-width="100" />
|
||||||
</el-table-column>
|
<el-table-column label="部门" prop="dept" min-width="100" />
|
||||||
<el-table-column label="账号" prop="username" min-width="100" />
|
<el-table-column label="创建时间" prop="createTime" min-width="180" />
|
||||||
<el-table-column label="名称" prop="nickname" min-width="100" />
|
<el-table-column label="最近登录时间" prop="lastLoginTime" min-width="180" />
|
||||||
<el-table-column label="角色" prop="role" min-width="100" />
|
<el-table-column label="最近登录IP" prop="lastLoginIp" min-width="120" />
|
||||||
<el-table-column label="部门" prop="dept" min-width="100" />
|
<el-table-column label="状态" min-width="100">
|
||||||
<el-table-column label="创建时间" prop="createTime" min-width="180" />
|
<template #default="{ row }">
|
||||||
<el-table-column
|
<el-switch
|
||||||
label="最近登录时间"
|
v-perms="['system:admin:disable']"
|
||||||
prop="lastLoginTime"
|
v-if="row.id != 1"
|
||||||
min-width="180"
|
:model-value="row.isDisable"
|
||||||
/>
|
:active-value="0"
|
||||||
<el-table-column
|
:inactive-value="1"
|
||||||
label="最近登录IP"
|
@change="changeStatus($event, row.id)"
|
||||||
prop="lastLoginIp"
|
/>
|
||||||
min-width="120"
|
</template>
|
||||||
/>
|
</el-table-column>
|
||||||
<el-table-column label="状态" min-width="100">
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-switch
|
<el-button
|
||||||
v-perms="['system:admin:disable']"
|
v-perms="['system:admin:edit']"
|
||||||
v-if="row.id != 1"
|
type="primary"
|
||||||
:model-value="row.isDisable"
|
link
|
||||||
:active-value="0"
|
@click="handleEdit(row)"
|
||||||
:inactive-value="1"
|
>
|
||||||
@change="changeStatus($event, row.id)"
|
编辑
|
||||||
/>
|
</el-button>
|
||||||
</template>
|
<el-button
|
||||||
</el-table-column>
|
v-if="row.id != 1"
|
||||||
<el-table-column label="操作" width="120" fixed="right">
|
v-perms="['system:admin:del']"
|
||||||
<template #default="{ row }">
|
type="danger"
|
||||||
<el-button
|
link
|
||||||
v-perms="['system:admin:edit']"
|
@click="handleDelete(row.id)"
|
||||||
type="primary"
|
>
|
||||||
link
|
删除
|
||||||
@click="handleEdit(row)"
|
</el-button>
|
||||||
>
|
</template>
|
||||||
编辑
|
</el-table-column>
|
||||||
</el-button>
|
</el-table>
|
||||||
<el-button
|
</div>
|
||||||
v-if="row.id != 1"
|
<div class="flex mt-4 justify-end">
|
||||||
v-perms="['system:admin:del']"
|
<pagination v-model="pager" @change="getLists" />
|
||||||
type="danger"
|
</div>
|
||||||
link
|
</el-card>
|
||||||
@click="handleDelete(row.id)"
|
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||||
>
|
</div>
|
||||||
删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
<div class="flex mt-4 justify-end">
|
|
||||||
<pagination v-model="pager" @change="getLists" />
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<edit-popup
|
|
||||||
v-if="showEdit"
|
|
||||||
ref="editRef"
|
|
||||||
@success="getLists"
|
|
||||||
@close="showEdit = false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="admin">
|
<script lang="ts" setup name="admin">
|
||||||
import { adminLists, adminDelete, adminStatus } from "@/api/perms/admin";
|
import { adminLists, adminDelete, adminStatus } from '@/api/perms/admin'
|
||||||
import { roleAll } from "@/api/perms/role";
|
import { roleAll } from '@/api/perms/role'
|
||||||
import { useDictOptions } from "@/hooks/useDictOptions";
|
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||||
import { usePaging } from "@/hooks/usePaging";
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import feedback from "@/utils/feedback";
|
import feedback from '@/utils/feedback'
|
||||||
import EditPopup from "./edit.vue";
|
import EditPopup from './edit.vue'
|
||||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>();
|
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = reactive<any>({
|
const formData = reactive<any>({
|
||||||
// username: "",
|
// username: "",
|
||||||
// nickname: "",
|
// nickname: "",
|
||||||
// role: "",
|
// role: "",
|
||||||
});
|
})
|
||||||
const showEdit = ref(false);
|
const showEdit = ref(false)
|
||||||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
const { pager, getLists, resetParams, resetPage } = usePaging({
|
||||||
fetchFun: adminLists,
|
fetchFun: adminLists,
|
||||||
params: formData,
|
params: formData
|
||||||
});
|
})
|
||||||
|
|
||||||
const changeStatus = async (active: any, id: number) => {
|
const changeStatus = async (active: any, id: number) => {
|
||||||
try {
|
try {
|
||||||
await feedback.confirm(`确定${active ? "停用" : "开启"}当前管理员?`);
|
await feedback.confirm(`确定${active ? '停用' : '开启'}当前管理员?`)
|
||||||
await adminStatus({ id });
|
await adminStatus({ id })
|
||||||
feedback.msgSuccess("修改成功");
|
feedback.msgSuccess('修改成功')
|
||||||
getLists();
|
getLists()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
getLists();
|
getLists()
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
const handleAdd = async () => {
|
const handleAdd = async () => {
|
||||||
showEdit.value = true;
|
showEdit.value = true
|
||||||
await nextTick();
|
await nextTick()
|
||||||
editRef.value?.open("add");
|
editRef.value?.open('add')
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleEdit = async (data: any) => {
|
const handleEdit = async (data: any) => {
|
||||||
showEdit.value = true;
|
showEdit.value = true
|
||||||
await nextTick();
|
await nextTick()
|
||||||
editRef.value?.open("edit");
|
editRef.value?.open('edit')
|
||||||
editRef.value?.setFormData(data);
|
editRef.value?.setFormData(data)
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleDelete = async (id: number) => {
|
const handleDelete = async (id: number) => {
|
||||||
await feedback.confirm("确定要删除?");
|
await feedback.confirm('确定要删除?')
|
||||||
await adminDelete({ id });
|
await adminDelete({ id })
|
||||||
feedback.msgSuccess("删除成功");
|
feedback.msgSuccess('删除成功')
|
||||||
getLists();
|
getLists()
|
||||||
};
|
}
|
||||||
|
|
||||||
const { optionsData } = useDictOptions<{
|
const { optionsData } = useDictOptions<{
|
||||||
role: any[];
|
role: any[]
|
||||||
}>({
|
}>({
|
||||||
role: {
|
role: {
|
||||||
api: roleAll,
|
api: roleAll
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getLists();
|
getLists()
|
||||||
});
|
})
|
||||||
</script>
|
</script>
|
||||||
|
126
server/admin/captcha/captcha_ctl.go
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package captcha
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
config2 "github.com/TestsLing/aj-captcha-go/config"
|
||||||
|
constant "github.com/TestsLing/aj-captcha-go/const"
|
||||||
|
"github.com/TestsLing/aj-captcha-go/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CaptchaGetParams struct {
|
||||||
|
CaptchaType string `json:"captchaType"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 客户端参数 看自身业务构建即可
|
||||||
|
type ClientParams struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
PointJson string `json:"pointJson"`
|
||||||
|
CaptchaType string `json:"captchaType"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// **********************默认配置***************************************************
|
||||||
|
// 默认配置,可以根据项目自行配置,将其他类型配置序列化上去
|
||||||
|
// var config = config2.NewConfig()
|
||||||
|
|
||||||
|
// *********************自定义配置**************************************************
|
||||||
|
// 水印配置(参数可从业务系统自定义)
|
||||||
|
var watermarkConfig = &config2.WatermarkConfig{
|
||||||
|
FontSize: 12,
|
||||||
|
Color: color.RGBA{R: 255, G: 255, B: 255, A: 255},
|
||||||
|
Text: "x_admin",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击文字配置(参数可从业务系统自定义)
|
||||||
|
var clickWordConfig = &config2.ClickWordConfig{
|
||||||
|
FontSize: 25,
|
||||||
|
FontNum: 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滑动模块配置(参数可从业务系统自定义)
|
||||||
|
var blockPuzzleConfig = &config2.BlockPuzzleConfig{Offset: 10}
|
||||||
|
|
||||||
|
// 行为校验配置模块(具体参数可从业务系统配置文件自定义)
|
||||||
|
var captcha_config = config2.BuildConfig(constant.MemCacheKey, constant.DefaultResourceRoot, watermarkConfig,
|
||||||
|
clickWordConfig, blockPuzzleConfig, 2*60)
|
||||||
|
|
||||||
|
// 服务工厂,主要用户注册 获取 缓存和验证服务
|
||||||
|
var factory = service.NewCaptchaServiceFactory(captcha_config)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// 这里默认是注册了 内存缓存,但是不足以应对生产环境,希望自行注册缓存驱动 实现缓存接口即可替换(CacheType就是注册进去的 key)
|
||||||
|
factory.RegisterCache(constant.MemCacheKey, service.NewMemCacheService(200000)) // 这里20指的是缓存阈值
|
||||||
|
|
||||||
|
//注册使用默认redis数据库
|
||||||
|
// factory.RegisterCache(constant.RedisCacheKey, service.NewDftRedisCacheService())
|
||||||
|
// //注册自定义配置redis数据库
|
||||||
|
// opt, err := redis.ParseURL(config.Config.RedisUrl)
|
||||||
|
// factory.RegisterCache(constant.RedisCacheKey, service.NewConfigRedisCacheService([]string{opt.Addr}, "", "", false, 0))
|
||||||
|
|
||||||
|
// 注册了两种验证码服务 可以自行实现更多的验证
|
||||||
|
factory.RegisterService(constant.ClickWordCaptcha, service.NewClickWordCaptchaService(factory))
|
||||||
|
factory.RegisterService(constant.BlockPuzzleCaptcha, service.NewBlockPuzzleCaptchaService(factory))
|
||||||
|
}
|
||||||
|
func CaptchaRoute(rg *gin.RouterGroup) {
|
||||||
|
|
||||||
|
rg = rg.Group("/captcha")
|
||||||
|
rg.POST("/get", func(c *gin.Context) {
|
||||||
|
var captchaGet CaptchaGetParams
|
||||||
|
if err := c.ShouldBind(&captchaGet); err != nil {
|
||||||
|
// 返回错误信息
|
||||||
|
c.JSON(200, errorRes(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据参数类型获取不同服务即可
|
||||||
|
data, _ := factory.GetService(captchaGet.CaptchaType).Get()
|
||||||
|
//输出json结果给调用方
|
||||||
|
c.JSON(200, successRes(data))
|
||||||
|
})
|
||||||
|
rg.POST("/check", func(c *gin.Context) {
|
||||||
|
var params ClientParams
|
||||||
|
if err := c.ShouldBind(¶ms); err != nil {
|
||||||
|
// 返回错误信息
|
||||||
|
c.JSON(200, errorRes(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ser := factory.GetService(params.CaptchaType)
|
||||||
|
err := ser.Check(params.Token, params.PointJson)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(200, errorRes(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//输出json结果给调用方
|
||||||
|
c.JSON(200, successRes(nil))
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登录等验证并删除
|
||||||
|
func Verify(params ClientParams) error {
|
||||||
|
ser := factory.GetService(params.CaptchaType)
|
||||||
|
// 登录验证并删除
|
||||||
|
err := ser.Verification(params.Token, params.PointJson)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func successRes(data interface{}) map[string]interface{} {
|
||||||
|
ret := make(map[string]interface{})
|
||||||
|
ret["error"] = false
|
||||||
|
ret["repCode"] = "0000"
|
||||||
|
ret["repData"] = data
|
||||||
|
ret["repMsg"] = nil
|
||||||
|
ret["successRes"] = true
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
func errorRes(err error) map[string]interface{} {
|
||||||
|
ret := make(map[string]interface{})
|
||||||
|
ret["error"] = true
|
||||||
|
ret["repCode"] = "0001"
|
||||||
|
ret["repData"] = nil
|
||||||
|
ret["repMsg"] = err.Error()
|
||||||
|
ret["successRes"] = false
|
||||||
|
return ret
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"x_admin/admin/captcha"
|
||||||
"x_admin/admin/common/album"
|
"x_admin/admin/common/album"
|
||||||
"x_admin/admin/common/index"
|
"x_admin/admin/common/index"
|
||||||
"x_admin/admin/common/upload"
|
"x_admin/admin/common/upload"
|
||||||
@@ -44,4 +45,6 @@ func RegisterGroup(rg *gin.RouterGroup) {
|
|||||||
system.RoleRoute(rg)
|
system.RoleRoute(rg)
|
||||||
log.LogRoute(rg)
|
log.LogRoute(rg)
|
||||||
ArticleCollectRoute(rg)
|
ArticleCollectRoute(rg)
|
||||||
|
|
||||||
|
captcha.CaptchaRoute(rg)
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package login
|
package login
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"x_admin/admin/captcha"
|
||||||
"x_admin/admin/system/admin"
|
"x_admin/admin/system/admin"
|
||||||
"x_admin/admin/system/role"
|
"x_admin/admin/system/role"
|
||||||
"x_admin/core"
|
"x_admin/core"
|
||||||
@@ -31,6 +32,16 @@ type loginHandler struct {
|
|||||||
|
|
||||||
// login 登录系统
|
// login 登录系统
|
||||||
func (lh loginHandler) login(c *gin.Context) {
|
func (lh loginHandler) login(c *gin.Context) {
|
||||||
|
var params captcha.ClientParams
|
||||||
|
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, ¶ms)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := captcha.Verify(params)
|
||||||
|
if err != nil {
|
||||||
|
response.FailWithMsg(c, response.Failed, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var loginReq SystemLoginReq
|
var loginReq SystemLoginReq
|
||||||
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &loginReq)) {
|
if response.IsFailWithResp(c, util.VerifyUtil.VerifyJSON(c, &loginReq)) {
|
||||||
return
|
return
|
||||||
|
@@ -18,6 +18,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/TestsLing/aj-captcha-go v0.0.0-20221117062708-1abcf4c62792 // indirect
|
||||||
github.com/bytedance/sonic v1.10.2 // indirect
|
github.com/bytedance/sonic v1.10.2 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||||
@@ -31,8 +32,10 @@ require (
|
|||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
@@ -64,6 +67,7 @@ require (
|
|||||||
golang.org/x/arch v0.6.0 // indirect
|
golang.org/x/arch v0.6.0 // indirect
|
||||||
golang.org/x/crypto v0.15.0 // indirect
|
golang.org/x/crypto v0.15.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
|
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
|
||||||
|
golang.org/x/image v0.14.0 // indirect
|
||||||
golang.org/x/net v0.18.0 // indirect
|
golang.org/x/net v0.18.0 // indirect
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
|
@@ -38,11 +38,14 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f
|
|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/TestsLing/aj-captcha-go v0.0.0-20221117062708-1abcf4c62792 h1:JrIVYRSZCe3yQuOvKUbyAMI+PEw4DUfuoUQR/H+0Kcc=
|
||||||
|
github.com/TestsLing/aj-captcha-go v0.0.0-20221117062708-1abcf4c62792/go.mod h1:PZU6xNk8I+Z9NR5rZhlQzG/BkrBdA94ptoiNTle/8tI=
|
||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||||
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
|
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
|
||||||
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
@@ -76,6 +79,8 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
|||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
@@ -105,14 +110,19 @@ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91
|
|||||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
|
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
|
||||||
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
github.com/go-redis/redis/v9 v9.0.0-rc.2 h1:IN1eI8AvJJeWHjMW/hlFAv2sAfvTun2DVksDDJ3a6a0=
|
github.com/go-redis/redis/v9 v9.0.0-rc.2 h1:IN1eI8AvJJeWHjMW/hlFAv2sAfvTun2DVksDDJ3a6a0=
|
||||||
github.com/go-redis/redis/v9 v9.0.0-rc.2/go.mod h1:cgBknjwcBJa2prbnuHH/4k/Mlj4r0pWNV2HBanHujfY=
|
github.com/go-redis/redis/v9 v9.0.0-rc.2/go.mod h1:cgBknjwcBJa2prbnuHH/4k/Mlj4r0pWNV2HBanHujfY=
|
||||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
@@ -139,6 +149,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
|||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
@@ -168,6 +179,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
|
|||||||
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||||
@@ -182,6 +194,7 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP
|
|||||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||||
@@ -224,10 +237,19 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
|
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
|
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||||
|
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||||
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
|
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
|
||||||
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||||
@@ -335,6 +357,9 @@ golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 h1:mchzmB1XO2pMaKFRqk/+MV3mg
|
|||||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||||
|
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
||||||
|
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@@ -358,6 +383,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
@@ -378,6 +404,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
|||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
@@ -387,6 +414,7 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||||
@@ -410,6 +438,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -418,8 +447,11 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -440,6 +472,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -447,6 +480,7 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@@ -512,6 +546,7 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
|
|||||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
@@ -608,6 +643,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
|||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
@@ -616,12 +652,15 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
BIN
server/resources/defaultImages/jigsaw/original/1.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
server/resources/defaultImages/jigsaw/original/2.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
server/resources/defaultImages/jigsaw/original/3.png
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
server/resources/defaultImages/jigsaw/original/4.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
server/resources/defaultImages/jigsaw/original/5.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
server/resources/defaultImages/jigsaw/original/6.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
server/resources/defaultImages/jigsaw/original/bg8.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
server/resources/defaultImages/jigsaw/original/img.png
Normal file
After Width: | Height: | Size: 645 KiB |
BIN
server/resources/defaultImages/jigsaw/slidingBlock/1.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
server/resources/defaultImages/jigsaw/slidingBlock/2.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
server/resources/defaultImages/jigsaw/slidingBlock/3.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
server/resources/defaultImages/jigsaw/slidingBlock/4.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
server/resources/defaultImages/jigsaw/slidingBlock/5.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
server/resources/defaultImages/jigsaw/slidingBlock/6.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
server/resources/defaultImages/pic-click/1.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
server/resources/defaultImages/pic-click/2.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
server/resources/defaultImages/pic-click/3.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
server/resources/defaultImages/pic-click/4.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
server/resources/defaultImages/pic-click/5.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
server/resources/defaultImages/pic-click/6.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
server/resources/defaultImages/pic-click/bg10.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
server/resources/defaultImages/pic-click/bg11.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
server/resources/defaultImages/pic-click/bg12.png
Normal file
After Width: | Height: | Size: 66 KiB |
BIN
server/resources/defaultImages/pic-click/bg13.png
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
server/resources/defaultImages/pic-click/bg14.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
server/resources/defaultImages/pic-click/bg15.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
server/resources/defaultImages/pic-click/bg16.png
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
server/resources/defaultImages/pic-click/bg17.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
server/resources/defaultImages/pic-click/bg18.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
server/resources/defaultImages/pic-click/bg19.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
server/resources/defaultImages/pic-click/bg20.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
server/resources/fonts/WenQuanZhengHei.ttf
Normal file
55
server/resources/fonts/license.txt
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
文泉驿是一个开源汉字字体项目
|
||||||
|
|
||||||
|
由旅美学者房骞骞(FangQ)
|
||||||
|
|
||||||
|
于2004年10月创建
|
||||||
|
|
||||||
|
集中力量解决GNU/Linux
|
||||||
|
|
||||||
|
高质量中文字体匮乏的状况
|
||||||
|
|
||||||
|
目前,文泉驿已经开发并发布了
|
||||||
|
|
||||||
|
第一个完整覆盖GB18030汉字
|
||||||
|
|
||||||
|
(包含27000多个汉字)
|
||||||
|
|
||||||
|
的多规格点阵汉字字型文件
|
||||||
|
|
||||||
|
第一个覆盖GBK字符集的
|
||||||
|
|
||||||
|
开源矢量字型文件(文泉驿正黑)
|
||||||
|
|
||||||
|
并提供了目前包含字符数目最多的
|
||||||
|
|
||||||
|
开源字体——GNU Unifont——中
|
||||||
|
|
||||||
|
绝大多数中日韩文相关的符号
|
||||||
|
|
||||||
|
这些字型文件已经逐渐成为
|
||||||
|
|
||||||
|
主流Linux/Unix发行版
|
||||||
|
|
||||||
|
中文桌面的首选中文字体
|
||||||
|
|
||||||
|
目前Ubuntu、Fedora、Slackware
|
||||||
|
|
||||||
|
Magic Linux、CDLinux
|
||||||
|
|
||||||
|
使用文泉驿作为默认中文字体
|
||||||
|
|
||||||
|
Debian、Gentoo、Mandriva
|
||||||
|
|
||||||
|
ArchLinux、Frugalware
|
||||||
|
|
||||||
|
则提供了官方源支持
|
||||||
|
|
||||||
|
而FreeBSD则在其ports中有提供
|
||||||
|
|
||||||
|
所以,今天我们所要分享的就是
|
||||||
|
|
||||||
|
文泉驿正黑体
|
||||||
|
|
||||||
|
可在Linux/UNIX,Windows
|
||||||
|
|
||||||
|
Mac OS和嵌入式操作系统中使用
|