✨ add rotate captcha
This commit is contained in:
4
components.d.ts
vendored
4
components.d.ts
vendored
@@ -28,7 +28,6 @@ declare module 'vue' {
|
||||
ATooltip: typeof import('ant-design-vue/es')['Tooltip']
|
||||
BoxDog: typeof import('./src/components/BoxDog/BoxDog.vue')['default']
|
||||
DynamicTitle: typeof import('./src/components/DynamicTitle/DynamicTitle.vue')['default']
|
||||
FoegetPage: typeof import('./src/views/Forget/FoegetPage.vue')['default']
|
||||
ForgetPage: typeof import('./src/views/Forget/ForgetPage.vue')['default']
|
||||
LockOutlined: typeof import('@ant-design/icons-vue')['LockOutlined']
|
||||
LoginFooter: typeof import('./src/views/Login/LoginFooter.vue')['default']
|
||||
@@ -36,15 +35,12 @@ declare module 'vue' {
|
||||
NotFound: typeof import('./src/views/404/NotFound.vue')['default']
|
||||
QRLogin: typeof import('./src/views/QRLogin/QRLogin.vue')['default']
|
||||
QRLoginFooter: typeof import('./src/views/QRLogin/QRLoginFooter.vue')['default']
|
||||
RegisterFooter: typeof import('./src/views/Register/RegisterFooter.vue')['default']
|
||||
RegisterPage: typeof import('./src/views/Register/RegisterPage.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
SafetyOutlined: typeof import('@ant-design/icons-vue')['SafetyOutlined']
|
||||
TabletOutlined: typeof import('@ant-design/icons-vue')['TabletOutlined']
|
||||
TestI18n: typeof import('./src/views/TestI18n.vue')['default']
|
||||
TestTheme: typeof import('./src/views/TestTheme.vue')['default']
|
||||
TotoroCom: typeof import('./src/components/Totoro/TotoroCom.vue')['default']
|
||||
UserOutlined: typeof import('@ant-design/icons-vue')['UserOutlined']
|
||||
}
|
||||
}
|
||||
|
20
index.html
20
index.html
@@ -1,13 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><%- title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<link rel="icon" type="image/svg+xml" href="/schisandra.svg"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title><%- title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -20,6 +20,7 @@
|
||||
"axios": "^1.7.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
"eslint": "9.9.0",
|
||||
"go-captcha-vue": "^2",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"less": "^4.2.0",
|
||||
"localforage": "^1.10.0",
|
||||
|
77
public/schisandra.svg
Normal file
77
public/schisandra.svg
Normal file
@@ -0,0 +1,77 @@
|
||||
<svg t="1710925923326" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8087"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M481.866 554.39C307.518 329.956 137.124 467.312 87.72 516.212c-8.342 8.258-4.326 23.352 8.838 33.298 79.538 60.1 340.138 238.074 393.422 34.128 2.33-8.918-0.66-19.652-8.114-29.248z"
|
||||
fill="#CCC033" p-id="8088"></path>
|
||||
<path
|
||||
d="M481.866 554.388C307.518 329.956 137.124 467.312 87.72 516.212c-5.48 5.424-5.598 13.796-1.32 21.726 78.098-41.21 195.85-57.526 315.466 96.452 7.456 9.598 10.446 20.33 8.116 29.25a207.5 207.5 0 0 1-3.572 12.14c38.236-8.552 68.836-35.732 83.572-92.14 2.328-8.92-0.662-19.654-8.116-29.252z"
|
||||
fill="#99AF17"></path>
|
||||
<path
|
||||
d="M608.99 589.628c107.374 263.132 308.492 176.808 369.252 143.04 10.26-5.702 10.462-21.32 0.468-34.448-60.388-79.32-263.344-320.97-369.648-138.946-4.648 7.96-4.662 19.102-0.072 30.354z"
|
||||
fill="#EACF32" p-id="8090"></path>
|
||||
<path
|
||||
d="M820.558 537.238c-74.148-52.542-155.996-73-211.496 22.036-4.648 7.96-4.664 19.102-0.072 30.354 46.838 114.78 111.512 163.062 174.594 178.224-25.672-20.84-50.152-50.102-71.994-90.258 15.608-16.372 25.21-38.522 25.21-62.93a90.812 90.812 0 0 0-17.646-53.916 135.364 135.364 0 0 0-7.852 7.886c32.054-34.944 70.066-41.51 109.256-31.396z m-128.932 98.73z m17.05 36.168z m-16.4-34.654z m2.712 6.244z m2.65 5.892z m2.686 5.77z m2.722 5.648z m2.786 5.59z m1.73-93.752z m-18.5 26.4z m4.286-6.992z m3.516-5.332z m3.498-4.94z m3.564-4.688z"
|
||||
fill="#CCC033" p-id="8091"></path>
|
||||
<path
|
||||
d="M65.508 873.848C533.44 700.74 756.58 451.128 824.804 362c13.046-17.044 7.766-41.7-11.132-51.876l-0.006-0.004c-15.116-8.14-33.912-4.076-44.27 9.616-55.86 73.84-256.384 304.032-719.526 516.368-10.962 5.026-15.234 18.396-9.188 28.83 4.996 8.622 15.482 12.37 24.826 8.914z"
|
||||
fill="#A56021" p-id="8092"></path>
|
||||
<path d="M494.452 523.422m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF4B34"
|
||||
p-id="8093"></path>
|
||||
<path d="M469.542 645.53m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF624B"
|
||||
p-id="8094"></path>
|
||||
<path
|
||||
d="M61.034 874.934c455.172-210.888 652.954-437.954 708.36-511.196 10.358-13.692 29.154-17.756 44.27-9.616l0.006 0.004a34.662 34.662 0 0 1 10.486 8.712l0.646-0.838c13.046-17.044 7.766-41.698-11.132-51.876l-0.006-0.004c-15.116-8.14-33.912-4.076-44.27 9.616-55.86 73.84-256.384 304.032-719.526 516.368-10.962 5.026-15.234 18.396-9.188 28.832 4.21 7.262 12.316 11.046 20.354 9.998z"
|
||||
fill="#8C4C17" p-id="8095"></path>
|
||||
<path
|
||||
d="M528.2 528.198c-243.476-146.586-127.232-332.026-84.516-386.866 7.214-9.26 22.676-7.056 34.11 4.84 69.084 71.874 276.624 309.598 80.41 386.626-8.58 3.368-19.592 1.668-30.004-4.6z"
|
||||
fill="#CCC033" p-id="8096"></path>
|
||||
<path d="M479.496 727.3m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF624B"
|
||||
p-id="8097"></path>
|
||||
<path
|
||||
d="M456.826 708.832c24.952-30.628 65.664-40.844 100.914-28.496a91.066 91.066 0 0 0-20.616-23.774c-39.068-31.828-96.538-25.958-128.366 13.11-31.826 39.068-25.958 96.54 13.11 128.366a91.02 91.02 0 0 0 27.452 15.384c-19.22-32.026-17.446-73.962 7.506-104.59z"
|
||||
fill="#FF4B34" p-id="8098"></path>
|
||||
<path
|
||||
d="M490.916 794.086a12.004 12.004 0 0 1-11.27-7.88 11.998 11.998 0 0 1 7.148-15.392c17.892-6.544 29.342-15.336 34.034-26.128 4.95-11.388 0.736-21.612 0.554-22.042-2.728-6.04-0.014-13.084 6.026-15.812 6.04-2.73 13.176 0.02 15.904 6.06 0.896 1.986 8.51 20.002-0.222 40.774-7.29 17.338-23.456 30.692-48.05 39.688a12.046 12.046 0 0 1-4.124 0.732z"
|
||||
fill="#FF9079" p-id="8099"></path>
|
||||
<path d="M403.212 559.58m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF624B"
|
||||
p-id="8100"></path>
|
||||
<path
|
||||
d="M375.942 570.134c-14.258-36.844-2.978-77.274 25.202-101.786a91.07 91.07 0 0 0-30.864 6.142c-46.994 18.188-70.348 71.026-52.16 118.022 18.188 46.994 71.028 70.348 118.022 52.16a91.034 91.034 0 0 0 26.958-16.234c-37.34 0.842-72.9-21.462-87.158-58.304z"
|
||||
fill="#FF4B34" p-id="8101"></path>
|
||||
<path
|
||||
d="M456.478 588.782a12 12 0 0 1-11.846-14c3.204-18.978 1.164-33.372-6.064-42.784-7.416-9.656-18.42-11.092-18.528-11.102a12 12 0 0 1 2.246-23.894c2.168 0.204 21.592 2.508 35.316 20.378 11.456 14.916 15.054 35.574 10.694 61.398a12.004 12.004 0 0 1-11.818 10.004z"
|
||||
fill="#FF9079" p-id="8102"></path>
|
||||
<path
|
||||
d="M491.586 160.806a1040.528 1040.528 0 0 0-13.792-14.636c-11.434-11.896-26.898-14.1-34.11-4.838-42.716 54.84-158.958 240.28 84.516 386.866 10.412 6.268 21.424 7.968 30.004 4.6 8.192-3.216 15.664-6.718 22.486-10.47-208.196-131.322-136.172-291.618-89.104-361.522z"
|
||||
fill="#99AF17" p-id="8103"></path>
|
||||
<path d="M605.562 614.662m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF624B"
|
||||
p-id="8104"></path>
|
||||
<path
|
||||
d="M576.32 614.664c0-39.506 25.112-73.14 60.24-85.83a91.062 91.062 0 0 0-31-5.41c-50.39 0-91.24 40.85-91.24 91.24 0 50.39 40.85 91.24 91.24 91.24 10.886 0 21.322-1.914 31-5.412-35.128-12.69-60.24-46.324-60.24-85.828z"
|
||||
fill="#FF4B34" p-id="8105"></path>
|
||||
<path
|
||||
d="M649.002 661.926a12 12 0 0 1-10.302-18.136c9.74-16.376 13.064-30.422 9.884-41.752-3.356-11.954-13.08-17.222-13.492-17.44-5.93-2.96-8.276-10.134-5.316-16.064 2.958-5.93 10.224-8.306 16.158-5.346 1.95 0.974 19.232 10.132 25.582 31.75 5.3 18.046 1.2 38.61-12.188 61.12a11.992 11.992 0 0 1-10.326 5.868z"
|
||||
fill="#FF9079" p-id="8106"></path>
|
||||
<path d="M378.3 797.142m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF624B"
|
||||
p-id="8107"></path>
|
||||
<path
|
||||
d="M349.704 791.034c8.252-38.634 39.836-66.28 76.842-71.352a91.028 91.028 0 0 0-29.186-11.768c-49.28-10.526-97.762 20.888-108.288 70.168-10.526 49.278 20.888 97.762 70.168 108.288a91.04 91.04 0 0 0 31.446 1.184c-31.702-19.75-49.234-57.886-40.982-96.52z"
|
||||
fill="#FF4B34" p-id="8108"></path>
|
||||
<path
|
||||
d="M413.426 852.702a12 12 0 0 1-8.802-20.152c12.944-13.98 19.13-27.022 18.388-38.766-0.784-12.392-9.194-19.574-9.55-19.874-5.18-4.134-5.976-11.64-1.842-16.822 4.134-5.18 11.736-5.986 16.918-1.854 1.704 1.358 16.69 13.926 18.384 36.396 1.414 18.756-6.892 38.008-24.686 57.224a11.968 11.968 0 0 1-8.81 3.848z"
|
||||
fill="#FF9079" p-id="8109"></path>
|
||||
<path d="M277.996 678.872m-91.24 0a91.24 91.24 0 1 0 182.48 0 91.24 91.24 0 1 0-182.48 0Z" fill="#FF624B"
|
||||
p-id="8110"></path>
|
||||
<path
|
||||
d="M248.754 678.872c0-39.506 25.112-73.14 60.24-85.83a91.062 91.062 0 0 0-31-5.41c-50.39 0-91.24 40.85-91.24 91.24 0 50.39 40.85 91.24 91.24 91.24 10.886 0 21.322-1.914 31-5.412-35.128-12.688-60.24-46.322-60.24-85.828z"
|
||||
fill="#FF4B34" p-id="8111"></path>
|
||||
<path
|
||||
d="M321.438 726.136a12 12 0 0 1-10.302-18.136c9.738-16.374 13.064-30.422 9.884-41.752-3.356-11.956-13.08-17.222-13.492-17.44-5.93-2.96-8.276-10.136-5.316-16.064 2.96-5.93 10.226-8.306 16.158-5.346 1.95 0.974 19.232 10.132 25.582 31.752 5.3 18.046 1.2 38.61-12.186 61.12a12.006 12.006 0 0 1-10.328 5.866z"
|
||||
fill="#FF9079" p-id="8112"></path>
|
||||
<path d="M557.74 439.404m-30 0a30 30 0 1 0 60 0 30 30 0 1 0-60 0Z" fill="#99AF17" p-id="8113"></path>
|
||||
<path d="M494.478 368.528m-30 0a30 30 0 1 0 60 0 30 30 0 1 0-60 0Z" fill="#99AF17" p-id="8114"></path>
|
||||
<path d="M785.856 674.864m-30 0a30 30 0 1 0 60 0 30 30 0 1 0-60 0Z" fill="#CCC033" p-id="8115"></path>
|
||||
<path
|
||||
d="M927.274 710.09a11.966 11.966 0 0 1-8.664-3.696l-65.998-68.844a12 12 0 0 1 17.324-16.608l65.998 68.844a12 12 0 0 1-8.66 20.304z"
|
||||
fill="#FCE575" p-id="8116"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 7.2 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
Before Width: | Height: | Size: 1.5 KiB |
23
src/api/captcha/index.ts
Normal file
23
src/api/captcha/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import {service} from "@/utils/alova/service.ts";
|
||||
|
||||
export const getRotatedCaptchaData = () => {
|
||||
return service.Get('/api/captcha/rotate/get', {
|
||||
meta: {
|
||||
ignoreToken: true
|
||||
},
|
||||
});
|
||||
|
||||
};
|
||||
export const checkRotatedCaptcha = (angle: any, key: any) => {
|
||||
return service.Post('/api/captcha/rotate/check', {
|
||||
angle: angle,
|
||||
key: key,
|
||||
},
|
||||
{
|
||||
meta: {
|
||||
ignoreToken: true
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
};
|
@@ -29,6 +29,11 @@ export default {
|
||||
repasswordValidate: "please enter the confirmation password",
|
||||
forgetPassword: "forget password",
|
||||
resetPassword: "reset password",
|
||||
captchaSuccess: "captcha success!",
|
||||
captchaError: "captcha failed!",
|
||||
rotateCaptchaTitle: "Please drag the slider to complete the puzzle",
|
||||
systemError: "System error, please try again later",
|
||||
captchaExpired: "captcha expired, please try again",
|
||||
},
|
||||
error: {
|
||||
networkError: 'Network error, please try again later',
|
||||
|
@@ -29,6 +29,12 @@ export default {
|
||||
repasswordValidate: "请输入确认密码",
|
||||
forgetPassword: "忘记密码",
|
||||
resetPassword: "重置密码",
|
||||
captchaSuccess: "验证成功!",
|
||||
captchaError: "验证失败!",
|
||||
rotateCaptchaTitle: "请拖动滑块完成拼图",
|
||||
systemError: "系统错误!请稍后再试!",
|
||||
captchaExpired: "验证码已过期,请重新获取!",
|
||||
|
||||
},
|
||||
error: {
|
||||
networkError: '网络连接失败!',
|
||||
|
@@ -5,9 +5,12 @@ import '@/assets/styles/global.scss';
|
||||
import i18n from "@/locales/index.ts";
|
||||
import {setupStore} from "@/store/pinia.ts";
|
||||
import router from "@/router/router.ts";
|
||||
import "go-captcha-vue/dist/style.css"
|
||||
import GoCaptcha from "go-captcha-vue"
|
||||
|
||||
const app = createApp(App);
|
||||
setupStore(app);
|
||||
app.use(router);
|
||||
app.use(i18n);
|
||||
app.use(GoCaptcha)
|
||||
app.mount('#app');
|
||||
|
@@ -5,13 +5,13 @@ import variables from '@/assets/styles/colors.module.scss';
|
||||
import {parse, stringify} from "zipson/lib";
|
||||
|
||||
/**
|
||||
* theme 配置 开启持久化
|
||||
* theme 配置
|
||||
*/
|
||||
export const useThemeStore = defineStore(
|
||||
'theme',
|
||||
() => {
|
||||
const themeName = ref('green'); // 主题名称
|
||||
const darkMode = ref('light'); // 颜色模式
|
||||
const themeName = ref<string>('green'); // 主题名称
|
||||
const darkMode = ref<string>('light'); // 颜色模式
|
||||
const darkModeComp = computed(() => {
|
||||
document.documentElement.setAttribute('data-dark', darkMode.value);
|
||||
return darkMode.value;
|
||||
|
@@ -17,10 +17,10 @@ export const service = createAlova({
|
||||
requestAdapter: axiosRequestAdapter(),
|
||||
l2Cache: localforageStorageAdapter,
|
||||
cacheFor: {
|
||||
GET: {
|
||||
mode: 'restore',
|
||||
expire: 10 * 1000
|
||||
},
|
||||
// GET: {
|
||||
// mode: 'restore',
|
||||
// expire: 10 * 1000
|
||||
// },
|
||||
},
|
||||
cacheLogger: import.meta.env.VITE_NODE_ENV === 'development',
|
||||
// 设置全局的请求拦截器
|
||||
|
@@ -15,7 +15,7 @@
|
||||
import {GithubOutlined, QqOutlined, QrcodeOutlined} from "@ant-design/icons-vue";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {h} from "vue";
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useRouter} from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
const {t} = useI18n();
|
||||
|
@@ -33,7 +33,8 @@
|
||||
<AFlex :vertical="true">
|
||||
<span class="login-card-span">{{ t("login.phoneCaptcha") }}</span>
|
||||
<AFlex :vertical="false" align="center" justify="center">
|
||||
<AInput v-model:value="phoneLoginForm.captcha" size="large" :placeholder=captchaValidate allow-clear>
|
||||
<AInput v-model:value="phoneLoginForm.captcha" size="large" :placeholder=captchaValidate
|
||||
allow-clear>
|
||||
<template #prefix>
|
||||
<SafetyOutlined/>
|
||||
</template>
|
||||
@@ -126,6 +127,18 @@
|
||||
</ATooltip>
|
||||
</ACard>
|
||||
</div>
|
||||
<div v-if="showRotateCaptcha" class="mask">
|
||||
<!-- 滑动验证码 -->
|
||||
<gocaptcha-rotate
|
||||
class="gocaptcha-rotate"
|
||||
v-if="showRotateCaptcha"
|
||||
:data="captchaData"
|
||||
:config="{
|
||||
title: t('login.rotateCaptchaTitle'),
|
||||
}"
|
||||
:events="rotateEvent"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -136,11 +149,27 @@ import {useI18n} from "vue-i18n";
|
||||
import BoxDog from "@/components/BoxDog/BoxDog.vue";
|
||||
import LoginFooter from "@/views/Login/LoginFooter.vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import {checkRotatedCaptcha, getRotatedCaptchaData} from "@/api/captcha";
|
||||
import {message} from "ant-design-vue";
|
||||
|
||||
const router = useRouter();
|
||||
const {t} = useI18n();
|
||||
const accountLoginFormRef = ref<any>();
|
||||
const phoneLoginFormRef = ref<any>();
|
||||
const showRotateCaptcha = ref<boolean>(false);
|
||||
const captchaData = reactive({angle: 0, image: "", thumb: "", key: ""});
|
||||
const captchaErrorCount = ref<number>(0);
|
||||
const rotateEvent = {
|
||||
confirm: (angle: number) => {
|
||||
checkCaptcha(angle);
|
||||
},
|
||||
close: () => {
|
||||
closeRotateCaptcha();
|
||||
},
|
||||
refresh: () => {
|
||||
getRotateCaptcha();
|
||||
},
|
||||
};
|
||||
// 账号登录表单数据
|
||||
const accountLoginForm: UnwrapRef<AccountLogin> = reactive({
|
||||
account: '',
|
||||
@@ -185,11 +214,12 @@ const state = reactive({
|
||||
countDownTime: 60,
|
||||
showCountDown: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* 验证码发送倒计时
|
||||
*/
|
||||
const countDown = () => {
|
||||
const startTime = localStorage.getItem('startTimeSendCaptcha');
|
||||
const startTime = localStorage.getItem('start_time_send_captcha');
|
||||
const nowTime = new Date().getTime();
|
||||
let surplus: number = 60;
|
||||
let timer: any;
|
||||
@@ -197,17 +227,15 @@ const countDown = () => {
|
||||
surplus = 60 - Math.floor((nowTime - Number(startTime)) / 1000);
|
||||
surplus = surplus <= 0 ? 0 : surplus;
|
||||
} else {
|
||||
localStorage.setItem('startTimeSendCaptcha', String(nowTime));
|
||||
localStorage.setItem('start_time_send_captcha', String(nowTime));
|
||||
}
|
||||
|
||||
state.countDownTime = surplus;
|
||||
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
timer = setInterval(() => {
|
||||
if (state.countDownTime <= 0) {
|
||||
localStorage.removeItem('startTimeSendCaptcha');
|
||||
localStorage.removeItem('start_time_send_captcha');
|
||||
clearInterval(timer);
|
||||
state.countDownTime = 60;
|
||||
state.showCountDown = false;
|
||||
@@ -218,7 +246,7 @@ const countDown = () => {
|
||||
}, 1000);
|
||||
};
|
||||
onMounted(() => {
|
||||
const sendEndTime = localStorage.getItem('startTimeSendCaptcha');
|
||||
const sendEndTime = localStorage.getItem('start_time_send_captcha');
|
||||
if (sendEndTime) {
|
||||
state.showCountDown = true;
|
||||
countDown();
|
||||
@@ -232,8 +260,8 @@ async function sendCaptcha() {
|
||||
phoneLoginFormRef.value
|
||||
.validateFields("phone")
|
||||
.then(() => {
|
||||
countDown();
|
||||
console.log('values');
|
||||
showRotateCaptcha.value = true;
|
||||
getRotateCaptcha();
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.log('error', error);
|
||||
@@ -268,6 +296,52 @@ async function phoneLoginSubmit() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取旋转验证码数据
|
||||
*/
|
||||
async function getRotateCaptcha() {
|
||||
const data: any = await getRotatedCaptchaData();
|
||||
if (data.code === 0 && data.data) {
|
||||
captchaData.image = data.data.image;
|
||||
captchaData.thumb = data.data.thumb;
|
||||
captchaData.key = data.data.key;
|
||||
} else {
|
||||
message.error(t('login.systemError'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证旋转验证码
|
||||
* @param angle
|
||||
*/
|
||||
async function checkCaptcha(angle: number) {
|
||||
if (captchaErrorCount.value >= 1) {
|
||||
message.error(t('login.captchaError'));
|
||||
getRotateCaptcha().then();
|
||||
captchaErrorCount.value = 0;
|
||||
} else {
|
||||
const result: any = await checkRotatedCaptcha(angle, captchaData.key);
|
||||
if (result.code === 0 && result.success) {
|
||||
message.success(t('login.captchaSuccess'));
|
||||
showRotateCaptcha.value = false;
|
||||
countDown();
|
||||
} else if (result.code === 1011) {
|
||||
message.error(t('login.captchaExpired'));
|
||||
getRotateCaptcha().then();
|
||||
captchaErrorCount.value = 0;
|
||||
} else {
|
||||
captchaErrorCount.value++;
|
||||
message.error(t('login.captchaError'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭旋转验证码
|
||||
*/
|
||||
async function closeRotateCaptcha() {
|
||||
showRotateCaptcha.value = false;
|
||||
}
|
||||
</script>
|
||||
<style src="./index.scss" scoped>
|
||||
@import "@/assets/styles/global.scss";
|
||||
|
@@ -84,4 +84,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
.gocaptcha-rotate {
|
||||
width: 330px;
|
||||
height: 350px;
|
||||
position: absolute;
|
||||
border-radius: 15px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.mask { /* 遮罩层的写法 */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@
|
||||
import {useI18n} from "vue-i18n";
|
||||
import BoxDog from "@/components/BoxDog/BoxDog.vue";
|
||||
import QRLoginFooter from "@/views/QRLogin/QRLoginFooter.vue";
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useRouter} from 'vue-router';
|
||||
|
||||
const {t} = useI18n();
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="test">
|
||||
<AButton @click="handleClick"> {{ t('login.test') }}</AButton>
|
||||
<AButton @click="changeLang('zh')"> 切换中文</AButton>
|
||||
<AButton @click="changeLang('en')"> 切换英文</AButton>
|
||||
@@ -32,5 +32,13 @@ async function changeLang(language: any) {
|
||||
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/styles/theme.scss";
|
||||
|
||||
.test {
|
||||
@include useTheme {
|
||||
background: getModeVar('primary');
|
||||
color: getColor('info');
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -17,6 +17,10 @@
|
||||
</AButtonGroup>
|
||||
<div class="test">test</div>
|
||||
</AConfigProvider>
|
||||
<AButton type="primary" @click="()=>{
|
||||
|
||||
}">获取验证码
|
||||
</AButton>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -25,10 +29,8 @@
|
||||
import variables from "@/assets/styles/colors.module.scss";
|
||||
import useStore from "@/store/index.ts";
|
||||
|
||||
|
||||
const app = useStore().theme;
|
||||
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "@/assets/styles/theme.scss";
|
||||
|
@@ -1854,6 +1854,13 @@ globby@^11.1.0:
|
||||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
|
||||
go-captcha-vue@^2:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/go-captcha-vue/-/go-captcha-vue-2.0.1.tgz#d9e3606e28648b7c9daeb7679aaf9b26592ca299"
|
||||
integrity sha512-nzFrn4qlk+bE1kHioCaOkdoMHkrzBZ0FzYcXgoGCQ9CSeDEYtMrey64T6wGz0JdEJwznElKc97jUGhbLavO5xQ==
|
||||
dependencies:
|
||||
vue "^3.0.1"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
@@ -3371,7 +3378,7 @@ vue-types@^3.0.0:
|
||||
dependencies:
|
||||
is-plain-object "3.0.1"
|
||||
|
||||
vue@^3.4.37:
|
||||
vue@^3.0.1, vue@^3.4.37:
|
||||
version "3.4.37"
|
||||
resolved "https://registry.npmmirror.com/vue/-/vue-3.4.37.tgz#64ce0eeb8de16a29fb74e504777ee8c0c1cf229e"
|
||||
integrity sha512-3vXvNfkKTBsSJ7JP+LyR7GBuwQuckbWvuwAid3xbqK9ppsKt/DUvfqgZ48fgOLEfpy1IacL5f8QhUVl77RaI7A==
|
||||
|
Reference in New Issue
Block a user