![]()
@@ -29,8 +29,10 @@ const emit = defineEmits<{
function decodeJWT(token: string) {
const base64Url = token.split('.')[1]
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
+ // 使用类型断言来避免 deprecated 警告,atob 在浏览器环境中仍然是最佳实践
+ const decoded = (atob as (data: string) => string)(base64)
const jsonPayload = decodeURIComponent(
- atob(base64)
+ decoded
.split('')
.map(function (c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
@@ -55,7 +57,8 @@ const handleCredentialResponse = async (response: { credential: string }) => {
const code = response.credential
emit('googelLogin', code)
- window.isAddGmail = false
+ // 移除这行,保持按钮可以重复使用
+ // window.isAddGmail = false
}
// 配置数据
@@ -70,38 +73,133 @@ console.log(import.meta.env.VITE_USER_NODE_ENV)
// 根据环境设置 Google Client ID
const GOOGLE_CLIENT_ID = '216037134725-7q8vqp0ohtmohlosltkfg7bd2v29rm5a.apps.googleusercontent.com'
-// 创建 Gmail 登录
-const createGmailLogin = async () => {
- const existingScript = document.querySelector(`script[src="${data.scriptSrc}"]`)
- if (!window.isAddGmail) {
- if (!existingScript) {
- window.isAddGmail = true
- await new Promise
((resolve) => {
- const script = document.createElement('script')
- script.onload = () => {
- resolve()
- }
- document.body.appendChild(script)
- script.src = data.scriptSrc
- })
+// 等待 Google API 可用
+const waitForGoogle = (): Promise => {
+ return new Promise((resolve) => {
+ const google = window.google as any
+ if (google?.accounts?.id) {
+ resolve()
+ return
}
- window.google.accounts.id.initialize({
- // 主要就是填写client_id
- client_id: GOOGLE_CLIENT_ID,
- auto_select: false,
- callback: handleCredentialResponse,
- // context:"signin",
- ux_mode: 'popup',
- itp_support: true
+ const checkInterval = setInterval(() => {
+ if (google?.accounts?.id) {
+ clearInterval(checkInterval)
+ resolve()
+ }
+ }, 50)
+ // 10秒超时
+ setTimeout(() => {
+ clearInterval(checkInterval)
+ resolve()
+ }, 10000)
+ })
+}
+
+// 初始化 Google API(确保脚本加载和 API 可用)
+const initializeGoogleAPI = async () => {
+ const existingScript = document.querySelector(`script[src="${data.scriptSrc}"]`)
+ if (!existingScript) {
+ window.isAddGmail = true
+ await new Promise((resolve) => {
+ const script = document.createElement('script')
+ script.onload = () => {
+ resolve()
+ }
+ script.onerror = () => {
+ console.error('Failed to load Google script')
+ resolve() // 仍然 resolve,让后续代码处理
+ }
+ document.body.appendChild(script)
+ script.src = data.scriptSrc
})
- console.log(document.querySelector('.Container #g_id_signin'))
- window.google.accounts.id.renderButton(document.querySelector('.Container #g_id_signin'), {
- type: 'standard', //icon为只有一个icon
+ }
+
+ // 等待 Google API 完全加载
+ await waitForGoogle()
+
+ const google = window.google as any
+ if (!google?.accounts?.id) {
+ console.error('Google API not available')
+ return false
+ }
+
+ return true
+}
+
+// 重新初始化 Google Sign-In(每次调用时都重新初始化,确保状态正确)
+const reinitializeGoogleSignIn = () => {
+ const google = window.google as any
+ if (!google?.accounts?.id) {
+ return false
+ }
+
+ // 每次重新初始化,确保状态正确
+ google.accounts.id.initialize({
+ client_id: GOOGLE_CLIENT_ID,
+ auto_select: false,
+ callback: handleCredentialResponse,
+ ux_mode: 'popup',
+ itp_support: true
+ })
+
+ return true
+}
+
+// 创建 Gmail 登录按钮
+const createGmailLogin = async () => {
+ const isReady = await initializeGoogleAPI()
+ if (!isReady) {
+ return
+ }
+
+ // 重新初始化确保状态正确
+ reinitializeGoogleSignIn()
+
+ // 等待一小段时间确保初始化完成
+ await new Promise(resolve => setTimeout(resolve, 100))
+
+ const google = window.google as any
+ // 然后渲染按钮
+ const buttonElement = document.querySelector('.Container #g_id_signin')
+ if (buttonElement) {
+ // 清除之前的内容,重新渲染
+ buttonElement.innerHTML = ''
+ google.accounts.id.renderButton(buttonElement, {
+ type: 'standard',
shape: 'circle',
theme: 'outline',
size: 'large',
logo_alignment: 'center'
})
+ } else {
+ console.error('Button element not found')
+ }
+}
+
+// 手动触发 Google 登录(用于处理弹窗关闭后无法再次触发的问题)
+const triggerGoogleLogin = async () => {
+ const isReady = await initializeGoogleAPI()
+ if (!isReady) {
+ return
+ }
+
+ // 重新初始化确保状态正确
+ reinitializeGoogleSignIn()
+
+ const google = window.google as any
+ // 使用 prompt() 方法手动触发登录
+ try {
+ google.accounts.id.prompt((notification: any) => {
+ // 处理通知(例如用户关闭了弹窗)
+ if (notification.isNotDisplayed() || notification.isSkippedMoment()) {
+ // 如果提示没有显示或被跳过,可以尝试使用按钮
+ console.log('Prompt not displayed, trying button click')
+ }
+ })
+ } catch (error) {
+ console.error('Error triggering Google login:', error)
+ // 如果 prompt() 失败,尝试重新渲染按钮
+ await createGmailLogin()
}
}
@@ -109,6 +207,29 @@ const toGmailLogin = () => {
showToast('Google login is not available yet')
}
+// 处理容器点击事件(确保每次点击都能触发登录)
+let isProcessingClick = false
+const handleContainerClick = async () => {
+ // 防止重复点击
+ if (isProcessingClick) {
+ return
+ }
+
+ isProcessingClick = true
+
+ // 确保 API 已加载
+ const isReady = await initializeGoogleAPI()
+ if (isReady) {
+ // 重新初始化 API,确保状态正确(不重新渲染按钮)
+ reinitializeGoogleSignIn()
+ }
+
+ // 短暂延迟后重置标志,允许下次点击
+ setTimeout(() => {
+ isProcessingClick = false
+ }, 200)
+}
+
onBeforeUnmount(() => {
const existingScript = document.querySelector(`script[src="${data.scriptSrc}"]`)
if (existingScript) {