mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-17 16:56:38 +08:00
fix: 采用弹窗的方式显示验证码,解决验证码在低分辨率下被掩盖的Bug
This commit is contained in:
parent
46a551df16
commit
bf3f68fa19
@ -70,7 +70,6 @@ func (h *UserHandler) Register(c *gin.Context) {
|
|||||||
var code int
|
var code int
|
||||||
err := h.leveldb.Get(key, &code)
|
err := h.leveldb.Get(key, &code)
|
||||||
if err != nil || code != data.Code {
|
if err != nil || code != data.Code {
|
||||||
logger.Info(code)
|
|
||||||
resp.ERROR(c, "短信验证码错误")
|
resp.ERROR(c, "短信验证码错误")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,11 @@ ALTER TABLE `chatgpt_chat_models`
|
|||||||
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
||||||
|
|
||||||
INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `created_at`, `updated_at`) VALUES
|
INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `created_at`, `updated_at`) VALUES
|
||||||
(1, 'OpenAI', 'Bot GPT-3.5', 'gpt-3.5-turbo', 0, 1, '2023-08-23 12:06:36', '2023-09-02 16:49:36'),
|
(1, 'OpenAI', 'GPT-3.5', 'gpt-3.5-turbo', 0, 1, '2023-08-23 12:06:36', '2023-09-02 16:49:36'),
|
||||||
(2, 'Azure', 'Bot Azure-3.5', 'gpt-3.5-turbo', 0, 1, '2023-08-23 12:15:30', '2023-09-02 16:49:46'),
|
(2, 'Azure', 'Azure-3.5', 'gpt-3.5-turbo', 0, 1, '2023-08-23 12:15:30', '2023-09-02 16:49:46'),
|
||||||
(3, 'ChatGML', 'ChatGML-Pro', 'chatglm_pro', 3, 1, '2023-08-23 13:35:45', '2023-08-29 11:41:29'),
|
(3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 3, 1, '2023-08-23 13:35:45', '2023-08-29 11:41:29'),
|
||||||
(5, 'ChatGML', 'ChatGLM-Std', 'chatglm_std', 2, 1, '2023-08-24 15:05:38', '2023-08-29 11:41:28'),
|
(5, 'ChatGLM', 'ChatGLM-Std', 'chatglm_std', 2, 1, '2023-08-24 15:05:38', '2023-08-29 11:41:28'),
|
||||||
(6, 'ChatGML', 'ChatGLM-Lite', 'chatglm_lite', 4, 1, '2023-08-24 15:06:15', '2023-08-29 11:41:29');
|
(6, 'ChatGLM', 'ChatGLM-Lite', 'chatglm_lite', 4, 1, '2023-08-24 15:06:15', '2023-08-29 11:41:29');
|
||||||
|
|
||||||
ALTER TABLE `chatgpt_users`
|
ALTER TABLE `chatgpt_users`
|
||||||
DROP `username`,
|
DROP `username`,
|
||||||
|
@ -12,15 +12,15 @@ npm run build
|
|||||||
cd ../docker
|
cd ../docker
|
||||||
|
|
||||||
# remove docker image if exists
|
# remove docker image if exists
|
||||||
docker rmi -f registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-go:$version
|
docker rmi -f registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-api:$version
|
||||||
# build docker image for chatgpt-plus-go
|
# build docker image for chatgpt-plus-go
|
||||||
docker build -t registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-go:$version -f dockerfile-api-go ../
|
docker build -t registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-api:$version -f dockerfile-api-go ../
|
||||||
|
|
||||||
# build docker image for chatgpt-plus-vue
|
# build docker image for chatgpt-plus-vue
|
||||||
docker rmi -f registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-vue:$version
|
docker rmi -f registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-web:$version
|
||||||
docker build --platform linux/amd64 -t registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-vue:$version -f dockerfile-vue ../
|
docker build --platform linux/amd64 -t registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-web:$version -f dockerfile-vue ../
|
||||||
|
|
||||||
if [ "$2" = "push" ];then
|
if [ "$2" = "push" ];then
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-vue:$version
|
docker push registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-api:$version
|
||||||
docker push registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-go:$version
|
docker push registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-web:$version
|
||||||
fi
|
fi
|
@ -2,7 +2,7 @@ version: '3'
|
|||||||
services:
|
services:
|
||||||
# 后端 API 程序
|
# 后端 API 程序
|
||||||
chatgpt-plus-api:
|
chatgpt-plus-api:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-api:v3.0.7.4
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-api:v3.1.0
|
||||||
container_name: chatgpt-plus-api
|
container_name: chatgpt-plus-api
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
@ -13,14 +13,14 @@ services:
|
|||||||
- "5678:5678"
|
- "5678:5678"
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
|
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime
|
||||||
- ./conf/config.toml:/var/www/app/config.toml
|
- ./conf/config.toml:/var/www/app/config.toml
|
||||||
- ./logs:/var/www/app/logs
|
- ./logs:/var/www/app/logs
|
||||||
- ./static:/var/www/app/static
|
- ./static:/var/www/app/static
|
||||||
|
|
||||||
# 前端应用
|
# 前端应用
|
||||||
chatgpt-plus-vue:
|
chatgpt-plus-web:
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/geekmaster/chatgpt-plus-vue:v3.0.7.4
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/chatgpt-plus-web:v3.1.0
|
||||||
container_name: chatgpt-plus-vue
|
container_name: chatgpt-plus-web
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
|
@ -4,5 +4,5 @@ VUE_APP_USER=18575670125
|
|||||||
VUE_APP_PASS=12345678
|
VUE_APP_PASS=12345678
|
||||||
VUE_APP_ADMIN_USER=admin
|
VUE_APP_ADMIN_USER=admin
|
||||||
VUE_APP_ADMIN_PASS=admin123
|
VUE_APP_ADMIN_PASS=admin123
|
||||||
VUE_APP_KEY_PREFIX=ChatPLUS_
|
VUE_APP_KEY_PREFIX=ChatPLUS_DEV_
|
||||||
VUE_APP_TITLE="ChatGPT-PLUS V3"
|
VUE_APP_TITLE="ChatGPT-PLUS V3"
|
||||||
|
@ -1,257 +1,265 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="wg-cap-wrap" :style="{width: width}">
|
<div class="wg-cap-wrap" :style="{width: width}">
|
||||||
<div class="wg-cap-wrap__header">
|
<div class="wg-cap-wrap__header">
|
||||||
<span>请在下图<em>依次</em>点击:</span>
|
<span>请在下图<em>依次</em>点击:</span>
|
||||||
<img class="wg-cap-wrap__thumb" v-if="thumbBase64Code" :src="thumbBase64Code" alt=" ">
|
<img class="wg-cap-wrap__thumb" v-if="thumbBase64Code" :src="thumbBase64Code" alt=" ">
|
||||||
</div>
|
</div>
|
||||||
<div class="wg-cap-wrap__body">
|
<div class="wg-cap-wrap__body">
|
||||||
<img class="wg-cap-wrap__picture" v-if="imageBase64Code" :src="imageBase64Code" alt=" " @click="handleClickPos($event)">
|
<img class="wg-cap-wrap__picture" v-if="imageBase64Code" :src="imageBase64Code" alt=" "
|
||||||
<img class="wg-cap-wrap__loading" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiByZ2JhKDI0MSwgMjQyLCAyNDMsIDApOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjM2LjgxMDEiIHI9IjEzIiBmaWxsPSIjM2U3Y2ZmIj4KICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9ImN5IiBkdXI9IjFzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgY2FsY01vZGU9InNwbGluZSIga2V5U3BsaW5lcz0iMC40NSAwIDAuOSAwLjU1OzAgMC40NSAwLjU1IDAuOSIga2V5VGltZXM9IjA7MC41OzEiIHZhbHVlcz0iMjM7Nzc7MjMiPjwvYW5pbWF0ZT4KICA8L2NpcmNsZT4KPC9zdmc+" alt="正在加载中...">
|
@click="handleClickPos($event)">
|
||||||
<div v-for="(dot, key) in dots" :key="key" class="wg-cap-wrap__dot" :style="`top: ${dot.y}px; left:${dot.x}px;`">
|
<img class="wg-cap-wrap__loading"
|
||||||
<span>{{ dot.index }}</span>
|
src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBzdHlsZT0ibWFyZ2luOiBhdXRvOyBiYWNrZ3JvdW5kOiByZ2JhKDI0MSwgMjQyLCAyNDMsIDApOyBkaXNwbGF5OiBibG9jazsgc2hhcGUtcmVuZGVyaW5nOiBhdXRvOyIgd2lkdGg9IjY0cHgiIGhlaWdodD0iNjRweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjM2LjgxMDEiIHI9IjEzIiBmaWxsPSIjM2U3Y2ZmIj4KICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9ImN5IiBkdXI9IjFzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgY2FsY01vZGU9InNwbGluZSIga2V5U3BsaW5lcz0iMC40NSAwIDAuOSAwLjU1OzAgMC40NSAwLjU1IDAuOSIga2V5VGltZXM9IjA7MC41OzEiIHZhbHVlcz0iMjM7Nzc7MjMiPjwvYW5pbWF0ZT4KICA8L2NpcmNsZT4KPC9zdmc+"
|
||||||
</div>
|
alt="正在加载中...">
|
||||||
</div>
|
<div v-for="(dot, key) in dots" :key="key" class="wg-cap-wrap__dot" :style="`top: ${dot.y}px; left:${dot.x}px;`">
|
||||||
<div class="wg-cap-wrap__footer">
|
<span>{{ dot.index }}</span>
|
||||||
<div class="wg-cap-wrap__ico">
|
|
||||||
<img @click="handleCloseEvent"
|
|
||||||
src="data:image/svg+xml;base64,PHN2ZyB0PSIxNjI2NjE0NDM5NDIzIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9Ijg2NzUiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNNTEyIDIzLjI3MjcyN2MyNjkuOTE3MDkxIDAgNDg4LjcyNzI3MyAyMTguODEwMTgyIDQ4OC43MjcyNzMgNDg4LjcyNzI3M2E0ODYuNjMyNzI3IDQ4Ni42MzI3MjcgMCAwIDEtODQuOTQ1NDU1IDI3NS40MDk0NTUgNDYuNTQ1NDU1IDQ2LjU0NTQ1NSAwIDAgMS03Ni44NDY1NDUtNTIuNTI2NTQ2QTM5My41NDE4MTggMzkzLjU0MTgxOCAwIDAgMCA5MDcuNjM2MzY0IDUxMmMwLTIxOC41MDc2MzYtMTc3LjEyODcyNy0zOTUuNjM2MzY0LTM5NS42MzYzNjQtMzk1LjYzNjM2NFMxMTYuMzYzNjM2IDI5My40OTIzNjQgMTE2LjM2MzYzNiA1MTJzMTc3LjEyODcyNyAzOTUuNjM2MzY0IDM5NS42MzYzNjQgMzk1LjYzNjM2NGEzOTUuMTcwOTA5IDM5NS4xNzA5MDkgMCAwIDAgMTI1LjQ0LTIwLjI5MzgxOSA0Ni41NDU0NTUgNDYuNTQ1NDU1IDAgMCAxIDI5LjQ4NjU0NSA4OC4yOTY3MjhBNDg4LjI2MTgxOCA0ODguMjYxODE4IDAgMCAxIDUxMiAxMDAwLjcyNzI3M0MyNDIuMDgyOTA5IDEwMDAuNzI3MjczIDIzLjI3MjcyNyA3ODEuOTE3MDkxIDIzLjI3MjcyNyA1MTJTMjQyLjA4MjkwOSAyMy4yNzI3MjcgNTEyIDIzLjI3MjcyN3ogbS0xMTUuMiAzMDcuNzEyTDUxMiA0NDYuMTM4MTgybDExNS4yLTExNS4yYTQ2LjU0NTQ1NSA0Ni41NDU0NTUgMCAxIDEgNjUuODE1MjczIDY1Ljg2MTgxOEw1NzcuODYxODE4IDUxMmwxMTUuMiAxMTUuMmE0Ni41NDU0NTUgNDYuNTQ1NDU1IDAgMSAxLTY1Ljg2MTgxOCA2NS44MTUyNzNMNTEyIDU3Ny44NjE4MThsLTExNS4yIDExNS4yYTQ2LjU0NTQ1NSA0Ni41NDU0NTUgMCAxIDEtNjUuODE1MjczLTY1Ljg2MTgxOEw0NDYuMTM4MTgyIDUxMmwtMTE1LjItMTE1LjJhNDYuNTQ1NDU1IDQ2LjU0NTQ1NSAwIDEgMSA2NS44NjE4MTgtNjUuODE1MjczeiIgcC1pZD0iODY3NiIgZmlsbD0iIzcwNzA3MCI+PC9wYXRoPjwvc3ZnPg=="
|
|
||||||
alt="关闭">
|
|
||||||
<img @click="handleRefreshEvent"
|
|
||||||
src="data:image/svg+xml;base64,PHN2ZyB0PSIxNjI2NjE0NDk5NjM4IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEzNjAiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNMTg3LjQ1NiA0MjUuMDI0YTMzNiAzMzYgMCAwIDAgMzY4LjM4NCA0MjAuMjI0IDQ4IDQ4IDAgMCAxIDEyLjU0NCA5NS4xNjggNDMyIDQzMiAwIDAgMS00NzMuNjY0LTU0MC4xNmwtNTcuMjgtMTUuMzZhMTIuOCAxMi44IDAgMCAxLTYuMjcyLTIwLjkyOGwxNTkuMTY4LTE3OS40NTZhMTIuOCAxMi44IDAgMCAxIDIyLjE0NCA1Ljg4OGw0OC4wNjQgMjM1LjA3MmExMi44IDEyLjggMCAwIDEtMTUuODA4IDE0LjkxMmwtNTcuMjgtMTUuMzZ6TTgzNi40OCA1OTkuMDRhMzM2IDMzNiAwIDAgMC0zNjguMzg0LTQyMC4yMjQgNDggNDggMCAxIDEtMTIuNTQ0LTk1LjE2OCA0MzIgNDMyIDAgMCAxIDQ3My42NjQgNTQwLjE2bDU3LjI4IDE1LjM2YTEyLjggMTIuOCAwIDAgMSA2LjI3MiAyMC45MjhsLTE1OS4xNjggMTc5LjQ1NmExMi44IDEyLjggMCAwIDEtMjIuMTQ0LTUuODg4bC00OC4wNjQtMjM1LjA3MmExMi44IDEyLjggMCAwIDEgMTUuODA4LTE0LjkxMmw1Ny4yOCAxNS4zNnoiIGZpbGw9IiM3MDcwNzAiIHAtaWQ9IjEzNjEiPjwvcGF0aD48L3N2Zz4="
|
|
||||||
alt="刷新">
|
|
||||||
</div>
|
|
||||||
<div class="wg-cap-wrap__btn">
|
|
||||||
<button @click="handleConfirmEvent">确认</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="wg-cap-wrap__footer">
|
||||||
|
<div class="wg-cap-wrap__ico">
|
||||||
|
<img @click="handleCloseEvent"
|
||||||
|
src="data:image/svg+xml;base64,PHN2ZyB0PSIxNjI2NjE0NDM5NDIzIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9Ijg2NzUiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNNTEyIDIzLjI3MjcyN2MyNjkuOTE3MDkxIDAgNDg4LjcyNzI3MyAyMTguODEwMTgyIDQ4OC43MjcyNzMgNDg4LjcyNzI3M2E0ODYuNjMyNzI3IDQ4Ni42MzI3MjcgMCAwIDEtODQuOTQ1NDU1IDI3NS40MDk0NTUgNDYuNTQ1NDU1IDQ2LjU0NTQ1NSAwIDAgMS03Ni44NDY1NDUtNTIuNTI2NTQ2QTM5My41NDE4MTggMzkzLjU0MTgxOCAwIDAgMCA5MDcuNjM2MzY0IDUxMmMwLTIxOC41MDc2MzYtMTc3LjEyODcyNy0zOTUuNjM2MzY0LTM5NS42MzYzNjQtMzk1LjYzNjM2NFMxMTYuMzYzNjM2IDI5My40OTIzNjQgMTE2LjM2MzYzNiA1MTJzMTc3LjEyODcyNyAzOTUuNjM2MzY0IDM5NS42MzYzNjQgMzk1LjYzNjM2NGEzOTUuMTcwOTA5IDM5NS4xNzA5MDkgMCAwIDAgMTI1LjQ0LTIwLjI5MzgxOSA0Ni41NDU0NTUgNDYuNTQ1NDU1IDAgMCAxIDI5LjQ4NjU0NSA4OC4yOTY3MjhBNDg4LjI2MTgxOCA0ODguMjYxODE4IDAgMCAxIDUxMiAxMDAwLjcyNzI3M0MyNDIuMDgyOTA5IDEwMDAuNzI3MjczIDIzLjI3MjcyNyA3ODEuOTE3MDkxIDIzLjI3MjcyNyA1MTJTMjQyLjA4MjkwOSAyMy4yNzI3MjcgNTEyIDIzLjI3MjcyN3ogbS0xMTUuMiAzMDcuNzEyTDUxMiA0NDYuMTM4MTgybDExNS4yLTExNS4yYTQ2LjU0NTQ1NSA0Ni41NDU0NTUgMCAxIDEgNjUuODE1MjczIDY1Ljg2MTgxOEw1NzcuODYxODE4IDUxMmwxMTUuMiAxMTUuMmE0Ni41NDU0NTUgNDYuNTQ1NDU1IDAgMSAxLTY1Ljg2MTgxOCA2NS44MTUyNzNMNTEyIDU3Ny44NjE4MThsLTExNS4yIDExNS4yYTQ2LjU0NTQ1NSA0Ni41NDU0NTUgMCAxIDEtNjUuODE1MjczLTY1Ljg2MTgxOEw0NDYuMTM4MTgyIDUxMmwtMTE1LjItMTE1LjJhNDYuNTQ1NDU1IDQ2LjU0NTQ1NSAwIDEgMSA2NS44NjE4MTgtNjUuODE1MjczeiIgcC1pZD0iODY3NiIgZmlsbD0iIzcwNzA3MCI+PC9wYXRoPjwvc3ZnPg=="
|
||||||
|
alt="关闭">
|
||||||
|
<img @click="handleRefreshEvent"
|
||||||
|
src="data:image/svg+xml;base64,PHN2ZyB0PSIxNjI2NjE0NDk5NjM4IiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEzNjAiIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBkPSJNMTg3LjQ1NiA0MjUuMDI0YTMzNiAzMzYgMCAwIDAgMzY4LjM4NCA0MjAuMjI0IDQ4IDQ4IDAgMCAxIDEyLjU0NCA5NS4xNjggNDMyIDQzMiAwIDAgMS00NzMuNjY0LTU0MC4xNmwtNTcuMjgtMTUuMzZhMTIuOCAxMi44IDAgMCAxLTYuMjcyLTIwLjkyOGwxNTkuMTY4LTE3OS40NTZhMTIuOCAxMi44IDAgMCAxIDIyLjE0NCA1Ljg4OGw0OC4wNjQgMjM1LjA3MmExMi44IDEyLjggMCAwIDEtMTUuODA4IDE0LjkxMmwtNTcuMjgtMTUuMzZ6TTgzNi40OCA1OTkuMDRhMzM2IDMzNiAwIDAgMC0zNjguMzg0LTQyMC4yMjQgNDggNDggMCAxIDEtMTIuNTQ0LTk1LjE2OCA0MzIgNDMyIDAgMCAxIDQ3My42NjQgNTQwLjE2bDU3LjI4IDE1LjM2YTEyLjggMTIuOCAwIDAgMSA2LjI3MiAyMC45MjhsLTE1OS4xNjggMTc5LjQ1NmExMi44IDEyLjggMCAwIDEtMjIuMTQ0LTUuODg4bC00OC4wNjQtMjM1LjA3MmExMi44IDEyLjggMCAwIDEgMTUuODA4LTE0LjkxMmw1Ny4yOCAxNS4zNnoiIGZpbGw9IiM3MDcwNzAiIHAtaWQ9IjEzNjEiPjwvcGF0aD48L3N2Zz4="
|
||||||
|
alt="刷新">
|
||||||
|
</div>
|
||||||
|
<div class="wg-cap-wrap__btn">
|
||||||
|
<el-button type="primary" @click="handleConfirmEvent">确认</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'CaptchaPlus',
|
name: 'CaptchaPlus',
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.$emit('refresh')
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: Boolean,
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '300px'
|
||||||
|
},
|
||||||
|
calcPosType: {
|
||||||
|
type: String,
|
||||||
|
default: 'dom',
|
||||||
|
validator: value => ['dom', 'screen'].includes(value)
|
||||||
|
},
|
||||||
|
maxDot: {
|
||||||
|
type: Number,
|
||||||
|
default: 5
|
||||||
|
// validator: value => value > 10
|
||||||
|
},
|
||||||
|
imageBase64: String,
|
||||||
|
thumbBase64: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dots: [],
|
||||||
|
imageBase64Code: '',
|
||||||
|
thumbBase64Code: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value() {
|
||||||
|
this.dots = []
|
||||||
|
this.imageBase64Code = ''
|
||||||
|
this.thumbBase64Code = ''
|
||||||
|
},
|
||||||
|
imageBase64(val) {
|
||||||
|
this.dots = []
|
||||||
|
this.imageBase64Code = val
|
||||||
|
},
|
||||||
|
thumbBase64(val) {
|
||||||
|
this.dots = []
|
||||||
|
this.thumbBase64Code = val
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* @Description: 处理关闭事件
|
||||||
|
*/
|
||||||
|
handleCloseEvent() {
|
||||||
|
this.$emit('close')
|
||||||
|
// this.dots = []
|
||||||
|
// this.imageBase64Code = ''
|
||||||
|
// this.thumbBase64Code = ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @Description: 处理刷新事件
|
||||||
|
*/
|
||||||
|
handleRefreshEvent() {
|
||||||
|
this.dots = []
|
||||||
this.$emit('refresh')
|
this.$emit('refresh')
|
||||||
},
|
},
|
||||||
props: {
|
/**
|
||||||
value: Boolean,
|
* @Description: 处理确认事件
|
||||||
width: {
|
*/
|
||||||
type: String,
|
handleConfirmEvent() {
|
||||||
default: '300px'
|
this.$emit('confirm', this.dots)
|
||||||
},
|
|
||||||
calcPosType: {
|
|
||||||
type: String,
|
|
||||||
default: 'dom',
|
|
||||||
validator: value => ['dom', 'screen'].includes(value)
|
|
||||||
},
|
|
||||||
maxDot: {
|
|
||||||
type: Number,
|
|
||||||
default: 5
|
|
||||||
// validator: value => value > 10
|
|
||||||
},
|
|
||||||
imageBase64: String,
|
|
||||||
thumbBase64: String
|
|
||||||
},
|
},
|
||||||
data() {
|
/**
|
||||||
|
* @Description: 处理dot
|
||||||
|
* @param ev
|
||||||
|
*/
|
||||||
|
handleClickPos(ev) {
|
||||||
|
if (this.dots.length >= this.maxDot) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const e = ev || window.event
|
||||||
|
e.preventDefault()
|
||||||
|
const dom = e.currentTarget
|
||||||
|
|
||||||
|
const {domX, domY} = this.getDomXY(dom)
|
||||||
|
// ===============================================
|
||||||
|
// @notice 如 getDomXY 不准确可尝试使用 calcLocationLeft 或 calcLocationTop
|
||||||
|
// const domX = this.calcLocationLeft(dom)
|
||||||
|
// const domY = this.calcLocationTop(dom)
|
||||||
|
// ===============================================
|
||||||
|
let mouseX = (navigator.vendor === 'Netscape') ? e.pageX : e.x + document.body.offsetTop
|
||||||
|
let mouseY = (navigator.vendor === 'Netscape') ? e.pageY : e.y + document.body.offsetTop
|
||||||
|
|
||||||
|
if (this.calcPosType === 'screen') {
|
||||||
|
mouseX = (navigator.vendor === 'Netscape') ? e.clientX : e.x
|
||||||
|
mouseY = (navigator.vendor === 'Netscape') ? e.clientY : e.y
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算点击的相对位置
|
||||||
|
const xPos = mouseX - domX
|
||||||
|
const yPos = mouseY - domY
|
||||||
|
|
||||||
|
// 转整形
|
||||||
|
const xp = parseInt(xPos.toString())
|
||||||
|
const yp = parseInt(yPos.toString())
|
||||||
|
|
||||||
|
// 减去点的一半
|
||||||
|
this.dots.push({
|
||||||
|
x: xp - 11,
|
||||||
|
y: yp - 11,
|
||||||
|
index: this.dots.length + 1
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @Description: 找到元素的屏幕位置
|
||||||
|
* @param el
|
||||||
|
*/
|
||||||
|
calcLocationLeft(el) {
|
||||||
|
let tmp = el.offsetLeft
|
||||||
|
let val = el.offsetParent
|
||||||
|
while (val != null) {
|
||||||
|
tmp += val.offsetLeft
|
||||||
|
val = val.offsetParent
|
||||||
|
}
|
||||||
|
return tmp
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @Description: 找到元素的屏幕位置
|
||||||
|
* @param el
|
||||||
|
*/
|
||||||
|
calcLocationTop(el) {
|
||||||
|
let tmp = el.offsetTop
|
||||||
|
let val = el.offsetParent
|
||||||
|
while (val != null) {
|
||||||
|
tmp += val.offsetTop
|
||||||
|
val = val.offsetParent
|
||||||
|
}
|
||||||
|
return tmp
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @Description: 找到元素的屏幕位置
|
||||||
|
* @param dom
|
||||||
|
*/
|
||||||
|
getDomXY(dom) {
|
||||||
|
let x = 0
|
||||||
|
let y = 0
|
||||||
|
if (dom.getBoundingClientRect) {
|
||||||
|
let box = dom.getBoundingClientRect();
|
||||||
|
let D = document.documentElement;
|
||||||
|
x = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft;
|
||||||
|
y = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop
|
||||||
|
} else {
|
||||||
|
while (dom !== document.body) {
|
||||||
|
x += dom.offsetLeft
|
||||||
|
y += dom.offsetTop
|
||||||
|
dom = dom.offsetParent
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
dots: [],
|
domX: x,
|
||||||
imageBase64Code: '',
|
domY: y
|
||||||
thumbBase64Code: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
value() {
|
|
||||||
this.dots = []
|
|
||||||
this.imageBase64Code = ''
|
|
||||||
this.thumbBase64Code = ''
|
|
||||||
},
|
|
||||||
imageBase64(val) {
|
|
||||||
this.dots = []
|
|
||||||
this.imageBase64Code = val
|
|
||||||
},
|
|
||||||
thumbBase64(val) {
|
|
||||||
this.dots = []
|
|
||||||
this.thumbBase64Code = val
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* @Description: 处理关闭事件
|
|
||||||
*/
|
|
||||||
handleCloseEvent() {
|
|
||||||
this.$emit('close')
|
|
||||||
// this.dots = []
|
|
||||||
// this.imageBase64Code = ''
|
|
||||||
// this.thumbBase64Code = ''
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @Description: 处理刷新事件
|
|
||||||
*/
|
|
||||||
handleRefreshEvent() {
|
|
||||||
this.dots = []
|
|
||||||
this.$emit('refresh')
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @Description: 处理确认事件
|
|
||||||
*/
|
|
||||||
handleConfirmEvent() {
|
|
||||||
this.$emit('confirm', this.dots)
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @Description: 处理dot
|
|
||||||
* @param ev
|
|
||||||
*/
|
|
||||||
handleClickPos(ev) {
|
|
||||||
if (this.dots.length >= this.maxDot) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const e = ev || window.event
|
|
||||||
e.preventDefault()
|
|
||||||
const dom = e.currentTarget
|
|
||||||
|
|
||||||
const {domX, domY} = this.getDomXY(dom)
|
|
||||||
// ===============================================
|
|
||||||
// @notice 如 getDomXY 不准确可尝试使用 calcLocationLeft 或 calcLocationTop
|
|
||||||
// const domX = this.calcLocationLeft(dom)
|
|
||||||
// const domY = this.calcLocationTop(dom)
|
|
||||||
// ===============================================
|
|
||||||
let mouseX = (navigator.vendor === 'Netscape') ? e.pageX : e.x + document.body.offsetTop
|
|
||||||
let mouseY = (navigator.vendor === 'Netscape') ? e.pageY : e.y + document.body.offsetTop
|
|
||||||
|
|
||||||
if (this.calcPosType === 'screen') {
|
|
||||||
mouseX = (navigator.vendor === 'Netscape') ? e.clientX : e.x
|
|
||||||
mouseY = (navigator.vendor === 'Netscape') ? e.clientY : e.y
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算点击的相对位置
|
|
||||||
const xPos = mouseX - domX
|
|
||||||
const yPos = mouseY - domY
|
|
||||||
|
|
||||||
// 转整形
|
|
||||||
const xp = parseInt(xPos.toString())
|
|
||||||
const yp = parseInt(yPos.toString())
|
|
||||||
|
|
||||||
// 减去点的一半
|
|
||||||
this.dots.push({
|
|
||||||
x: xp - 11,
|
|
||||||
y: yp - 11,
|
|
||||||
index: this.dots.length + 1
|
|
||||||
})
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @Description: 找到元素的屏幕位置
|
|
||||||
* @param el
|
|
||||||
*/
|
|
||||||
calcLocationLeft(el) {
|
|
||||||
let tmp = el.offsetLeft
|
|
||||||
let val = el.offsetParent
|
|
||||||
while (val != null) {
|
|
||||||
tmp += val.offsetLeft
|
|
||||||
val = val.offsetParent
|
|
||||||
}
|
|
||||||
return tmp
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @Description: 找到元素的屏幕位置
|
|
||||||
* @param el
|
|
||||||
*/
|
|
||||||
calcLocationTop(el) {
|
|
||||||
let tmp = el.offsetTop
|
|
||||||
let val = el.offsetParent
|
|
||||||
while (val != null) {
|
|
||||||
tmp += val.offsetTop
|
|
||||||
val = val.offsetParent
|
|
||||||
}
|
|
||||||
return tmp
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* @Description: 找到元素的屏幕位置
|
|
||||||
* @param dom
|
|
||||||
*/
|
|
||||||
getDomXY(dom){
|
|
||||||
let x = 0
|
|
||||||
let y = 0
|
|
||||||
if (dom.getBoundingClientRect) {
|
|
||||||
let box = dom.getBoundingClientRect();
|
|
||||||
let D = document.documentElement;
|
|
||||||
x = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft;
|
|
||||||
y = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
while (dom !== document.body) {
|
|
||||||
x += dom.offsetLeft
|
|
||||||
y += dom.offsetTop
|
|
||||||
dom = dom.offsetParent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
domX: x,
|
|
||||||
domY: y
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped lang="stylus">
|
||||||
.wg-cap-wrap{
|
.wg-cap-wrap {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
|
|
||||||
-webkit-border-radius: 10px;
|
-webkit-border-radius: 10px;
|
||||||
-moz-border-radius: 10px;
|
-moz-border-radius: 10px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
|
||||||
.wg-cap-wrap__header{
|
.wg-cap-wrap__header {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
|
||||||
display:-webkit-box;
|
display: -webkit-box;
|
||||||
display:-webkit-flex;
|
display: -webkit-flex;
|
||||||
display:-ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display:flex;
|
display: flex;
|
||||||
-webkit-box-align:center;
|
-webkit-box-align: center;
|
||||||
-webkit-align-items:center;
|
-webkit-align-items: center;
|
||||||
-ms-flex-align:center;
|
-ms-flex-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
|
||||||
.wg-cap-wrap__header span{
|
span {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
|
||||||
.wg-cap-wrap__header span em{
|
em {
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #3e7cff;
|
color: #3e7cff;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
.wg-cap-wrap__header .wg-cap-wrap__image{
|
}
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
.wg-cap-wrap__image {
|
||||||
border-radius: 5px;
|
-webkit-border-radius: 5px;
|
||||||
overflow: hidden;
|
-moz-border-radius: 5px;
|
||||||
text-align: center;
|
border-radius: 5px;
|
||||||
line-height: 1;
|
overflow: hidden;
|
||||||
}
|
text-align: center;
|
||||||
.wg-cap-wrap__header .wg-cap-wrap__thumb{
|
line-height: 1;
|
||||||
min-width: 150px;
|
}
|
||||||
text-align: center;
|
|
||||||
line-height: 1;
|
.wg-cap-wrap__thumb {
|
||||||
max-height: 100%;
|
min-width: 150px;
|
||||||
}
|
text-align: center;
|
||||||
.wg-cap-wrap__header .wg-cap-wrap__thumb.wg-cap-wrap__hidden{
|
line-height: 1;
|
||||||
display: none;
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wg-cap-wrap__thumb.wg-cap-wrap__hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.wg-cap-wrap__body{
|
.wg-cap-wrap__body {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: -moz-box;
|
display: -moz-box;
|
||||||
@ -264,106 +272,78 @@
|
|||||||
-moz-border-radius: 5px;
|
-moz-border-radius: 5px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
.wg-cap-wrap__body .wg-cap-wrap__picture{
|
|
||||||
position: relative;
|
|
||||||
z-index: 10;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
/*height: 100%;*/
|
.wg-cap-wrap__picture {
|
||||||
/*max-width: 100%;*/
|
position: relative;
|
||||||
/*max-height: 100%;*/
|
z-index: 10;
|
||||||
/*object-fit: cover;*/
|
width: 100%;
|
||||||
/*text-align: center;*/
|
}
|
||||||
}
|
|
||||||
.wg-cap-wrap__body .wg-cap-wrap__picture.wg-cap-wrap__hidden{
|
.wg-cap-wrap__picture.wg-cap-wrap__hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.wg-cap-wrap__body .wg-cap-wrap__loading{
|
|
||||||
position: absolute;
|
.wg-cap-wrap__loading {
|
||||||
z-index: 9;
|
position: absolute;
|
||||||
top: 50%;
|
z-index: 9;
|
||||||
left: 50%;
|
top: 50%;
|
||||||
width: 68px;
|
left: 50%;
|
||||||
height: 68px;
|
width: 68px;
|
||||||
margin-left: -34px;
|
height: 68px;
|
||||||
margin-top: -34px;
|
margin-left: -34px;
|
||||||
line-height: 68px;
|
margin-top: -34px;
|
||||||
text-align: center;
|
line-height: 68px;
|
||||||
}
|
text-align: center;
|
||||||
.wg-cap-wrap__body .wg-cap-wrap__dot{
|
}
|
||||||
position: absolute;
|
|
||||||
z-index: 10;
|
.wg-cap-wrap__dot {
|
||||||
width: 22px;
|
position: absolute;
|
||||||
height: 22px;
|
z-index: 10;
|
||||||
color: #cedffe;
|
width: 22px;
|
||||||
background: #3e7cff;
|
height: 22px;
|
||||||
border: 2px solid #f7f9fb;
|
color: #cedffe;
|
||||||
line-height: 20px;
|
background: #3e7cff;
|
||||||
text-align: center;
|
border: 2px solid #f7f9fb;
|
||||||
-webkit-border-radius: 22px;
|
line-height: 20px;
|
||||||
-moz-border-radius: 22px;
|
text-align: center;
|
||||||
border-radius: 22px;
|
-webkit-border-radius: 22px;
|
||||||
cursor: default;
|
-moz-border-radius: 22px;
|
||||||
|
border-radius: 22px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wg-cap-wrap__footer {
|
.wg-cap-wrap__footer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
color: #34383e;
|
color: #34383e;
|
||||||
display:-webkit-box;
|
display: -webkit-box;
|
||||||
display:-webkit-flex;
|
display: -webkit-flex;
|
||||||
display:-ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display:flex;
|
display: flex;
|
||||||
-webkit-box-align:center;
|
-webkit-box-align: center;
|
||||||
-webkit-align-items:center;
|
-webkit-align-items: center;
|
||||||
-ms-flex-align:center;
|
-ms-flex-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding-top: 15px;
|
padding-top: 15px;
|
||||||
|
|
||||||
|
.wg-cap-wrap__ico {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: #34383e;
|
||||||
|
margin: 0 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wg-cap-wrap__btn {
|
||||||
|
display flex
|
||||||
|
width: 120px;
|
||||||
|
justify-content right
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.wg-cap-wrap__footer .wg-cap-wrap__ico{
|
}
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.wg-cap-wrap__footer .wg-cap-wrap__ico img{
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
color: #34383e;
|
|
||||||
margin: 0 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.wg-cap-wrap__footer .wg-cap-wrap__btn{
|
|
||||||
width: 120px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
.wg-cap-wrap__footer .wg-cap-wrap__btn button{
|
|
||||||
width: 100%;
|
|
||||||
height: 40px;
|
|
||||||
letter-spacing: 2px;
|
|
||||||
text-align: center;
|
|
||||||
padding: 9px 15px;
|
|
||||||
font-size: 15px;
|
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
-moz-border-radius: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 1;
|
|
||||||
white-space: nowrap;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #409eff;
|
|
||||||
border: 1px solid #409eff;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
outline: none;
|
|
||||||
margin: 0;
|
|
||||||
transition: .1s;
|
|
||||||
font-weight: 500;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
}
|
|
||||||
.wg-cap-wrap__footer .wg-cap-wrap__btn button:hover {
|
|
||||||
background: #66b1ff;
|
|
||||||
border-color: #66b1ff;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,29 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container>
|
<el-container class="captcha-box">
|
||||||
<el-popover
|
<el-button type="primary" class="send-btn" :size="props.size" :disabled="!canSend" @click="loadCaptcha" plain>
|
||||||
:visible="showCaptcha"
|
{{ btnText }}
|
||||||
:hide-after="0"
|
</el-button>
|
||||||
placement="top"
|
|
||||||
:width="325"
|
<el-dialog
|
||||||
trigger="click"
|
v-model="showCaptcha"
|
||||||
content="this is content, this is content, this is content"
|
:close-on-click-modal="true"
|
||||||
|
:show-close="false"
|
||||||
|
style="width:90%;max-width: 360px;"
|
||||||
>
|
>
|
||||||
<captcha-plus
|
<captcha-plus
|
||||||
v-if="showCaptcha"
|
|
||||||
:max-dot="maxDot"
|
:max-dot="maxDot"
|
||||||
:image-base64="imageBase64"
|
:image-base64="imageBase64"
|
||||||
:thumb-base64="thumbBase64"
|
:thumb-base64="thumbBase64"
|
||||||
|
width="300"
|
||||||
@close="showCaptcha = false"
|
@close="showCaptcha = false"
|
||||||
@refresh="handleRequestCaptCode"
|
@refresh="handleRequestCaptCode"
|
||||||
@confirm="handleConfirm"
|
@confirm="handleConfirm"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<template #reference>
|
</el-dialog>
|
||||||
<el-button type="primary" :size="props.size" :disabled="!canSend" @click="loadCaptcha" plain>
|
|
||||||
{{ btnText }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popover>
|
|
||||||
</el-container>
|
</el-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -75,6 +72,7 @@ const handleConfirm = (dots) => {
|
|||||||
dots: dots.value,
|
dots: dots.value,
|
||||||
key: captKey.value
|
key: captKey.value
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
// ElMessage.success('人机验证成功')
|
||||||
showCaptcha.value = false
|
showCaptcha.value = false
|
||||||
sendMsg()
|
sendMsg()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -120,6 +118,21 @@ const sendMsg = () => {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="stylus">
|
||||||
|
|
||||||
|
.captcha-box {
|
||||||
|
.send-btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog {
|
||||||
|
.el-dialog__header {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
//padding 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -18,7 +18,7 @@
|
|||||||
placeholder="请输入短信验证码"
|
placeholder="请输入短信验证码"
|
||||||
>
|
>
|
||||||
<template #button>
|
<template #button>
|
||||||
<send-msg-mobile size="small" :mobile="form.mobile"/>
|
<send-msg size="small" :mobile="form.mobile"/>
|
||||||
</template>
|
</template>
|
||||||
</van-field>
|
</van-field>
|
||||||
</van-cell-group>
|
</van-cell-group>
|
||||||
@ -30,7 +30,7 @@ import {computed, ref} from "vue";
|
|||||||
import {httpPost} from "@/utils/http";
|
import {httpPost} from "@/utils/http";
|
||||||
import {validateMobile} from "@/utils/validate";
|
import {validateMobile} from "@/utils/validate";
|
||||||
import {showNotify} from "vant";
|
import {showNotify} from "vant";
|
||||||
import SendMsgMobile from "@/components/mobile/SendMsgMobile.vue";
|
import SendMsg from "@/components/SendMsg.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-container class="captcha-box">
|
|
||||||
<el-button type="primary" class="send-btn" :size="props.size" :disabled="!canSend" @click="loadCaptcha" plain>
|
|
||||||
{{ btnText }}
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
<el-dialog
|
|
||||||
v-model="showCaptcha"
|
|
||||||
:close-on-click-modal="true"
|
|
||||||
:show-close="false"
|
|
||||||
style="width:90%;max-width: 800px;"
|
|
||||||
>
|
|
||||||
<captcha-plus
|
|
||||||
:max-dot="maxDot"
|
|
||||||
:image-base64="imageBase64"
|
|
||||||
:thumb-base64="thumbBase64"
|
|
||||||
width="100%"
|
|
||||||
@close="showCaptcha = false"
|
|
||||||
@refresh="handleRequestCaptCode"
|
|
||||||
@confirm="handleConfirm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</el-dialog>
|
|
||||||
</el-container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
// 发送短信验证码组件
|
|
||||||
import {ref} from "vue";
|
|
||||||
import lodash from 'lodash'
|
|
||||||
import {validateMobile} from "@/utils/validate";
|
|
||||||
import {ElMessage} from "element-plus";
|
|
||||||
import {httpGet, httpPost} from "@/utils/http";
|
|
||||||
import CaptchaPlus from "@/components/CaptchaPlus.vue";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
mobile: String,
|
|
||||||
size: String,
|
|
||||||
});
|
|
||||||
const btnText = ref('发送验证码')
|
|
||||||
const canSend = ref(true)
|
|
||||||
const showCaptcha = ref(false)
|
|
||||||
const maxDot = ref(5)
|
|
||||||
const imageBase64 = ref('')
|
|
||||||
const thumbBase64 = ref('')
|
|
||||||
const captKey = ref('')
|
|
||||||
const dots = ref(null)
|
|
||||||
|
|
||||||
const handleRequestCaptCode = () => {
|
|
||||||
|
|
||||||
httpGet('/api/captcha/get').then(res => {
|
|
||||||
const data = res.data
|
|
||||||
imageBase64.value = data.image
|
|
||||||
thumbBase64.value = data.thumb
|
|
||||||
captKey.value = data.key
|
|
||||||
}).catch(e => {
|
|
||||||
ElMessage.error('获取人机验证数据失败:' + e.message)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleConfirm = (dots) => {
|
|
||||||
if (lodash.size(dots) <= 0) {
|
|
||||||
return ElMessage.error('请进行人机验证再操作')
|
|
||||||
}
|
|
||||||
|
|
||||||
let dotArr = []
|
|
||||||
lodash.forEach(dots, (dot) => {
|
|
||||||
dotArr.push(dot.x, dot.y)
|
|
||||||
})
|
|
||||||
dots.value = dotArr.join(',')
|
|
||||||
httpPost('/api/captcha/check', {
|
|
||||||
dots: dots.value,
|
|
||||||
key: captKey.value
|
|
||||||
}).then(() => {
|
|
||||||
showCaptcha.value = false
|
|
||||||
sendMsg()
|
|
||||||
}).catch(() => {
|
|
||||||
ElMessage.error('人机验证失败')
|
|
||||||
handleRequestCaptCode()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadCaptcha = () => {
|
|
||||||
if (!validateMobile(props.mobile)) {
|
|
||||||
return ElMessage.error("请输入合法的手机号")
|
|
||||||
}
|
|
||||||
|
|
||||||
showCaptcha.value = true
|
|
||||||
handleRequestCaptCode() // 每次点开都刷新验证码
|
|
||||||
}
|
|
||||||
|
|
||||||
const sendMsg = () => {
|
|
||||||
if (!canSend.value) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
canSend.value = false
|
|
||||||
httpPost('/api/sms/code', {mobile: props.mobile, key: captKey.value, dots: dots.value}).then(() => {
|
|
||||||
ElMessage.success('短信发送成功')
|
|
||||||
let time = 120
|
|
||||||
btnText.value = time
|
|
||||||
const handler = setInterval(() => {
|
|
||||||
time = time - 1
|
|
||||||
if (time <= 0) {
|
|
||||||
clearInterval(handler)
|
|
||||||
btnText.value = '重新发送'
|
|
||||||
canSend.value = true
|
|
||||||
} else {
|
|
||||||
btnText.value = time
|
|
||||||
}
|
|
||||||
}, 1000)
|
|
||||||
}).catch(e => {
|
|
||||||
canSend.value = true
|
|
||||||
ElMessage.error('短信发送失败:' + e.message)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus">
|
|
||||||
|
|
||||||
.captcha-box {
|
|
||||||
.send-btn {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-dialog {
|
|
||||||
.el-dialog__header {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-dialog__body {
|
|
||||||
//padding 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -9,7 +9,7 @@
|
|||||||
<div class="header">{{ title }}</div>
|
<div class="header">{{ title }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<el-input placeholder="手机号" size="large" v-model="username" autocomplete="off">
|
<el-input placeholder="手机号" size="large" maxlength="11" v-model="username" autocomplete="off">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<UserFilled/>
|
<UserFilled/>
|
||||||
@ -57,6 +57,7 @@ import FooterBar from "@/components/FooterBar.vue";
|
|||||||
import {isMobile} from "@/utils/libs";
|
import {isMobile} from "@/utils/libs";
|
||||||
import {checkSession} from "@/action/session";
|
import {checkSession} from "@/action/session";
|
||||||
import {setUserToken} from "@/store/session";
|
import {setUserToken} from "@/store/session";
|
||||||
|
import {validateMobile} from "@/utils/validate";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const title = ref('ChatGPT-PLUS 用户登录');
|
const title = ref('ChatGPT-PLUS 用户登录');
|
||||||
@ -81,8 +82,8 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const login = function () {
|
const login = function () {
|
||||||
if (username.value === '') {
|
if (!validateMobile(username.value)) {
|
||||||
return ElMessage.error('请输入用户名');
|
return ElMessage.error('请输入合法的手机号');
|
||||||
}
|
}
|
||||||
if (password.value.trim() === '') {
|
if (password.value.trim() === '') {
|
||||||
return ElMessage.error('请输入密码');
|
return ElMessage.error('请输入密码');
|
||||||
|
@ -64,8 +64,7 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<send-msg-mobile size="large" :mobile="formData.mobile" v-if="isMobile()"/>
|
<send-msg size="large" :mobile="formData.mobile"/>
|
||||||
<send-msg size="large" :mobile="formData.mobile" v-else/>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
@ -109,7 +108,7 @@ import FooterBar from "@/components/FooterBar.vue";
|
|||||||
import SendMsg from "@/components/SendMsg.vue";
|
import SendMsg from "@/components/SendMsg.vue";
|
||||||
import {validateMobile} from "@/utils/validate";
|
import {validateMobile} from "@/utils/validate";
|
||||||
import {isMobile} from "@/utils/libs";
|
import {isMobile} from "@/utils/libs";
|
||||||
import SendMsgMobile from "@/components/mobile/SendMsgMobile.vue";
|
import SendMsgMobile from "@/components/SendMsg.vue";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const title = ref('ChatGPT-PLUS 用户注册');
|
const title = ref('ChatGPT-PLUS 用户注册');
|
||||||
|
Loading…
Reference in New Issue
Block a user