Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/lanecarford_front

This commit is contained in:
X1627315083
2025-11-17 14:37:16 +08:00
17 changed files with 183 additions and 120 deletions

34
env.d.ts vendored
View File

@@ -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
}

View File

@@ -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
}) })

View File

@@ -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' }
] ]

View File

@@ -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);

View File

@@ -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>

View File

@@ -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{

View File

@@ -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 {

View File

@@ -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{

View File

@@ -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%;

View File

@@ -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;

View File

@@ -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 />

View File

@@ -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">Dont have an account? Sign Up</div> <div class="sign-up-button" @click="handleSignup">Dont 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)

View File

@@ -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')

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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%;
} }
} }

View File

@@ -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;