From 3874df18d43a612f61f62f6bd9d8e6021a65c992 Mon Sep 17 00:00:00 2001 From: Baobhan Sith <80159437+Heavrnl@users.noreply.github.com> Date: Sat, 26 Apr 2025 00:09:31 +0800 Subject: [PATCH] update --- package-lock.json | 113 ++-------------------- packages/frontend/package.json | 2 +- packages/frontend/src/main.ts | 12 +-- packages/frontend/src/views/LoginView.vue | 61 +++++------- 4 files changed, 35 insertions(+), 153 deletions(-) diff --git a/package-lock.json b/package-lock.json index ef8ba4a..f6d7801 100644 --- a/package-lock.json +++ b/package-lock.json @@ -745,21 +745,6 @@ "node": ">=18.12.0" } }, - "node_modules/@nuxt/schema": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-3.16.2.tgz", - "integrity": "sha512-2HZPM372kuI/uw9VU/hOoYuzv803oZAtyoEKC5dQCQTKAQ293AjypF3WljMXUSReFS/hcbBSgGzYUPHr3Qo+pg==", - "license": "MIT", - "dependencies": { - "consola": "^3.4.2", - "defu": "^6.1.4", - "pathe": "^2.0.3", - "std-env": "^3.8.1" - }, - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, "node_modules/@peculiar/asn1-android": { "version": "2.3.16", "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.3.16.tgz", @@ -1931,18 +1916,6 @@ "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", "license": "MIT" }, - "node_modules/@vueuse/shared": { - "version": "10.11.1", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.1.tgz", - "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", - "license": "MIT", - "dependencies": { - "vue-demi": ">=0.14.8" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -5113,18 +5086,6 @@ "wrappy": "1" } }, - "node_modules/p-defer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", - "integrity": "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -6685,18 +6646,6 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "license": "Unlicense" }, - "node_modules/type-fest": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", - "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", @@ -7082,32 +7031,6 @@ } } }, - "node_modules/vue-demi": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", - "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "vue-demi-fix": "bin/vue-demi-fix.js", - "vue-demi-switch": "bin/vue-demi-switch.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "@vue/composition-api": "^1.0.0-rc.1", - "vue": "^3.0.0-0 || ^2.6.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, "node_modules/vue-i18n": { "version": "9.14.4", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.4.tgz", @@ -7134,34 +7057,6 @@ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, - "node_modules/vue-recaptcha": { - "version": "3.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/vue-recaptcha/-/vue-recaptcha-3.0.0-alpha.6.tgz", - "integrity": "sha512-hwxxAXENLN6GKJhH6s+NJV1f6llSFEQ0jMTxjEunpR6CMbQ5xc7DAHFtwrsDutGnbS8wl9yp30jsYcCToZEhTQ==", - "license": "MIT", - "workspaces": [ - ".", - "docs" - ], - "dependencies": { - "@nuxt/kit": "^3.4.3", - "@nuxt/schema": "^3.4.3", - "@vueuse/shared": "^10.1.0", - "defu": "^6.1.2", - "p-defer": "^4.0.0", - "std-env": "^3.3.2", - "type-fest": "^3.9.0", - "vue-demi": "^0.14.0" - }, - "peerDependencies": { - "vue": "^3.0.0" - }, - "peerDependenciesMeta": { - "@vue/composition-api": { - "optional": true - } - } - }, "node_modules/vue-recaptcha-v3": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/vue-recaptcha-v3/-/vue-recaptcha-v3-2.0.1.tgz", @@ -7212,6 +7107,12 @@ "typescript": ">=5.0.0" } }, + "node_modules/vue3-recaptcha2": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/vue3-recaptcha2/-/vue3-recaptcha2-1.8.0.tgz", + "integrity": "sha512-lICGpLGv9wsdVjgWZ0usbZ+Ki52YX5kOzjt8l/ADun9GxdjJ5/AkGpxE7dZ+mG3VcE4ASZG2B/nYWB4wWFadvQ==", + "license": "ISC" + }, "node_modules/vuedraggable": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", @@ -7494,9 +7395,9 @@ "vite-plugin-monaco-editor": "^1.1.0", "vue": "^3.3.0", "vue-i18n": "^9.14.4", - "vue-recaptcha": "^3.0.0-alpha.6", "vue-recaptcha-v3": "^2.0.1", "vue-router": "^4.5.0", + "vue3-recaptcha2": "^1.8.0", "vuedraggable": "^4.1.0", "xterm": "^5.3.0", "xterm-addon-fit": "^0.8.0", diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 658282a..fc4af01 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -23,9 +23,9 @@ "vite-plugin-monaco-editor": "^1.1.0", "vue": "^3.3.0", "vue-i18n": "^9.14.4", - "vue-recaptcha": "^3.0.0-alpha.6", "vue-recaptcha-v3": "^2.0.1", "vue-router": "^4.5.0", + "vue3-recaptcha2": "^1.8.0", "vuedraggable": "^4.1.0", "xterm": "^5.3.0", "xterm-addon-fit": "^0.8.0", diff --git a/packages/frontend/src/main.ts b/packages/frontend/src/main.ts index dc266b9..ffe834a 100644 --- a/packages/frontend/src/main.ts +++ b/packages/frontend/src/main.ts @@ -12,8 +12,7 @@ import './style.css'; import '@fortawesome/fontawesome-free/css/all.min.css'; // 导入 splitpanes CSS import 'splitpanes/dist/splitpanes.css'; -// 恢复导入 reCAPTCHA v3 -import { VueReCaptcha } from 'vue-recaptcha-v3'; + const pinia = createPinia(); // 创建 Pinia 实例 pinia.use(piniaPluginPersistedstate); // 使用持久化插件 @@ -24,14 +23,7 @@ app.use(pinia); // 使用配置好的 Pinia 实例 // 注意:在状态初始化完成前,暂时不 use(router) app.use(i18n); // 使用 i18n -// 恢复初始化 reCAPTCHA v3 -// 重要提示:请将 'YOUR_RECAPTCHA_V3_SITE_KEY' 替换为您从 Google reCAPTCHA 获取的实际 Site Key -app.use(VueReCaptcha, { - siteKey: 'YOUR_RECAPTCHA_V3_SITE_KEY', // <-- 在此处替换您的 Site Key - loaderOptions: { - autoHideBadge: true // 可选:自动隐藏 reCAPTCHA 徽章 - } -}); + // --- 应用初始化逻辑 --- // 使用 async IIFE 来允许顶层 await diff --git a/packages/frontend/src/views/LoginView.vue b/packages/frontend/src/views/LoginView.vue index a3fd31b..b4051a4 100644 --- a/packages/frontend/src/views/LoginView.vue +++ b/packages/frontend/src/views/LoginView.vue @@ -3,8 +3,8 @@ import { reactive, ref, onMounted, computed } from 'vue'; // computed 已导入 import { storeToRefs } from 'pinia'; import { useI18n } from 'vue-i18n'; import { useAuthStore } from '../stores/auth.store'; -import VueHcaptcha from '@hcaptcha/vue3-hcaptcha'; // <-- Import hCaptcha component -import { useReCaptcha } from 'vue-recaptcha-v3'; // <-- Restore reCAPTCHA v3 hook +import VueHcaptcha from '@hcaptcha/vue3-hcaptcha'; +import VueRecaptcha from 'vue3-recaptcha2'; // 使用默认导入 const { t } = useI18n(); const authStore = useAuthStore(); @@ -21,9 +21,10 @@ const rememberMe = ref(false); // 新增:记住我状态,默认为 false const captchaToken = ref(null); // NEW: Store CAPTCHA token const captchaError = ref(null); // NEW: Store CAPTCHA specific error const hcaptchaWidget = ref | null>(null); // NEW: Ref for hCaptcha component instance +const recaptchaWidget = ref | null>(null); // 更新 Ref 类型以匹配新导入 // --- reCAPTCHA v3 Initialization --- -const recaptchaInstance = useReCaptcha(); // Restore v3 instance +// const recaptchaInstance = useReCaptcha(); // 移除 v3 实例,因为我们将使用 v2 组件 // --- CAPTCHA Event Handlers --- @@ -46,7 +47,8 @@ const resetCaptchaWidget = () => { captchaToken.value = null; // Reset hCaptcha if it exists hcaptchaWidget.value?.reset(); - // reCAPTCHA v3 doesn't typically need explicit reset in the same way + // Reset reCAPTCHA v2 if it exists + recaptchaWidget.value?.reset(); }; // --- End CAPTCHA Event Handlers --- @@ -56,36 +58,16 @@ const handleSubmit = async () => { captchaError.value = null; // Clear previous CAPTCHA error // --- CAPTCHA Execution & Check --- + // --- CAPTCHA Check (v2/hCaptcha) --- if (publicCaptchaConfig.value?.enabled && !loginRequires2FA.value) { - // Restore If reCAPTCHA v3, execute it now to get the token - if (publicCaptchaConfig.value.provider === 'recaptcha') { - // Check if instance and methods are available - if (recaptchaInstance?.recaptchaLoaded && recaptchaInstance?.executeRecaptcha) { - try { - await recaptchaInstance.recaptchaLoaded(); // Ensure library is loaded - const token = await recaptchaInstance.executeRecaptcha('login'); // Execute with action 'login' - console.log('reCAPTCHA v3 token obtained:', token); - captchaToken.value = token; // Store the obtained token - } catch (reError: any) { - console.error('reCAPTCHA v3 execution failed:', reError); - captchaError.value = t('login.error.captchaLoadFailed'); - return; // Stop submission if reCAPTCHA execution fails - } - } else { - // Handle case where reCAPTCHA is not ready/initialized - console.error('reCAPTCHA v3 not initialized or ready.'); - captchaError.value = t('login.error.captchaLoadFailed'); // Or a more specific error - return; - } - } - - // Check if token exists (for both hCaptcha and reCAPTCHA) + // Check if token exists (obtained via component event for v2/hCaptcha) if (!captchaToken.value) { captchaError.value = t('login.error.captchaRequired'); - return; // Stop submission if CAPTCHA is required but not completed/obtained + return; // Stop submission if CAPTCHA is required but not completed } } // --- End CAPTCHA Check --- + // --- End CAPTCHA Check --- try { if (loginRequires2FA.value) { @@ -169,8 +151,8 @@ onMounted(() => {
- - + +
{ theme="auto" >
- -
-

- {{ t('login.recaptchaV3Notice') }} -

- + +
+ + + +