Files
lanecarford_front/src/views/stylist/index.vue
2025-12-01 11:30:31 +08:00

342 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<header-title style-type="3" />
<div class="stylist-page">
<!-- 主要内容区域 -->
<div class="content">
<!-- 标题 -->
<div class="header">
<div class="title">CHOOSE YOUR STYLIST</div>
</div>
<div class="carousel-container" v-show="!showVideo">
<div class="nav-arrow left" @click="handleChangeSwiper('prev')">
<!-- <van-icon name="arrow-left" color="#fff" /> -->
<SvgIcon name="left" size="70" color="#fff" />
</div>
<van-swipe touchable ref="swiperRef" @change="handleChangeCurrent">
<van-swipe-item v-for="item in stylists" :key="item.id">
<div class="swiper-container" @click="handleClickStylist(item)">
<img :src="item.image" />
<div class="text-container">
<div class="name">{{ item.name }}</div>
<div class="description">
{{ item.description }}
</div>
</div>
</div>
</van-swipe-item>
</van-swipe>
<div class="nav-arrow right" @click="handleChangeSwiper('next')">
<SvgIcon class="arrow-right" name="left" size="70" color="#fff" />
</div>
</div>
</div>
<!-- Continue按钮 -->
<div class="continue-button" @click="handleContinue" v-if="!$route.query?.demo">Continue</div>
<van-dialog
class="video-dialog"
:show-confirm-button="false"
:show-cancel-button="false"
close-on-click-overlay
v-model:show="showVideo"
title=""
>
<div class="close-btn" @click="showVideo = false">
<van-icon name="cross" class="close-icon" />
</div>
<Video ref="videoRef" />
</van-dialog>
</div>
<footer-navigation />
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useRouter } from 'vue-router'
import Video from './components/Video.vue'
import { useUserInfoStore } from '@/stores'
import male from '@/assets/images/male.png'
import female from '@/assets/images/female.png'
import HeaderTitle from '@/components/HeaderTitle.vue'
import FooterNavigation from '@/components/FooterNavigation.vue'
const router = useRouter()
const userInfoStore = useUserInfoStore()
// stylist数据
const stylists = ref<any[]>([
{
id: 1,
value: 'crystal',
name: 'Vera Lo',
description: 'Contemporary, Classic, Simple Silhouettes, Statement Pieces',
image: female
},
{
id: 2,
value: 'mini',
name: 'Sarah Chen',
description: 'Modern, Edgy, Bold Colors, Street Style',
image: male
},
{
id: 3,
value: 'crystal',
name: 'Emma Wilson',
description: 'Elegant, Feminine, Vintage Inspired, Soft Tones',
image: female
},
{
id: 4,
value: 'mini',
name: 'Alex Johnson',
description: 'Minimalist, Professional, Neutral Palette, Clean Lines',
image: male
}
])
const currentChoosed = ref(1)
const swiperRef = ref<any>(null)
const showVideo = ref<boolean>(false)
const videoRef = ref<any>(null)
const handleChangeCurrent = (index: number) => {
currentChoosed.value = stylists.value[index].id
}
const handleChangeSwiper = (type: 'next' | 'prev') => {
if (type === 'next') {
swiperRef.value.next()
} else {
swiperRef.value.prev()
}
}
const handleClickStylist = (item: any) => {
console.log(item)
// showVideo.value = true
}
const handleContinue = () => {
const generateParams = userInfoStore.getGenerateParams()
generateParams.stylist =
stylists.value.find((item) => item.id === currentChoosed.value)?.value || ''
userInfoStore.setGenerateParams(generateParams)
router.push('/stylist/sex')
}
// 监听showVideo变化关闭时暂停视频
watch(showVideo, (newValue) => {
if (!newValue && videoRef.value) {
videoRef.value.pause()
videoRef.value.reset()
}
})
</script>
<style scoped lang="less">
.stylist-page {
position: relative;
width: 100%;
height: calc(100vh - 12rem - 14.9rem);
overflow: hidden;
display: flex;
flex-direction: column;
color: #fff;
background: url('@/assets/images/stylist_bg.png') no-repeat center center;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.content {
position: relative;
z-index: 2;
flex: 1;
display: flex;
flex-direction: column;
padding: 2rem;
padding-top: 6rem;
}
.header {
text-align: center;
margin-bottom: 4rem;
.title {
font-size: 15rem;
font-weight: 400;
color: white;
font-family: 'boskaRegular';
line-height: 96%;
}
}
.carousel-container {
position: relative;
display: flex;
// align-items: center;
// justify-content: center;
// flex: 1;
margin: 2rem 0;
}
.nav-arrow {
font-size: 4rem;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 8.6rem;
height: 8.4rem;
background: rgba(255, 255, 255, 0.15);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s ease;
z-index: 3;
box-shadow: 0 2rem 2.5rem rgba(0, 0, 0, 0.25), 0 0 6rem rgba(0, 0, 0, 0.25);
border: 0.1rem solid rgba(255, 255, 255, 0.2);
filter: drop-shadow(0.2rem 4px 6.6px rgba(0, 0, 0, 0.25));
&.left {
left: 1rem;
}
&.right {
right: 1rem;
.arrow-right {
transform: rotate(180deg);
}
}
}
.van-swipe {
.van-swipe-item {
display: flex;
justify-content: center;
.swiper-container {
width: 66rem;
height: 100rem;
border: 0.2rem solid #fff;
border-radius: 1.2rem;
display: flex;
flex-direction: column;
align-items: center;
padding: 4.25rem 0 2.65rem;
background: radial-gradient(
100% 100% at 0% 0%,
rgba(115, 115, 115, 0.4) 0%,
rgba(115, 115, 115, 0.2) 50%,
rgba(0, 0, 0, 0) 100%
);
backdrop-filter: blur(35px);
-webkit-backdrop-filter: blur(35px);
-moz-backdrop-filter: blur(35px);
-ms-backdrop-filter: blur(35px);
-o-backdrop-filter: blur(35px);
overflow: hidden;
position: relative;
img {
width: 59rem;
height: 63rem;
object-fit: cover;
}
.text-container {
padding: 0 5.25rem;
width: 100%;
font-weight: 400;
.name {
line-height: 6rem;
font-size: 4.8rem;
margin: 2.6rem 0 2.2rem;
}
.description {
// line-height: 3rem;
font-size: 2.8rem;
// width: 100%;
}
}
}
}
:deep(.van-swipe__indicators) {
bottom: 2.65rem;
background: #fff;
border-radius: 25px;
padding: 1rem 2rem;
.van-swipe__indicator {
width: 1rem;
height: 1rem;
background-color: #d9d9d9;
opacity: 1;
}
.van-swipe__indicator--active {
background-color: #000;
opacity: 1;
width: 3rem;
border-radius: 3px;
}
}
}
.continue-button {
height: 5.9rem;
box-sizing: border-box;
position: absolute;
bottom: 6.4rem;
right: 7.6rem;
padding: 0 3.4rem;
border: 0.3rem solid #fff;
border-radius: 1rem;
color: white;
font-size: 4rem;
font-weight: 500;
cursor: pointer;
z-index: 3;
font-family: 'satoshiRegular';
display: flex;
align-items: center;
}
:deep(.van-overlay) {
background: transparent;
}
:deep(.video-dialog) {
width: calc(100% - 12rem);
background: transparent;
.close-btn {
width: 8.6rem;
height: 8.4rem;
position: absolute;
right: 0;
top: 0;
z-index: 3;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(145deg, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.4));
border-radius: 50%;
cursor: pointer;
backdrop-filter: blur(1rem);
-webkit-backdrop-filter: blur(1rem);
-moz-backdrop-filter: blur(1rem);
-ms-backdrop-filter: blur(1rem);
-o-backdrop-filter: blur(1rem);
border: 1px solid rgba(255, 255, 255, 0.3);
box-shadow: 0 0.8rem 1.6rem rgba(0, 0, 0, 0.4), inset 0 0.2rem 0.4rem rgba(255, 255, 255, 0.1),
inset 0 -0.2rem 0.4rem rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
.close-icon {
color: white;
font-size: 3.64rem;
text-shadow: 0 0.2rem 0.4rem rgba(0, 0, 0, 0.5);
}
}
}
</style>