google-login.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <view class="btns_item" @click="handleGoogleLogin">
  3. <view class="btn_icon">
  4. <image src="@/static/login/google.png" class="img" mode="widthFix"></image>
  5. </view>
  6. <trans _t="使用谷歌登录" />
  7. </view>
  8. </template>
  9. <script setup>
  10. import { ref, onMounted } from 'vue'
  11. import { systemInfo, Toast } from "@/utils"
  12. const emit = defineEmits(['success', 'error'])
  13. const platform = ref(systemInfo().uniPlatform)
  14. const isLoggingIn = ref(false)
  15. const isGoogleApiLoaded = ref(false)
  16. // #ifdef H5
  17. // 初始化Google登录
  18. const initGoogleAuth = async () => {
  19. if (isGoogleApiLoaded.value) return
  20. return new Promise((resolve) => {
  21. if (window.google && window.google.accounts) {
  22. initWebGoogleAuth()
  23. isGoogleApiLoaded.value = true
  24. return resolve()
  25. }
  26. const script = document.createElement('script')
  27. script.src = 'https://accounts.google.com/gsi/client'
  28. script.async = true
  29. script.defer = true
  30. script.onload = () => {
  31. initWebGoogleAuth()
  32. isGoogleApiLoaded.value = true
  33. resolve()
  34. }
  35. document.head.appendChild(script)
  36. })
  37. }
  38. const initWebGoogleAuth = () => {
  39. window.google.accounts.id.initialize({
  40. client_id: '132211687127-bo929nasc04jk3927j07facbgovfv9vj.apps.googleusercontent.com',
  41. callback: handleCredentialResponse
  42. })
  43. }
  44. const handleCredentialResponse = (response) => {
  45. emit('success', response)
  46. }
  47. const googleLoginInH5 = () => {
  48. if (!window.google || !window.google.accounts) {
  49. return initGoogleAuth().then(googleLoginInH5)
  50. }
  51. window.google.accounts.id.prompt((notification) => {
  52. if (notification.isNotDisplayed() || notification.isSkippedMoment()) {
  53. emit('error', new Error('Google登录弹出框被阻止'))
  54. }
  55. })
  56. }
  57. // #endif
  58. // #ifdef APP-PLUS
  59. const googleLoginInApp = () => {
  60. return new Promise((resolve, reject) => {
  61. uni.login({
  62. provider: 'google',
  63. success: (loginRes) => {
  64. uni.getUserInfo({
  65. provider: 'google',
  66. success: (info) => {
  67. Toast(info.authResult)
  68. emit('success', info.authResult)
  69. resolve(info)
  70. },
  71. fail: (err) => {
  72. console.error('获取用户信息失败:', err)
  73. emit('error', err)
  74. reject(err)
  75. }
  76. })
  77. },
  78. fail: (err) => {
  79. console.error('登录失败:', err)
  80. emit('error', err)
  81. reject(err)
  82. }
  83. })
  84. })
  85. }
  86. // #endif
  87. // 统一登录处理
  88. const handleGoogleLogin = async () => {
  89. if (isLoggingIn.value) return
  90. try {
  91. isLoggingIn.value = true
  92. // #ifdef H5
  93. if (!window.google || !window.google.accounts) {
  94. await initGoogleAuth()
  95. }
  96. // #endif
  97. if (platform.value === 'app') {
  98. await googleLoginInApp()
  99. } else if (platform.value === 'web') {
  100. await googleLoginInH5()
  101. } else {
  102. emit('error', new Error('不支持的平台'))
  103. }
  104. } catch (error) {
  105. emit('error', error)
  106. } finally {
  107. isLoggingIn.value = false
  108. }
  109. }
  110. onMounted(() => {
  111. // #ifdef H5
  112. initGoogleAuth().catch(err => {
  113. console.error('Google API 初始化失败:', err)
  114. })
  115. // #endif
  116. })
  117. </script>
  118. <style lang="less" scoped>
  119. @import url('@/style.less');
  120. .btns_item {
  121. .ver();
  122. width: 400rpx;
  123. border: 1px solid var(--black);
  124. border-radius: 100px;
  125. padding: 14rpx 52rpx;
  126. margin-top: 18rpx;
  127. color: var(--text-02);
  128. .size(24rpx);
  129. .btn_icon {
  130. width: 48rpx;
  131. margin-right: 52rpx;
  132. .img {
  133. width: inherit;
  134. display: block;
  135. }
  136. }
  137. }
  138. </style>