Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/lanecarford_front
This commit is contained in:
34
env.d.ts
vendored
34
env.d.ts
vendored
@@ -1 +1,35 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
// Google Identity Services 类型声明
|
||||||
|
interface GoogleAccounts {
|
||||||
|
accounts: {
|
||||||
|
id: {
|
||||||
|
initialize: (config: {
|
||||||
|
client_id: string
|
||||||
|
auto_select?: boolean
|
||||||
|
callback: (response: { credential: string }) => void
|
||||||
|
ux_mode?: 'popup' | 'redirect'
|
||||||
|
itp_support?: boolean
|
||||||
|
}) => void
|
||||||
|
renderButton: (element: Element | null, config: {
|
||||||
|
type?: 'standard' | 'icon'
|
||||||
|
shape?: 'rectangular' | 'pill' | 'circle' | 'square'
|
||||||
|
theme?: 'outline' | 'filled_blue' | 'filled_black'
|
||||||
|
size?: 'large' | 'medium' | 'small'
|
||||||
|
logo_alignment?: 'left' | 'center'
|
||||||
|
}) => void
|
||||||
|
}
|
||||||
|
oauth2: {
|
||||||
|
initTokenClient: (config: {
|
||||||
|
client_id: string
|
||||||
|
callback: (response: { access_token: string }) => void
|
||||||
|
scope?: string
|
||||||
|
}) => void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Window {
|
||||||
|
google?: GoogleAccounts
|
||||||
|
isAddGmail?: boolean
|
||||||
|
}
|
||||||
@@ -50,11 +50,11 @@ export const LogOut = (): Promise<ApiResponse> => {
|
|||||||
|
|
||||||
// Google登录/注册参数类型
|
// Google登录/注册参数类型
|
||||||
interface GoogleAuthParamsType {
|
interface GoogleAuthParamsType {
|
||||||
credential?: string // Google ID Token (用于One Tap登录)
|
accessToken?: string // Google ID Token (用于One Tap登录)
|
||||||
}
|
}
|
||||||
export const googleAuth = (data: GoogleAuthParamsType): Promise<LoginResponse> => {
|
export const googleAuth = (data: GoogleAuthParamsType): Promise<LoginResponse> => {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/auth/parseGoogleCredential',
|
url: '/api/auth/parseGoogleAccessToken',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
const navs = [
|
const navs = [
|
||||||
{ label: 'Home', icon: 'home', size: 73, path: '/stylist/customer', on: onHome },
|
{ label: 'Home', icon: 'home', size: 73, path: '/homeNav' },
|
||||||
{ label: 'Library', icon: 'library', size: 53, path: '/workshop/library' },
|
{ label: 'Library', icon: 'library', size: 53, path: '/workshop/library' },
|
||||||
{ label: 'Profile', icon: 'profile', size: 55, path: '/workshop/profile' }
|
{ label: 'Profile', icon: 'profile', size: 55, path: '/workshop/profile' }
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
defineProps({
|
defineProps({
|
||||||
title: { type: String, default: 'AI STYLING ASSISTANT' },
|
title: { type: String, default: 'AI STYLING ASSISTANT' },
|
||||||
hasSetting: { type: Boolean, default: false },
|
hasSetting: { type: Boolean, default: false },
|
||||||
styleType: { type: String, default: '1' },//1低 2高
|
styleType: { type: String, default: '1' },//1低 2高 3-12rem
|
||||||
isPlaceholder: { type: Boolean, default: true },
|
isPlaceholder: { type: Boolean, default: true },
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -36,6 +36,10 @@
|
|||||||
--header-title-border-bottom-width: 0.2rem;
|
--header-title-border-bottom-width: 0.2rem;
|
||||||
--header-title-return-left: 7.8rem;
|
--header-title-return-left: 7.8rem;
|
||||||
}
|
}
|
||||||
|
&[style-type="3"] {
|
||||||
|
--header-title-height: 12rem;
|
||||||
|
--header-title-border-bottom-width: 0.2rem;
|
||||||
|
}
|
||||||
> div {
|
> div {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--header-title-height, 9.9rem);
|
height: var(--header-title-height, 9.9rem);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<div class="footer">
|
<div class="footer">
|
||||||
<p v-show="!loading" class="placeholder" ref="placeholder"></p>
|
<p v-show="!loading" class="placeholder" ref="placeholder"></p>
|
||||||
<span class="loading" v-show="loading">Loading...</span>
|
<span class="loading" v-show="loading">Loading...</span>
|
||||||
<span class="nomore" v-show="finish">Mo more</span>
|
<span class="nomore" v-show="finish">No more</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -88,11 +88,11 @@ const {} = toRefs(data);
|
|||||||
> .item{
|
> .item{
|
||||||
width: calc(50% - 3.1rem / 2);
|
width: calc(50% - 3.1rem / 2);
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-bottom: 3.3rem;
|
// margin-bottom: 3.3rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
> .title{
|
> .title{
|
||||||
font-size: 3.6rem;
|
font-size: 3.44rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #000;
|
color: #000;
|
||||||
font-family: 'satoshiMedium';
|
font-family: 'satoshiMedium';
|
||||||
@@ -102,7 +102,7 @@ const {} = toRefs(data);
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
height: 47.2rem;
|
height: 45rem;
|
||||||
margin: 2.4rem 0;
|
margin: 2.4rem 0;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -148,8 +148,8 @@ const {} = toRefs(data);
|
|||||||
color: #000;
|
color: #000;
|
||||||
margin-right: 1.2rem;
|
margin-right: 1.2rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 6.6rem;
|
width: 5.2rem;
|
||||||
height: 6.6rem;
|
height: 5.2rem;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
&:last-child{
|
&:last-child{
|
||||||
|
|||||||
@@ -26,12 +26,12 @@
|
|||||||
}
|
}
|
||||||
const onReload = () => {
|
const onReload = () => {
|
||||||
customizeInfo.inputText = customizeInfo.oldInputText
|
customizeInfo.inputText = customizeInfo.oldInputText
|
||||||
generate("reload")
|
generate('reload')
|
||||||
customizeInfo.inputText = ''
|
customizeInfo.inputText = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成结果
|
// 生成结果
|
||||||
const generate = (type?: "reload") => {
|
const generate = (type?: 'reload') => {
|
||||||
customizeInfo.oldInputText = customizeInfo.inputText
|
customizeInfo.oldInputText = customizeInfo.inputText
|
||||||
customizeInfo.oldTryOnId = customizeInfo.tryOnId
|
customizeInfo.oldTryOnId = customizeInfo.tryOnId
|
||||||
const data = {
|
const data = {
|
||||||
@@ -39,11 +39,12 @@
|
|||||||
visitRecordId: generateStore.visitRecordId,
|
visitRecordId: generateStore.visitRecordId,
|
||||||
styleId: generateStore.styleId,
|
styleId: generateStore.styleId,
|
||||||
// modelPhotoId: generateStore.modelPhotoId,
|
// modelPhotoId: generateStore.modelPhotoId,
|
||||||
originalTryOnId: type === "reload" ? customizeInfo.oldTryOnId : generateStore.originalTryOnId,
|
originalTryOnId: type === 'reload' ? customizeInfo.oldTryOnId : generateStore.originalTryOnId,
|
||||||
isRegenerated: 1,
|
isRegenerated: 1,
|
||||||
prompt: customizeInfo.inputText
|
prompt: customizeInfo.inputText
|
||||||
}
|
}
|
||||||
if (generateStore.customerPhotoId && customizeInfo.count === 0) data["customerPhotoId"] = generateStore.customerPhotoId
|
if (generateStore.customerPhotoId && customizeInfo.count === 0)
|
||||||
|
data['customerPhotoId'] = generateStore.customerPhotoId
|
||||||
loading.value = true
|
loading.value = true
|
||||||
generateTryOnEffect(data)
|
generateTryOnEffect(data)
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
@@ -92,8 +93,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<header-title style-type="2" />
|
<header-title style-type="2" />
|
||||||
<div class="loading" v-if="loading"><generate-loading /></div>
|
<div class="loading" v-if="loading"><generate-loading /></div>
|
||||||
<template v-else>
|
<div class="customize" v-else>
|
||||||
<div class="customize">
|
|
||||||
<div class="title">Customize your Look!</div>
|
<div class="title">Customize your Look!</div>
|
||||||
<p class="tip">Refine your Look</p>
|
<p class="tip">Refine your Look</p>
|
||||||
<div class="input-box">
|
<div class="input-box">
|
||||||
@@ -117,7 +117,9 @@
|
|||||||
<div @click="onLove">
|
<div @click="onLove">
|
||||||
<SvgIcon :name="`love_${customizeInfo.isFavorite ? 1 : 0}`" size="35" />
|
<SvgIcon :name="`love_${customizeInfo.isFavorite ? 1 : 0}`" size="35" />
|
||||||
</div>
|
</div>
|
||||||
<div @click="onReload" v-show="customizeInfo.oldInputText"><SvgIcon name="reload" size="35" /></div>
|
<div @click="onReload" v-show="customizeInfo.oldInputText">
|
||||||
|
<SvgIcon name="reload" size="35" />
|
||||||
|
</div>
|
||||||
<!-- <div @click="onDownload"><SvgIcon name="download" size="35" /></div> -->
|
<!-- <div @click="onDownload"><SvgIcon name="download" size="35" /></div> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -127,7 +129,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<footer-navigation />
|
<footer-navigation />
|
||||||
</template>
|
</template>
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.loading {
|
.loading {
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ defineExpose({})
|
|||||||
margin-top: 6.8rem;
|
margin-top: 6.8rem;
|
||||||
font-size: 9.6rem;
|
font-size: 9.6rem;
|
||||||
line-height: 124%;
|
line-height: 124%;
|
||||||
background: radial-gradient(99.56% 47.68% at 99.56% 93.08%, #E6E6E6 0%, #443E37 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */,
|
background: #B3B3B3;
|
||||||
linear-gradient(120.09deg, #B3B3B3 0%, rgba(255, 255, 255, 0) 35.41%);
|
background: linear-gradient(120deg, #b3b3b3 1%, rgba(0, 0, 0, 0) 48%), linear-gradient(
|
||||||
|
344deg, #B3B3B2 16%, #000000 66%);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
color: transparent; /* 文字本身透明,显示渐变背景 */
|
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
}
|
}
|
||||||
> .navBox{
|
> .navBox{
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ const { isLoading } = toRefs(data);
|
|||||||
<div class="loading-container" v-if="isLoading">
|
<div class="loading-container" v-if="isLoading">
|
||||||
<GenerateLoading title="Generating Results..." />
|
<GenerateLoading title="Generating Results..." />
|
||||||
</div>
|
</div>
|
||||||
|
<footer-navigation is-placeholder/>
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.product{
|
.product{
|
||||||
@@ -281,9 +282,10 @@ const { isLoading } = toRefs(data);
|
|||||||
.loading-container{
|
.loading-container{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
// align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
padding-top: 36.6rem;
|
||||||
}
|
}
|
||||||
.feedback{
|
.feedback{
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -294,6 +296,7 @@ const { isLoading } = toRefs(data);
|
|||||||
> .succeedIcon{
|
> .succeedIcon{
|
||||||
width: 12.8rem;
|
width: 12.8rem;
|
||||||
height: 12.8rem;
|
height: 12.8rem;
|
||||||
|
margin-top: 11.6rem;
|
||||||
> img{
|
> img{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { onMounted, onUnmounted, reactive, toRefs, computed, onActivated } from "vue";
|
import { onMounted, onUnmounted, reactive, toRefs, computed, onActivated } from "vue";
|
||||||
import SelectItem from "@/components/selectStyle/selectItem.vue";
|
import SelectItem from "@/components/selectStyle/selectItem.vue";
|
||||||
import HeaderTitle from '@/components/HeaderTitle.vue'
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useGenerateStore, useUserInfoStore } from '@/stores'
|
import { useGenerateStore, useUserInfoStore } from '@/stores'
|
||||||
import { showToast } from 'vant';
|
import { showToast } from 'vant';
|
||||||
@@ -122,14 +123,15 @@ const { styleList, select } = toRefs(data);
|
|||||||
<SelectItem :selectList="styleList" v-model:select="select" @selectItem="selectItem" @updateStyle="updateStyle" />
|
<SelectItem :selectList="styleList" v-model:select="select" @selectItem="selectItem" @updateStyle="updateStyle" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer placeholder"></div>
|
<!-- <div class="footer placeholder"></div> -->
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<button @click.stop="toProduct">Continue</button>
|
<button @click.stop="toProduct">Continue</button>
|
||||||
</div>
|
</div>
|
||||||
|
<footer-navigation is-placeholder />
|
||||||
</template>
|
</template>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.header-title {
|
.header-title {
|
||||||
--header-title-background: #f6f6f6;
|
// --header-title-background: #f6f6f6;
|
||||||
}
|
}
|
||||||
.selectStyle{
|
.selectStyle{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -144,7 +146,7 @@ const { styleList, select } = toRefs(data);
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: 3.4rem;
|
margin-top: 3.4rem;
|
||||||
margin-bottom: 7.2rem;
|
margin-bottom: 4.9rem;
|
||||||
> .title{
|
> .title{
|
||||||
font-family: satoshiBold;
|
font-family: satoshiBold;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -159,13 +161,13 @@ const { styleList, select } = toRefs(data);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.selectContent{
|
.selectContent{
|
||||||
padding: 0 3.5rem;
|
padding: 0 4rem;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.footer {
|
.footer {
|
||||||
position: fixed;
|
// position: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="asistant-container flex flex-column">
|
<div class="asistant-container flex flex-column">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<HeaderTitle hasSetting styleType="2" />
|
<HeaderTitle hasSetting styleType="3" />
|
||||||
</div>
|
</div>
|
||||||
<div class="loading-container" v-if="isLoading">
|
<div class="loading-container" v-if="isLoading">
|
||||||
<GenerateLoading />
|
<GenerateLoading />
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<img :src="google" class="google-icon" />
|
<img :src="google" class="google-icon" />
|
||||||
Sign in with Google
|
Sign in with Google
|
||||||
</div> -->
|
</div> -->
|
||||||
<GoogleLogin @googelLogin="handleGoogleLogin"></GoogleLogin>
|
<GoogleLogin @googelLogin="handleGoogleLogin" ref="googleLoginRef" @click="clickGooleLogin"></GoogleLogin>
|
||||||
<div class="sign-up-button" @click="handleSignup">Don’t have an account? Sign Up</div>
|
<div class="sign-up-button" @click="handleSignup">Don’t have an account? Sign Up</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -128,12 +128,15 @@ const handleForgotPassword = () => {
|
|||||||
// 这里可以跳转到忘记密码页面
|
// 这里可以跳转到忘记密码页面
|
||||||
router.push('/reset')
|
router.push('/reset')
|
||||||
}
|
}
|
||||||
|
const googleLoginRef = ref(null)
|
||||||
|
const clickGooleLogin = () => {
|
||||||
|
googleLoginRef.value?.login()
|
||||||
|
}
|
||||||
// 处理Google登录
|
// 处理Google登录
|
||||||
const handleGoogleLogin = async (credential: string) => {
|
const handleGoogleLogin = async (accessToken: string) => {
|
||||||
try {
|
try {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
const result = await googleAuth({ credential })
|
const result = await googleAuth({ accessToken })
|
||||||
// console.log('result', result)
|
// console.log('result', result)
|
||||||
userInfoStore.setToken(result.token)
|
userInfoStore.setToken(result.token)
|
||||||
userInfoStore.setUserInfo(result.user)
|
userInfoStore.setUserInfo(result.user)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<button type="button" class="login-button" @click="handleConfirm">Sign Up</button>
|
<button type="button" class="login-button" @click="handleConfirm">Sign Up</button>
|
||||||
|
|
||||||
<GoogleLogin text="Sign up with Google" @googelLogin="handleGoogleSignup" />
|
<GoogleLogin text="Sign up with Google" @googelLogin="handleGoogleSignup" ref="googleSignupRef" @click="clickGooleLogin" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -130,12 +130,15 @@ const handleConfirm = async () => {
|
|||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const googleSignupRef = ref(null)
|
||||||
|
const clickGooleLogin = () => {
|
||||||
|
googleSignupRef.value?.login()
|
||||||
|
}
|
||||||
// 处理Google注册
|
// 处理Google注册
|
||||||
const handleGoogleSignup = async (credential: string) => {
|
const handleGoogleSignup = async (accessToken: string) => {
|
||||||
try {
|
try {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
const result = await googleAuth({ credential })
|
const result = await googleAuth({ accessToken })
|
||||||
userInfoStore.setToken(result.token)
|
userInfoStore.setToken(result.token)
|
||||||
userInfoStore.setUserInfo(result.user)
|
userInfoStore.setUserInfo(result.user)
|
||||||
showToast('Google sign up successful')
|
showToast('Google sign up successful')
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive, onMounted, onBeforeUnmount } from 'vue'
|
import { reactive, onMounted, onBeforeUnmount } from 'vue'
|
||||||
import { showToast } from 'vant'
|
|
||||||
import { google } from '@/assets/base64'
|
import { google } from '@/assets/base64'
|
||||||
|
|
||||||
// 定义 props
|
// 定义 props
|
||||||
@@ -25,35 +24,22 @@ const emit = defineEmits<{
|
|||||||
(e: 'googelLogin', code: string): void
|
(e: 'googelLogin', code: string): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
// JWT 解码函数
|
|
||||||
function decodeJWT(token: string) {
|
|
||||||
const base64Url = token.split('.')[1]
|
|
||||||
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/')
|
|
||||||
const jsonPayload = decodeURIComponent(
|
|
||||||
atob(base64)
|
|
||||||
.split('')
|
|
||||||
.map(function (c) {
|
|
||||||
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
|
|
||||||
})
|
|
||||||
.join('')
|
|
||||||
)
|
|
||||||
return JSON.parse(jsonPayload)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理 Google 登录回调
|
// 处理 Google 登录回调
|
||||||
const handleCredentialResponse = async (response: { credential: string }) => {
|
const handleCredentialResponse = async (response: { access_token: string, credential: string }) => {
|
||||||
// 获取回调响应的凭证数据 然后拿这个凭证给后台,后台jwt进行解析获取登录信息
|
console.log('Google 登录响应:', response)
|
||||||
console.log('Encoded JWT ID token: ' + response.credential)
|
// fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
|
||||||
const responsePayload = decodeJWT(response.credential)
|
// headers: {
|
||||||
console.log('Decoded JWT ID token fields:')
|
// 'Authorization': `Bearer ${response.access_token}`
|
||||||
console.log(' Full Name: ' + responsePayload.name)
|
// }
|
||||||
console.log(' Given Name: ' + responsePayload.given_name)
|
// })
|
||||||
console.log(' Family Name: ' + responsePayload.family_name)
|
// .then(response => response.json())
|
||||||
console.log(' Unique ID: ' + responsePayload.sub)
|
// .then(userInfo => {
|
||||||
console.log(' Profile image URL: ' + responsePayload.picture)
|
// console.log('User info:', userInfo);
|
||||||
console.log(' Email: ' + responsePayload.email)
|
// })
|
||||||
|
// .catch(error => {
|
||||||
const code = response.credential
|
// console.error('Error fetching user info:', error);
|
||||||
|
// });
|
||||||
|
const code = response.access_token
|
||||||
emit('googelLogin', code)
|
emit('googelLogin', code)
|
||||||
window.isAddGmail = false
|
window.isAddGmail = false
|
||||||
}
|
}
|
||||||
@@ -62,11 +48,10 @@ const handleCredentialResponse = async (response: { credential: string }) => {
|
|||||||
const data = reactive({
|
const data = reactive({
|
||||||
// scriptSrc:'https://apis.google.com/js/platform.js',
|
// scriptSrc:'https://apis.google.com/js/platform.js',
|
||||||
scriptSrc: 'https://accounts.google.com/gsi/client',
|
scriptSrc: 'https://accounts.google.com/gsi/client',
|
||||||
script: null
|
script: null,
|
||||||
|
tokenClient: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(import.meta.env.VITE_USER_NODE_ENV)
|
|
||||||
|
|
||||||
// 根据环境设置 Google Client ID
|
// 根据环境设置 Google Client ID
|
||||||
const GOOGLE_CLIENT_ID = '216037134725-7q8vqp0ohtmohlosltkfg7bd2v29rm5a.apps.googleusercontent.com'
|
const GOOGLE_CLIENT_ID = '216037134725-7q8vqp0ohtmohlosltkfg7bd2v29rm5a.apps.googleusercontent.com'
|
||||||
|
|
||||||
@@ -85,28 +70,39 @@ const createGmailLogin = async () => {
|
|||||||
script.src = data.scriptSrc
|
script.src = data.scriptSrc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
window.google.accounts.id.initialize({
|
// window.google.accounts.id.initialize({
|
||||||
// 主要就是填写client_id
|
// // 主要就是填写client_id
|
||||||
|
// client_id: GOOGLE_CLIENT_ID,
|
||||||
|
// auto_select: false,
|
||||||
|
// callback: handleCredentialResponse,
|
||||||
|
// // context:"signin",
|
||||||
|
// ux_mode: 'popup',
|
||||||
|
// itp_support: true
|
||||||
|
// })
|
||||||
|
// console.log('创建谷歌登录按钮:', document.querySelector('.Container #g_id_signin'))
|
||||||
|
// window.google.accounts.id.renderButton(document.querySelector('.Container #g_id_signin'), {
|
||||||
|
// type: 'standard', //icon为只有一个icon
|
||||||
|
// shape: 'circle',
|
||||||
|
// theme: 'outline',
|
||||||
|
// size: 'large',
|
||||||
|
// logo_alignment: 'center'
|
||||||
|
// })
|
||||||
|
|
||||||
|
data.tokenClient = window.google.accounts.oauth2.initTokenClient({
|
||||||
client_id: GOOGLE_CLIENT_ID,
|
client_id: GOOGLE_CLIENT_ID,
|
||||||
auto_select: false,
|
scope: "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
|
||||||
callback: handleCredentialResponse,
|
callback: handleCredentialResponse,
|
||||||
// context:"signin",
|
|
||||||
ux_mode: 'popup',
|
|
||||||
itp_support: true
|
|
||||||
})
|
|
||||||
console.log(document.querySelector('.Container #g_id_signin'))
|
|
||||||
window.google.accounts.id.renderButton(document.querySelector('.Container #g_id_signin'), {
|
|
||||||
type: 'standard', //icon为只有一个icon
|
|
||||||
shape: 'circle',
|
|
||||||
theme: 'outline',
|
|
||||||
size: 'large',
|
|
||||||
logo_alignment: 'center'
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toGmailLogin = () => {
|
const login = ()=>{
|
||||||
showToast('Google login is not available yet')
|
if(!data.tokenClient) {
|
||||||
|
console.warn('谷歌登录未初始化')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.tokenClient.requestAccessToken()
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
@@ -120,6 +116,10 @@ onBeforeUnmount(() => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
createGmailLogin()
|
createGmailLogin()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
login
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.Container {
|
.Container {
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<header-title style-type="3" />
|
||||||
<div class="dressfor-container flex">
|
<div class="dressfor-container flex">
|
||||||
<div class="content flex-1 flex flex-column">
|
<div class="content flex-1 flex flex-column">
|
||||||
<div class="setting flex flex-between">
|
<!-- <div class="setting flex flex-between">
|
||||||
<van-icon name="arrow-left" color="#fff" @click="handleBack" />
|
<van-icon name="arrow-left" color="#fff" @click="handleBack" />
|
||||||
<SvgIcon name="setting" size="70" />
|
<SvgIcon name="setting" size="70" />
|
||||||
</div>
|
</div> -->
|
||||||
<div class="text">What are you dressing for?</div>
|
<div class="text">What are you dressing for?</div>
|
||||||
<div class="start-btn" @click="handleStart">Start</div>
|
<div class="start-btn" @click="handleStart">Start</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<footer-navigation />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
@@ -25,7 +29,7 @@ const handleStart = () => {
|
|||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.dressfor-container {
|
.dressfor-container {
|
||||||
height: 100vh;
|
height: calc(100vh - 12rem - 14.9rem);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<header-title style-type="3" />
|
||||||
<div class="stylist-page">
|
<div class="stylist-page">
|
||||||
<!-- 主要内容区域 -->
|
<!-- 主要内容区域 -->
|
||||||
<div class="content">
|
<div class="content">
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
<Video ref="videoRef" />
|
<Video ref="videoRef" />
|
||||||
</van-dialog>
|
</van-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
<footer-navigation />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -57,6 +59,8 @@ import Video from './components/Video.vue'
|
|||||||
import { useUserInfoStore } from '@/stores'
|
import { useUserInfoStore } from '@/stores'
|
||||||
import male from '@/assets/images/male.png'
|
import male from '@/assets/images/male.png'
|
||||||
import female from '@/assets/images/female.png'
|
import female from '@/assets/images/female.png'
|
||||||
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userInfoStore = useUserInfoStore()
|
const userInfoStore = useUserInfoStore()
|
||||||
@@ -111,7 +115,7 @@ const handleChangeSwiper = (type: 'next' | 'prev') => {
|
|||||||
|
|
||||||
const handleClickStylist = (item: any) => {
|
const handleClickStylist = (item: any) => {
|
||||||
console.log(item)
|
console.log(item)
|
||||||
showVideo.value = true
|
// showVideo.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleContinue = () => {
|
const handleContinue = () => {
|
||||||
@@ -136,7 +140,7 @@ watch(showVideo, (newValue) => {
|
|||||||
.stylist-page {
|
.stylist-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: calc(100vh - 12rem - 14.9rem);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -165,6 +169,7 @@ watch(showVideo, (newValue) => {
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: white;
|
color: white;
|
||||||
font-family: 'boskaRegular';
|
font-family: 'boskaRegular';
|
||||||
|
line-height: 96%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<header-title style-type="3" />
|
||||||
<div class="sex-select">
|
<div class="sex-select">
|
||||||
<div class="text">Before we begin.</div>
|
<div class="text">Before we begin.</div>
|
||||||
<div class="desc">Who are you styling?</div>
|
<div class="desc">Who are you styling?</div>
|
||||||
@@ -14,8 +15,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<footer-navigation />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import HeaderTitle from '@/components/HeaderTitle.vue'
|
||||||
|
import FooterNavigation from '@/components/FooterNavigation.vue'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import {useUserInfoStore} from '@/stores'
|
import {useUserInfoStore} from '@/stores'
|
||||||
@@ -36,7 +40,7 @@ const handleSelect = (value: string) => {
|
|||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.sex-select {
|
.sex-select {
|
||||||
height: 100vh;
|
height: calc(100vh - 12rem - 14.9rem);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -58,7 +62,7 @@ const handleSelect = (value: string) => {
|
|||||||
.select-list {
|
.select-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 31.6rem;
|
bottom: 15.7rem;
|
||||||
width: calc(100% - 12.4rem - 8.5rem);
|
width: calc(100% - 12.4rem - 8.5rem);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
Reference in New Issue
Block a user