Files
ylst-pc/src/views/Home/components/Operating.vue
du.meimei 9c8d8ee218 feat(首页): 使用 Swiper替换 Element UI 轮播组件
- 移除 Element UI 的 el-carousel 组件
-引入 Swiper 库并实现轮播功能
- 优化轮播项的样式和布局
- 添加自定义左右按钮和分页器
- 实现视频自动播放和轮播同步
- 优化轮播切换效果,支持 fade切换
2025-05-24 17:53:08 +08:00

430 lines
11 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>
<div class="operating-container">
<div class="top">
<p class="fw-bold fs-24 title">简单4步轻松完成你的调研</p>
<p class="desc">创建编辑投放分析让洞察更简单</p>
</div>
<div style="height: 80%">
<div class="swiper-container" ref="swiperContainer">
<div class="swiper-wrapper">
<div
v-for="(item, index) in operatingList"
:key="index"
class="swiper-slide"
>
<div class="flex" style="justify-content: center">
<div style="margin-right: 9%">
<div class="flex-start operating-item" >
<p class="progress" :style="{'color':item.btnColor}">
<span class="fs-36">
{{index+1}}
</span>
<img src="@/assets/img/home/xiegang.png" alt="">
<span>
{{operatingList.length}}
</span>
</p>
<div class="info">
<p>{{item.title}}</p>
<p>{{item.desc}}</p>
</div>
</div>
<ul class="desc-item">
<li class="flex" v-for="(tips,index) in item.descList" :key="index">
<p class="block"></p>
{{tips}}
<span class="fs-12 tag" v-if="index === 0 && item.isShowTag">
新功能
</span>
</li>
</ul>
<a-button type="primary" @click="toSurveyInfo(item,index)">
立即体验
<img src="@/assets/img/home/tow.png" alt=""
style="margin-left: 5px;margin-bottom: 2px">
</a-button>
</div>
<div>
<video
ref="videoPlayer"
class="video-player"
width="820"
height="420"
autoplay
muted
playsinline
style="width: 100%;">
<source :src="getVideo(index)" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>
</div>
</div>
</div>
<!-- 分页器 -->
<div class="swiper-pagination" ref="pagination"></div>
<!-- 自定义左右按钮 -->
<div class="custom-swiper-button-prev" ref="prevBtn" @click="goPre">
<img ref="prevImg" src="@/assets/img/home/kanoicon.png" alt="Previous" />
</div>
<div class="custom-swiper-button-next" ref="nextBtn" @click="goNext">
<img ref="nextImg" src="@/assets/img/home/pkicon.png" alt="Next" />
</div>
</div>
</div>
</div>
</template>
<script setup>
import {ref, onMounted, onBeforeUnmount} from 'vue'
import Swiper from 'swiper';
import 'swiper/swiper-bundle.css';
import { useRouter } from 'vue-router';
import { getQueryUserSurvey } from '@/api/home';
const router = useRouter();
const emit = defineEmits(['create-survey']);
const swiperContainer = ref(null);
const pagination = ref(null);
const prevBtn = ref(null);
const nextBtn = ref(null);
const prevImg = ref(null);
const nextImg = ref(null);
// 🟩 存储 Swiper 实例
let mySwiper = null;
const goPre = () => {
if (mySwiper) {
mySwiper.slidePrev(); // 👈 使用实例方法
}
};
const goNext = () => {
if (mySwiper) {
mySwiper.slideNext(); // 👈 使用实例方法
}
};
const operatingList = ref(
[
{
title: '多种方式',
desc:'快速创建问卷',
descList:[
'一句话AI生成问卷高效智能','20+专业场景模板,快速创建','WORD模板上传一键导入','空白创建编辑,灵活简单'
],
btnColor:'green',
isShowTag:true
},
{
title: '编辑质检',
desc:'设计快速搞定',
descList:[
'30+专业题型及模型题组,多种逻辑适配各类场景','AI多维度问卷质检快速识别问题提供建议',
'多种主题、九宫格抽奖, 自定义问卷风格', '多人协作编辑,便捷协同快捷高效'
],
btnColor:'green',
key:'design'
},{
title: '精准触达',
desc:'投放轻松高效',
descList:[
'多元样本资源精准圈选,在线一站式投放','标准链接及二维码,问卷快捷私发群发','自定义链接参数,记录多渠道样本来源','回收进度、配额进度在线实时追踪'
],
btnColor:'green',
key:'accurate'
},{
title: '数据分析',
desc:'多种维度洞察',
descList:[
'AI数据清洗无效数据在线剔除','AI智能总结调研结论一键洞察','专业模型看板,直达分析结论','个性化交叉分析,多维数据挖掘'
],
btnColor:'green',
key:'particulars'
}])
const toSurveyInfo = async (item,index) => {
let res = await getQueryUserSurvey()
const {sn} = res.data
const urlJson = {
design: `/survey/planet/design?sn=${sn}`,
accurate: `/survey/publish/accurate?sn=${sn}`,
particulars: `/survey/analyse/diagram?sn=${sn}`,
};
if (index === 0){
// 在第 101 行通过事件通知父组件调用 Scene.vue 文件的 createScene 方法
const sceneObj = {
title: '智能创建',
description: 'AI随行调研随心',
value: 1
};
// 通过事件向父组件发送信号,让父组件调用 Scene 组件的 createScene 方法
emit('create-survey', sceneObj, 0);
}else{
if (res.data.flag){
await router.push({
path: urlJson[item.key],
query: {
sn,
}
});
}
}
}
const getVideo = (index) => {
return require(`@/assets/img/home/video${index+1}.mp4`)
}
const addVideoEndedListener =()=> {
const videos = document.querySelectorAll('.video-player');
videos.forEach((video, index) => {
video.addEventListener('ended', () => {
if (index < operatingList.value.length - 1) {
mySwiper.slideNext(); // 自动滑动到下一页
}
});
// // 使用 WeakMap 或 data-* 存储监听器,方便后续移除
// video._onVideoEnd = onVideoEnd;
// video.addEventListener('ended', onVideoEnd);
});
}
/**
* 更新左右图标
* @param currentIndex
*/
const updateButtonImages = (currentIndex) => {
// 获取 next 按钮的 img 元素
const nextImgElement = nextImg.value;
const prevImgElement = prevImg.value;
if (currentIndex === 0) {
prevImg.value.src = require('@/assets/img/home/arrow-dis.png');
nextImg.value.src = require('@/assets/img/home/arrow-act.png');
prevImgElement.style.transform = 'rotate(0deg)';
} else if (currentIndex === 3) {
nextImg.value.src = require('@/assets/img/home/arrow-dis.png');
nextImgElement.style.transform = 'rotate(180deg)';
}else{
// 其他情况恢复默认图片
prevImg.value.src = require('@/assets/img/home/arrow-act.png');
nextImg.value.src = require('@/assets/img/home/arrow-act.png');
prevImgElement.style.transform = 'rotate(180deg)';
nextImgElement.style.transform = 'rotate(0deg)';
}
};
/**
* 自动播放视频
*/
const autoPlayCurrentVideo = () => {
const activeSlide = mySwiper.slides[mySwiper.realIndex];
if (activeSlide) {
const video = activeSlide.querySelector('.video-player');
if (video) {
video.play().catch(err => {
console.warn('视频自动播放失败(可能被浏览器策略阻止)', err);
});
}
}
};
onMounted(() => {
// 🟩 初始化 Swiper 并赋值给 mySwiper
mySwiper = new Swiper(swiperContainer.value, {
loop: false,
autoplay: {
delay: 1300,
},
pagination: {
el: pagination.value,
clickable: true,
},
navigation: {
nextEl: nextBtn.value,
prevEl: prevBtn.value,
},
effect: 'fade',
fadeEffect: {
// crossFade: true, // 启用交叉淡出
},
simulateTouch: false, // 禁止滑动切换
on: {
init: () => {
updateButtonImages(0)
addVideoEndedListener(); // 初始化时添加监听器
},
slideChange: () => {
updateButtonImages(mySwiper.realIndex)
autoPlayCurrentVideo(); // 每次切换时播放当前页视频
},
},
});
});
// 在组件卸载时清理监听器
onBeforeUnmount(() => {
const videos = document.querySelectorAll('.video-player');
videos.forEach(video => {
if (video._onVideoEnd) {
video.removeEventListener('ended', video._onVideoEnd);
}
});
});
</script>
<style scoped lang="scss">
p{
margin: 0;
padding: 0;
}
.fs-36{
font-size: 36px;
}
.fs-34{
font-size: 34px;
}
li{
list-style-type: none;
}
.operating-container{
margin-top: 20px;
min-height: 600px;
height: 600px;
.top{
margin-bottom: 40px;
}
&>div:first-child {
text-align: center;
}
.title{
margin-bottom: 5px;
}
.desc{
color: #7F7F81;
}
.operating-item{
.progress{
display: flex;
align-items: baseline;
letter-spacing: 1px;
& :nth-child(1){
color: #70B937;
font-size: 45px;
font-weight: 400;
}
& :nth-child(2){
height: 33px;
}
& :nth-child(3){
color: #000;
font-size: 24px;
font-weight: 500;
}
}
.info{
font-size: 24px;
font-weight: bold;
margin-left: 20px;
white-space: nowrap;
}
}
.desc-item{
font-weight: bold;
font-size: 12px;
color: #000;
margin-left: 5%;
margin-bottom: 40px;
width: max-content;
li{
margin: 20px 0;
justify-content: flex-start;
.block{
width: 8px;
height: 8px;
background-color: #000;
margin-right: 10px;
}
.tag{
font-weight: 500;
font-size: 13px;
color: #2F5EF2;
background-color: #E2E8FA;
border: 1px solid #2F5EF2;
padding: 1px 5px;
border-radius: 6px;
margin-left: 10px
}
}
}
}
:deep(.el-carousel__arrow--right){
border: 1px solid #C1C1C2;
background: transparent;
color: #C1C1C2;
}
:deep(.el-carousel__arrow--left){
border: 1px solid #C1C1C2;
background: transparent;
color: #C1C1C2;
}
:deep(.el-carousel__container) {
height: 100%;
}
.swiper-container {
height: 100%;
width: 95%;
margin: 0 auto;
}
.swiper-slide {
//display: flex;
//align-items: center;
//justify-content: center;
font-size: 24px;
height: 100%;
//position: absolute; /* 必须设置为绝对定位才能实现 fade 切换 */
width: 100%;
//top: 0;
//left: 0;
//transition: opacity 1s ease;
}
/* 自定义按钮样式 */
.custom-swiper-button-prev,
.custom-swiper-button-next {
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 10;
cursor: pointer;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
//background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
}
.custom-swiper-button-prev img,
.custom-swiper-button-next img {
width: 30px;
height: 30px;
filter: brightness(100%);
}
.custom-swiper-button-prev {
left: 0;
}
.custom-swiper-button-next {
right: 0;
}
</style>