Commit 2dc5a72e authored by tyyin lan's avatar tyyin lan

feat: 谷歌登录

parent 69ef3c03
...@@ -26,6 +26,7 @@ export default [ ...@@ -26,6 +26,7 @@ export default [
ConversationMessageItemInfo: 'readonly', ConversationMessageItemInfo: 'readonly',
MittEvents: 'readonly', MittEvents: 'readonly',
I18n: 'readonly', I18n: 'readonly',
google: 'readonly',
}, },
parser: vueParser, parser: vueParser,
parserOptions: { parserOptions: {
......
import { request } from '@/utils/request' import { request } from '@/utils/request'
export function fetchLogin<T>(payload: { export function fetchLogin<T>(payload: {
loginChannel: 'MEMBER_PLATFOMR_SMS' | 'MEMBER_PLATFOMR_EMAIL' | 'MEMBER_PLATFOMR_PW' loginChannel: 'MEMBER_PLATFOMR_SMS' | 'MEMBER_PLATFOMR_EMAIL' | 'MEMBER_PLATFOMR_PW' | 'MEMBER_PLATFOMR_GOOGLE'
account: string account: string
password?: string password?: string
authCode?: string authCode?: string
...@@ -38,3 +38,7 @@ export function fetchUserPasswordUpdate<T>(authCode: string, password: string) { ...@@ -38,3 +38,7 @@ export function fetchUserPasswordUpdate<T>(authCode: string, password: string) {
params: { authCode, password }, params: { authCode, password },
}) })
} }
export function fetchGoogleClientId<T>() {
return request.post<T>('/googleConfigRest/getClientId.json')
}
...@@ -134,6 +134,7 @@ common_module: ...@@ -134,6 +134,7 @@ common_module:
export_successfully: 'Export successfully' export_successfully: 'Export successfully'
export_failed: 'Export failed' export_failed: 'Export failed'
copy_link: 'Copy link' copy_link: 'Copy link'
or: 'or'
dialogue_module: dialogue_module:
continue_question_message: 'You can keep asking questions' continue_question_message: 'You can keep asking questions'
......
...@@ -133,6 +133,7 @@ common_module: ...@@ -133,6 +133,7 @@ common_module:
export_successfully: '导出成功' export_successfully: '导出成功'
export_failed: '导出失败' export_failed: '导出失败'
copy_link: '复制链接' copy_link: '复制链接'
or: '或'
dialogue_module: dialogue_module:
continue_question_message: '你可以继续提问' continue_question_message: '你可以继续提问'
......
...@@ -133,6 +133,7 @@ common_module: ...@@ -133,6 +133,7 @@ common_module:
export_successfully: '導出成功' export_successfully: '導出成功'
export_failed: '導出失敗' export_failed: '導出失敗'
copy_link: '複製鏈接' copy_link: '複製鏈接'
or: '或'
dialogue_module: dialogue_module:
continue_question_message: '你可以繼續提問' continue_question_message: '你可以繼續提問'
......
...@@ -53,6 +53,10 @@ export const useUserStore = defineStore('user-store', { ...@@ -53,6 +53,10 @@ export const useUserStore = defineStore('user-store', {
this.token = '' this.token = ''
this.userInfo = createDefaultUserInfoFactory() this.userInfo = createDefaultUserInfoFactory()
if (window.google) {
window.google.accounts.id.disableAutoSelect()
}
ss.remove(UserStoreStorageKeyEnum.isLogin) ss.remove(UserStoreStorageKeyEnum.isLogin)
ss.remove(UserStoreStorageKeyEnum.token) ss.remove(UserStoreStorageKeyEnum.token)
ss.remove(UserStoreStorageKeyEnum.userInfo) ss.remove(UserStoreStorageKeyEnum.userInfo)
......
...@@ -5,27 +5,29 @@ import { Mail, Lock, Iphone, Down, User } from '@icon-park/vue-next' ...@@ -5,27 +5,29 @@ import { Mail, Lock, Iphone, Down, User } from '@icon-park/vue-next'
import isMobilePhone from 'validator/es/lib/isMobilePhone' import isMobilePhone from 'validator/es/lib/isMobilePhone'
import isEmail from 'validator/es/lib/isEmail' import isEmail from 'validator/es/lib/isEmail'
import { ss } from '@/utils/storage' import { ss } from '@/utils/storage'
import { fetchEmailCode, fetchLogin, fetchSMSCode } from '@/apis/user' import { fetchEmailCode, fetchLogin, fetchSMSCode, fetchGoogleClientId } from '@/apis/user'
import SparkMD5 from 'spark-md5' import SparkMD5 from 'spark-md5'
import { useUserStore } from '@/store/modules/user' import { useUserStore } from '@/store/modules/user'
import type { UserInfo } from '@/store/types/user' import type { UserInfo } from '@/store/types/user'
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import LanguageSetting from '@/components/language-setting/language-setting.vue' import LanguageSetting from '@/components/language-setting/language-setting.vue'
import { useSystemLanguageStore } from '@/store/modules/system-language'
enum StorageKeyEnum { enum StorageKeyEnum {
smsCountdownTime = 'SMS_COUNTDOWN_TIME', smsCountdownTime = 'SMS_COUNTDOWN_TIME',
emailCountdownTime = 'MAIL_COUNTDOWN_TIME', emailCountdownTime = 'MAIL_COUNTDOWN_TIME',
} }
type LoginMethod = 'password' | 'sms' | 'email' type LoginMethod = 'password' | 'sms' | 'email' | 'google'
interface LoginPayload { interface LoginPayload {
loginChannel: 'MEMBER_PLATFOMR_SMS' | 'MEMBER_PLATFOMR_EMAIL' | 'MEMBER_PLATFOMR_PW' loginChannel: 'MEMBER_PLATFOMR_SMS' | 'MEMBER_PLATFOMR_EMAIL' | 'MEMBER_PLATFOMR_PW' | 'MEMBER_PLATFOMR_GOOGLE'
account: string account: string
password?: string password?: string
authCode?: string authCode?: string
} }
const userStore = useUserStore() const userStore = useUserStore()
const systemLanguageStore = useSystemLanguageStore()
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const { t } = useI18n() const { t } = useI18n()
...@@ -34,6 +36,7 @@ const passwordLoginFormRef = useTemplateRef<FormInst>('passwordLoginFormRef') ...@@ -34,6 +36,7 @@ const passwordLoginFormRef = useTemplateRef<FormInst>('passwordLoginFormRef')
const smsLoginFormRef = useTemplateRef<FormInst>('smsLoginFormRef') const smsLoginFormRef = useTemplateRef<FormInst>('smsLoginFormRef')
const emailLoginFormRef = useTemplateRef<FormInst>('emailLoginFormRef') const emailLoginFormRef = useTemplateRef<FormInst>('emailLoginFormRef')
const countdownRef = useTemplateRef<CountdownInst>('countdownRef') const countdownRef = useTemplateRef<CountdownInst>('countdownRef')
const googleLoginBtnRef = useTemplateRef<HTMLDivElement>('googleLoginBtnRef')
const currentLoginMethod = ref<LoginMethod>('sms') const currentLoginMethod = ref<LoginMethod>('sms')
const showCardReserveAnimation = ref(false) const showCardReserveAnimation = ref(false)
...@@ -52,6 +55,9 @@ const emailLoginForm = ref({ ...@@ -52,6 +55,9 @@ const emailLoginForm = ref({
email: '', email: '',
code: '', code: '',
}) })
const googleLoginForm = ref({
credential: '',
})
const passwordLoginFormRules = shallowReadonly<FormRules>({ const passwordLoginFormRules = shallowReadonly<FormRules>({
account: { required: true, message: t('login_module.please_enter_your_account_number'), trigger: 'blur' }, account: { required: true, message: t('login_module.please_enter_your_account_number'), trigger: 'blur' },
...@@ -90,6 +96,12 @@ const emailLoginFormRules = shallowReadonly<FormRules>({ ...@@ -90,6 +96,12 @@ const emailLoginFormRules = shallowReadonly<FormRules>({
code: { required: true, message: t('login_module.please_enter_the_verification_code') }, code: { required: true, message: t('login_module.please_enter_the_verification_code') },
}) })
const currentPhoneNumberArea = ref<'+86' | '+852'>('+852')
const countdownActive = ref(true)
const isShowCountdown = ref(false)
const countdownDuration = ref<number>(60000)
const phoneNumberAreaOptions = computed(() => { const phoneNumberAreaOptions = computed(() => {
return [ return [
{ {
...@@ -102,11 +114,6 @@ const phoneNumberAreaOptions = computed(() => { ...@@ -102,11 +114,6 @@ const phoneNumberAreaOptions = computed(() => {
}, },
] ]
}) })
const currentPhoneNumberArea = ref<'+86' | '+852'>('+852')
const countdownActive = ref(true)
const isShowCountdown = ref(false)
const countdownDuration = ref<number>(60000)
watchEffect(() => { watchEffect(() => {
let timeStringDraft = '' let timeStringDraft = ''
...@@ -135,6 +142,21 @@ watchEffect(() => { ...@@ -135,6 +142,21 @@ watchEffect(() => {
} }
}) })
/* created */
;(function () {
if (!window.google) {
const script = document.createElement('script')
script.src = `https://accounts.google.com/gsi/client?hl=${systemLanguageStore.currentLanguage}` // 加载客户端库
script.async = true
script.onload = () => {
getGoogleLoginClientId().then((clientId) => {
clientId && initializeGoogleSignIn(clientId)
})
}
document.head.appendChild(script)
}
})()
function onlyAllowNumber(value: string) { function onlyAllowNumber(value: string) {
return !value || /^\d+$/.test(value) return !value || /^\d+$/.test(value)
} }
...@@ -218,6 +240,17 @@ function handleLoginSubmit(method: LoginMethod) { ...@@ -218,6 +240,17 @@ function handleLoginSubmit(method: LoginMethod) {
}) })
} }
break break
case 'google':
{
payload = {
loginChannel: 'MEMBER_PLATFOMR_GOOGLE',
account: '',
authCode: googleLoginForm.value.credential,
}
resolve(true)
}
break
} }
}).then(() => { }).then(() => {
loginBtnLoading.value = true loginBtnLoading.value = true
...@@ -301,6 +334,41 @@ function handleEmailCodeGain() { ...@@ -301,6 +334,41 @@ function handleEmailCodeGain() {
}, },
) )
} }
function initializeGoogleSignIn(clientId: string) {
window.google.accounts.id.initialize({
client_id: encodeURIComponent(clientId),
auto_select: false,
callback: (res: { credential: string; clientId: string }) => {
googleLoginForm.value.credential = res.credential
handleLoginSubmit('google')
},
})
if (googleLoginBtnRef.value) {
window.google.accounts.id.renderButton(googleLoginBtnRef.value, {
size: 'medium',
text: 'signin_with',
logo_alignment: 'left',
locale: systemLanguageStore.currentLanguage,
})
}
// window.google.accounts.id.prompt((notification: any) => {
// if (notification.isNotDisplayed() || notification.isSkippedMoment()) {
// console.log('💥💥💥💥💥💥登录失败💥💥💥💥💥💥')
// }
// })
}
function getGoogleLoginClientId() {
return fetchGoogleClientId<string>().then((res) => {
if (res.code !== 0) return ''
return res.data
})
}
</script> </script>
<template> <template>
...@@ -313,7 +381,7 @@ function handleEmailCodeGain() { ...@@ -313,7 +381,7 @@ function handleEmailCodeGain() {
<LanguageSetting arrow-direction="bottom" btn-bg-color="#f4f5f5" /> <LanguageSetting arrow-direction="bottom" btn-bg-color="#f4f5f5" />
</div> </div>
<div class="absolute right-[14%] top-1/2 h-[458px] w-[390px] -translate-y-1/2"> <div class="absolute right-[14%] top-1/2 w-[390px] -translate-y-1/2">
<div <div
class="h-full w-full rounded-[10px] bg-[#fff] px-[29px] shadow-2xl" class="h-full w-full rounded-[10px] bg-[#fff] px-[29px] shadow-2xl"
:class="{ 'animate-card-reverse': showCardReserveAnimation }" :class="{ 'animate-card-reverse': showCardReserveAnimation }"
...@@ -532,8 +600,8 @@ function handleEmailCodeGain() { ...@@ -532,8 +600,8 @@ function handleEmailCodeGain() {
</n-form> </n-form>
</div> </div>
<div class="absolute bottom-[22px] left-0 w-full"> <div class="w-full pb-[34px]">
<div class="mb-[32px]"> <div class="h-[134px]">
<div class="mb-[12px] text-center text-[12px] text-[#999999]"> <div class="mb-[12px] text-center text-[12px] text-[#999999]">
{{ t('login_module.other_login_methods') }} {{ t('login_module.other_login_methods') }}
</div> </div>
...@@ -562,6 +630,12 @@ function handleEmailCodeGain() { ...@@ -562,6 +630,12 @@ function handleEmailCodeGain() {
<Lock theme="outline" size="17" fill="#666666" :stroke-width="3" /> <Lock theme="outline" size="17" fill="#666666" :stroke-width="3" />
</button> </button>
</div> </div>
<div class="py-[10px] text-center text-[12px] text-[#999999]">{{ t('common_module.or') }}</div>
<div class="flex-center flex">
<div ref="googleLoginBtnRef"></div>
</div>
</div> </div>
<!-- <div class="text-center"> <!-- <div class="text-center">
......
...@@ -6,6 +6,8 @@ declare interface Window { ...@@ -6,6 +6,8 @@ declare interface Window {
ctWarning: (message: string, title?: string, cancelText?: string, confirmText?: string) => Promise<boolean | Error> ctWarning: (message: string, title?: string, cancelText?: string, confirmText?: string) => Promise<boolean | Error>
} }
$notification: import('naive-ui').NotificationProviderInst $notification: import('naive-ui').NotificationProviderInst
google: any
} }
declare namespace JSX { declare namespace JSX {
......
...@@ -133,6 +133,7 @@ declare namespace I18n { ...@@ -133,6 +133,7 @@ declare namespace I18n {
export_successfully: string export_successfully: string
export_failed: string export_failed: string
copy_link: string copy_link: string
or: string
dialogue_module: { dialogue_module: {
continue_question_message: string continue_question_message: string
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment