diff --git a/components.d.ts b/components.d.ts
index bbfb868..1ea6ec5 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -7,6 +7,7 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
+ CaptchaPanel: typeof import('./src/components/CaptchaPanel.vue')['default']
ElAside: typeof import('element-plus/es')['ElAside']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
diff --git a/src/components/CaptchaPanel.vue b/src/components/CaptchaPanel.vue
new file mode 100644
index 0000000..3831009
--- /dev/null
+++ b/src/components/CaptchaPanel.vue
@@ -0,0 +1,126 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/vendor/tianai-captcha/captcha/concat/concat.less b/src/vendor/tianai-captcha/captcha/concat/concat.less
index 6013fe6..796e8d6 100644
--- a/src/vendor/tianai-captcha/captcha/concat/concat.less
+++ b/src/vendor/tianai-captcha/captcha/concat/concat.less
@@ -3,7 +3,6 @@
background-size: 100% 180px;
position: absolute;
transform: translate(0px, 0px);
- /* border-bottom: 1px solid blue; */
z-index: 1;
width: 100%;
}
diff --git a/src/views/Login.vue b/src/views/Login.vue
index b92236f..69fa29a 100644
--- a/src/views/Login.vue
+++ b/src/views/Login.vue
@@ -53,7 +53,13 @@
@closed="handleCaptchaDialogClosed"
>
请先完成验证码校验,再继续登录。
-
+
@@ -63,13 +69,9 @@ import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import type { VForm } from '../types'
+import CaptchaPanel from '@/components/CaptchaPanel.vue'
import http from '@/utils/http'
-import {
- createTianAiCaptcha,
- type TianAiCaptchaConfig,
- type TianAiCaptchaInstance,
- type TianAiCaptchaResult
-} from '@/vendor/tianai-captcha'
+import type { TianAiCaptchaResult } from '@/vendor/tianai-captcha'
type LoginFormState = {
username: string | null,
@@ -87,13 +89,17 @@ type LoginConfigResponse = {
}
}
+type CaptchaPanelRef = {
+ destroy: () => void
+ init: () => Promise
+ reload: () => void
+}
+
const store = useStore()
const router = useRouter()
const loginForm = ref()
-const captchaBoxRef = ref(null)
+const captchaRef = ref(null)
const captchaDialogVisible = ref(false)
-const captchaInstance = ref(null)
-const requestCaptchaDataUrl = buildApiUrl('/captcha/gen')
const captchaErrorPattern = /验证码|captcha/i
const userInfo: LoginFormState = reactive({
@@ -119,7 +125,7 @@ localStorage.clear()
async function openCaptchaDialog() {
captchaDialogVisible.value = true
await nextTick()
- initCaptcha()
+ await captchaRef.value?.init()
}
async function handleLogin() {
@@ -148,31 +154,6 @@ async function handleLogin() {
})
}
-function initCaptcha() {
- if (!captchaBoxRef.value) {
- captchaDialogVisible.value = false
- ElMessage.error('验证码容器初始化失败')
- return
- }
-
- destroyCaptcha(false)
-
- const config: TianAiCaptchaConfig = {
- bindEl: captchaBoxRef.value,
- requestCaptchaDataUrl,
- onDataReady: handleCaptchaSolved,
- btnRefreshFun: (_el, tac) => {
- tac.reloadCaptcha()
- },
- btnCloseFun: () => {
- closeCaptchaDialog()
- }
- }
-
- captchaInstance.value = createTianAiCaptcha(config)
- captchaInstance.value.init()
-}
-
async function handleCaptchaSolved(result: TianAiCaptchaResult) {
if (loading.value) return
@@ -186,7 +167,7 @@ async function handleCaptchaSolved(result: TianAiCaptchaResult) {
})
} catch (error) {
if (isCaptchaError(error)) {
- captchaInstance.value?.reloadCaptcha()
+ captchaRef.value?.reload()
} else {
closeCaptchaDialog()
}
@@ -207,29 +188,19 @@ async function submitLogin(payload: LoginRequest) {
function closeCaptchaDialog(resetLoading = true) {
captchaDialogVisible.value = false
- destroyCaptcha(false)
+ captchaRef.value?.destroy()
if (resetLoading) {
loading.value = false
}
}
function handleCaptchaDialogClosed() {
- destroyCaptcha(false)
+ captchaRef.value?.destroy()
}
-function destroyCaptcha(showMessage = false) {
- if (!captchaInstance.value) return
- captchaInstance.value.destroyWindow()
- captchaInstance.value = null
- if (showMessage) {
- console.info('[login captcha] destroy captcha instance')
- }
-}
-
-function buildApiUrl(path: string) {
- const normalizedBase = (import.meta.env.VITE_APP_API_BASE || '').replace(/\/+$/, '')
- const normalizedPath = path.startsWith('/') ? path : `/${path}`
- return `${normalizedBase}${normalizedPath}`
+function handleCaptchaInitError() {
+ captchaDialogVisible.value = false
+ ElMessage.error('验证码初始化失败')
}
function isCaptchaError(error: unknown) {
@@ -239,7 +210,7 @@ function isCaptchaError(error: unknown) {
return false
}
-onBeforeUnmount(() => destroyCaptcha())
+onBeforeUnmount(() => captchaRef.value?.destroy())