|
|
@@ -1,25 +1,14 @@
|
|
|
<template>
|
|
|
- <div class="hotspot-page">
|
|
|
+ <div class="hotspot-page" v-if="myTitle !== '互动体验'">
|
|
|
<h3>{{ myTitle }}</h3>
|
|
|
|
|
|
<div class="hotspot-page-container">
|
|
|
<!-- 音频播放器 -->
|
|
|
- <audio
|
|
|
- id="myAudio"
|
|
|
- v-if="audio"
|
|
|
- ref="volumeRef"
|
|
|
- v-show="isOneAduio"
|
|
|
- :src="audio"
|
|
|
- controls
|
|
|
- ></audio>
|
|
|
+ <audio id="myAudio" v-if="audio" ref="volumeRef" v-show="isOneAduio" :src="audio" controls></audio>
|
|
|
|
|
|
<!-- 模型页面 -->
|
|
|
- <Swiper
|
|
|
- v-if="myType === 'model'"
|
|
|
- class="hotspot-page-swiper hotspot-page-model"
|
|
|
- @swiper="initSwiper"
|
|
|
- @slideChange="handleChange"
|
|
|
- >
|
|
|
+ <Swiper v-if="myType === 'model'" class="hotspot-page-swiper hotspot-page-model" @swiper="initSwiper"
|
|
|
+ @slideChange="handleChange">
|
|
|
<SwiperSlide v-for="(item, index) in curList" :key="item.url">
|
|
|
<iframe v-if="index === myInd" :src="item" frameborder="0" />
|
|
|
</SwiperSlide>
|
|
|
@@ -28,35 +17,17 @@
|
|
|
<!-- 视频页面 -->
|
|
|
<div v-if="myType === 'video'" class="hotspot-page-swiper hotspot-page-video">
|
|
|
<template v-for="(item, index) in curList" :key="item.url">
|
|
|
- <video
|
|
|
- v-if="index === myInd"
|
|
|
- id="videoID"
|
|
|
- class="hotspot-page-video"
|
|
|
- controls
|
|
|
- :src="item.url"
|
|
|
- autoplay
|
|
|
- />
|
|
|
+ <video v-if="index === myInd" id="videoID" class="hotspot-page-video" controls :src="item.url" autoplay />
|
|
|
</template>
|
|
|
</div>
|
|
|
|
|
|
<!-- 图片页面 -->
|
|
|
- <Swiper
|
|
|
- v-if="myType === 'img'"
|
|
|
- class="hotspot-page-swiper hotspot-page-img-swiper"
|
|
|
- @swiper="initSwiper"
|
|
|
- @slideChange="handleChange"
|
|
|
- >
|
|
|
+ <Swiper v-if="myType === 'img'" class="hotspot-page-swiper hotspot-page-img-swiper" @swiper="initSwiper"
|
|
|
+ @slideChange="handleChange">
|
|
|
<SwiperSlide v-for="(item, idx) in curList" :key="item">
|
|
|
<div class="hotspot-page-img">
|
|
|
- <el-image
|
|
|
- :src="item"
|
|
|
- fit="contain"
|
|
|
- style="width: 100%; height: 100%"
|
|
|
- preview-teleported
|
|
|
- :preview-src-list="curList"
|
|
|
- :initial-index="idx"
|
|
|
- @contextmenu.native.prevent
|
|
|
- />
|
|
|
+ <el-image :src="item" fit="contain" style="width: 100%; height: 100%" preview-teleported
|
|
|
+ :preview-src-list="curList" :initial-index="idx" @contextmenu.native.prevent />
|
|
|
</div>
|
|
|
</SwiperSlide>
|
|
|
</Swiper>
|
|
|
@@ -68,17 +39,12 @@
|
|
|
|
|
|
<!-- 底部的tab -->
|
|
|
<div v-if="flooTab.length > 1" class="hotspot-page-nav">
|
|
|
- <div
|
|
|
- v-for="item in flooTab"
|
|
|
- :key="item.id"
|
|
|
- :class="[
|
|
|
- 'hotspot-page-nav__item',
|
|
|
- {
|
|
|
- active: myType === item.type,
|
|
|
- },
|
|
|
- ]"
|
|
|
- @click="handleTab(item)"
|
|
|
- >
|
|
|
+ <div v-for="item in flooTab" :key="item.id" :class="[
|
|
|
+ 'hotspot-page-nav__item',
|
|
|
+ {
|
|
|
+ active: myType === item.type,
|
|
|
+ },
|
|
|
+ ]" @click="handleTab(item)">
|
|
|
<img :class="`${item.type}-icon`" :src="myType === item.type ? item.acIcon : item.icon" />
|
|
|
<!-- {{ item.name }}
|
|
|
{{ item.type === 'img' ? `${myInd + 1}/${data.img.length}` : '' }} -->
|
|
|
@@ -86,12 +52,8 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 音频图标 -->
|
|
|
- <div
|
|
|
- v-if="audio && !isOneAduio"
|
|
|
- class="audioIcon"
|
|
|
- :title="audioSta ? '关闭音频' : '打开音频'"
|
|
|
- @click="audioSta = !audioSta"
|
|
|
- >
|
|
|
+ <div v-if="audio && !isOneAduio" class="audioIcon" :title="audioSta ? '关闭音频' : '打开音频'"
|
|
|
+ @click="audioSta = !audioSta">
|
|
|
<img :src="audioSta ? VolumeOff : VolumeOn" alt="" />
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -100,179 +62,240 @@
|
|
|
<div class="hotspot-page-info" v-html="myTxt"></div>
|
|
|
</el-scrollbar>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div class="hotspot-page-QA" v-if="myTitle === '互动体验'">
|
|
|
+ <div class="hotspot-page-QA-scroll">
|
|
|
+ <div class="hotspot-page-QA-list" v-for="(item, index) in QAList" :key="item.question">
|
|
|
+ <div class="hotspot-page-QA-list-question">{{ index + 1 }}.{{ item.question }}</div>
|
|
|
+ <div class="hotspot-page-QA-list-answer" v-if="item.isShow">答案:{{ item.answer }}</div>
|
|
|
+ <div class="hotspot-page-QA-list-button" v-else @click="handleQA(item)">答案</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
- import { Swiper, SwiperSlide } from 'swiper/vue';
|
|
|
- import 'swiper/css';
|
|
|
- import { parseUrlParams } from '@/utils';
|
|
|
+import { Swiper, SwiperSlide } from 'swiper/vue'
|
|
|
+import 'swiper/css'
|
|
|
+import { parseUrlParams } from '@/utils'
|
|
|
|
|
|
- import ModelIcon from '@hotspot/assets/images/icon-model@2x.png';
|
|
|
- import AcModelIcon from '@hotspot/assets/images/icon-model-1@2x.png';
|
|
|
- import ImageIcon from '@hotspot/assets/images/icon-image@2x.png';
|
|
|
- import AcImageIcon from '@hotspot/assets/images/icon-image-1@2x.png';
|
|
|
- import VideoIcon from '@hotspot/assets/images/icon-video@2x.png';
|
|
|
- import AcVideoIcon from '@hotspot/assets/images/icon-video-1@2x.png';
|
|
|
- import VolumeOn from '@hotspot/assets/images/Volume-on.png';
|
|
|
- import VolumeOff from '@hotspot/assets/images/Volume-off.png';
|
|
|
+import ModelIcon from '@hotspot/assets/images/icon-model@2x.png'
|
|
|
+import AcModelIcon from '@hotspot/assets/images/icon-model-1@2x.png'
|
|
|
+import ImageIcon from '@hotspot/assets/images/icon-image@2x.png'
|
|
|
+import AcImageIcon from '@hotspot/assets/images/icon-image-1@2x.png'
|
|
|
+import VideoIcon from '@hotspot/assets/images/icon-video@2x.png'
|
|
|
+import AcVideoIcon from '@hotspot/assets/images/icon-video-1@2x.png'
|
|
|
+import VolumeOn from '@hotspot/assets/images/Volume-on.png'
|
|
|
+import VolumeOff from '@hotspot/assets/images/Volume-off.png'
|
|
|
|
|
|
- const urlParams = parseUrlParams(window.location.href);
|
|
|
+const urlParams = parseUrlParams(window.location.href)
|
|
|
|
|
|
- export default {
|
|
|
- name: 'hotspot',
|
|
|
- components: {
|
|
|
- Swiper,
|
|
|
- SwiperSlide,
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- VolumeOn,
|
|
|
- VolumeOff,
|
|
|
- m: urlParams.m,
|
|
|
- id: urlParams.id,
|
|
|
- // 音频地址
|
|
|
- audio: '',
|
|
|
- // 如果只有单独的音频
|
|
|
- isOneAduio: false,
|
|
|
- // 音频状态
|
|
|
- audioSta: false,
|
|
|
+export default {
|
|
|
+ name: 'hotspot',
|
|
|
+ components: {
|
|
|
+ Swiper,
|
|
|
+ SwiperSlide,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ VolumeOn,
|
|
|
+ VolumeOff,
|
|
|
+ m: urlParams.m,
|
|
|
+ id: urlParams.id,
|
|
|
+ // 音频地址
|
|
|
+ audio: '',
|
|
|
+ // 如果只有单独的音频
|
|
|
+ isOneAduio: false,
|
|
|
+ // 音频状态
|
|
|
+ audioSta: false,
|
|
|
|
|
|
- data: {
|
|
|
- // 模型数组
|
|
|
- model: [],
|
|
|
- // 视频数组
|
|
|
- video: [],
|
|
|
- // 图片数组
|
|
|
- img: [],
|
|
|
- },
|
|
|
- // 当前 type
|
|
|
- myType: '',
|
|
|
+ data: {
|
|
|
+ // 模型数组
|
|
|
+ model: [],
|
|
|
+ // 视频数组
|
|
|
+ video: [],
|
|
|
+ // 图片数组
|
|
|
+ img: [],
|
|
|
+ },
|
|
|
+ // 当前 type
|
|
|
+ myType: '',
|
|
|
|
|
|
- // 当前索引
|
|
|
- myInd: 0,
|
|
|
+ // 当前索引
|
|
|
+ myInd: 0,
|
|
|
|
|
|
- // 底部的tab
|
|
|
- flooTab: [],
|
|
|
+ // 底部的tab
|
|
|
+ flooTab: [],
|
|
|
|
|
|
- // 标题
|
|
|
- myTitle: '',
|
|
|
- // 内容
|
|
|
- myTxt: '',
|
|
|
- // 视频内容
|
|
|
- videoTxt: [],
|
|
|
- imgTxt: [],
|
|
|
+ // 标题
|
|
|
+ myTitle: '',
|
|
|
+ // 内容
|
|
|
+ myTxt: '',
|
|
|
+ // 视频内容
|
|
|
+ videoTxt: [],
|
|
|
+ imgTxt: [],
|
|
|
|
|
|
- // 只有标题和文字(没有视频,没有模型,没有图片)
|
|
|
- oneTxt: false,
|
|
|
- };
|
|
|
+ // 只有标题和文字(没有视频,没有模型,没有图片)
|
|
|
+ oneTxt: false,
|
|
|
+ // 问答列表
|
|
|
+ QAList: [
|
|
|
+ {
|
|
|
+ question: '五卅惨案为什么叫五卅?',
|
|
|
+ answer: '卅字读作sà,在阿拉伯数字普及推广之前,中国人习惯用卅指代三十,就像廿指代二十一样。这场运动是五月三十日爆发的,为了纪念这个日子而命名,所以才叫五卅运动。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '五卅运动的导火索是什么?',
|
|
|
+ answer: '顾正红惨案。1925年5月15日,上海日商纱厂工人顾正红因组织罢工抗议日本监工暴行,被日本资本家枪杀,这一事件激起了全国人民的愤怒,成为五卅运动的导火索。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '五卅运动中,中国共产党创办的第一份日报是什么?',
|
|
|
+ answer: '《热血日报》。这份报纸1925年6月4日创刊于上海,6月27日被迫停刊,共出版24期,主编瞿秋白,是中国共产党领导“五卅运动”的机关报,也是迄今能看到的中国共产党出版的第一份日报。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '五卅运动的发生地是在哪里?',
|
|
|
+ answer: '上海。五卅运动最初在上海爆发,随后迅速扩展到全国,席卷近600座城镇,有1700万人自觉地投入斗争的洪流。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '五卅运动中的“三罢”斗争指的是什么?',
|
|
|
+ answer: '工人罢工、学生罢课、商人罢市。这是五卅运动中工人、学生、商人联合采取的斗争形式,形成了强大的反帝爱国统一战线。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '上海工商学联合会的成立对五卅运动的意义是什么?',
|
|
|
+ answer: '工商学联合会的成立,不仅协调了工人、学生、商人的斗争,还为中国共产党领导统一战线提供了重要经验,成为五卅运动成功的关键因素之一。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '上海总工会的主要领导人有谁?',
|
|
|
+ answer: '李立三、刘少奇等。李立三担任上海总工会委员长,刘少奇担任总务科主任,他们在五卅运动中发挥了重要的领导作用。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ question: '五卅运动中,青年学生的作用是什么?',
|
|
|
+ answer: '青年学生是五卅运动的先锋队和宣传队,通过罢课、示威游行、散发传单等方式推动运动发展。青年学生的热血与激情为五卅运动注入了强大活力,唤醒了民众的爱国热情。',
|
|
|
+ isShow: false,
|
|
|
+ },
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ curList() {
|
|
|
+ return this.data[this.myType] || []
|
|
|
},
|
|
|
- computed: {
|
|
|
- curList() {
|
|
|
- return this.data[this.myType] || [];
|
|
|
- },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ audioSta(val) {
|
|
|
+ if (val) {
|
|
|
+ this.$refs.volumeRef.play()
|
|
|
+ this.$refs.volumeRef.onended = () => {
|
|
|
+ // console.log("----音频播放完毕");
|
|
|
+ this.audioSta = false
|
|
|
+ }
|
|
|
+ } else this.$refs.volumeRef.pause()
|
|
|
},
|
|
|
- watch: {
|
|
|
- audioSta(val) {
|
|
|
- if (val) {
|
|
|
- this.$refs.volumeRef.play();
|
|
|
- this.$refs.volumeRef.onended = () => {
|
|
|
- // console.log("----音频播放完毕");
|
|
|
- this.audioSta = false;
|
|
|
- };
|
|
|
- } else this.$refs.volumeRef.pause();
|
|
|
- },
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.getData()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handleQA(item) {
|
|
|
+ item.isShow = !item.isShow
|
|
|
},
|
|
|
- mounted() {
|
|
|
- this.getData();
|
|
|
+ sendMessageToParent(msg) {
|
|
|
+ window.parent.postMessage(msg, '*') // '*' 表示接受来自任何源的消息
|
|
|
},
|
|
|
- methods: {
|
|
|
- async getData() {
|
|
|
- // https://www.4dmodel.com/
|
|
|
- let url = `https://super.4dage.com/data/${this.id}/hot/js/data.js?time=${Math.random()}`;
|
|
|
- let result = await fetch(url).then((response) => response.json());
|
|
|
- const resData = result[this.m];
|
|
|
- console.log('----', resData);
|
|
|
- if (resData) {
|
|
|
- this.audio = resData.backgroundMusic;
|
|
|
- // 只有单独的音频上传
|
|
|
- if (resData.backgroundMusic && !resData.model && !resData.video && !resData.images) {
|
|
|
- this.isOneAduio = true;
|
|
|
- }
|
|
|
- // 底部的tab
|
|
|
- const arr = [];
|
|
|
- const obj = {};
|
|
|
- if (resData.model) {
|
|
|
- obj.model = resData.model;
|
|
|
- arr.push({ id: 1, type: 'model', name: '模型', icon: ModelIcon, acIcon: AcModelIcon });
|
|
|
- }
|
|
|
- if (resData.video) {
|
|
|
- obj.video = resData.video;
|
|
|
- arr.push({ id: 2, type: 'video', name: '视频', icon: VideoIcon, acIcon: AcVideoIcon });
|
|
|
- } else {
|
|
|
- this.$nextTick(() => {
|
|
|
- if (
|
|
|
- !window.navigator.userAgent.match(
|
|
|
- /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
|
|
|
- )
|
|
|
- ) {
|
|
|
- this.audioSta = true;
|
|
|
- this.$refs.volumeRef.play();
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- if (resData.images) {
|
|
|
- obj.img = resData.images;
|
|
|
- arr.push({ id: 3, type: 'img', name: '图片', icon: ImageIcon, acIcon: AcImageIcon });
|
|
|
- }
|
|
|
- this.flooTab = arr;
|
|
|
- this.data = obj;
|
|
|
|
|
|
- // 当前type的值 应该为
|
|
|
- if (resData.model) this.myType = 'model';
|
|
|
- else if (resData.video) this.myType = 'video';
|
|
|
- else if (resData.images) this.myType = 'img';
|
|
|
+ async getData() {
|
|
|
+ // https://www.4dmodel.com/
|
|
|
+ let url = `https://super.4dage.com/data/${this.id}/hot/js/data.js?time=${Math.random()}`
|
|
|
+ let result = await fetch(url).then((response) => response.json())
|
|
|
+ const resData = result[this.m]
|
|
|
+ console.log('----', resData)
|
|
|
+ if (resData) {
|
|
|
+ this.sendMessageToParent(resData.title) // 发送消息给父级
|
|
|
+ this.audio = resData.backgroundMusic
|
|
|
+ // 只有单独的音频上传
|
|
|
+ if (resData.backgroundMusic && !resData.model && !resData.video && !resData.images) {
|
|
|
+ this.isOneAduio = true
|
|
|
+ }
|
|
|
+ // 底部的tab
|
|
|
+ const arr = []
|
|
|
+ const obj = {}
|
|
|
+ if (resData.model) {
|
|
|
+ obj.model = resData.model
|
|
|
+ arr.push({ id: 1, type: 'model', name: '模型', icon: ModelIcon, acIcon: AcModelIcon })
|
|
|
+ }
|
|
|
+ if (resData.video) {
|
|
|
+ obj.video = resData.video
|
|
|
+ arr.push({ id: 2, type: 'video', name: '视频', icon: VideoIcon, acIcon: AcVideoIcon })
|
|
|
+ } else {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (
|
|
|
+ !window.navigator.userAgent.match(
|
|
|
+ /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
|
|
|
+ )
|
|
|
+ ) {
|
|
|
+ this.audioSta = true
|
|
|
+ this.$refs.volumeRef.play()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if (resData.images) {
|
|
|
+ obj.img = resData.images
|
|
|
+ arr.push({ id: 3, type: 'img', name: '图片', icon: ImageIcon, acIcon: AcImageIcon })
|
|
|
+ }
|
|
|
+ this.flooTab = arr
|
|
|
+ this.data = obj
|
|
|
+
|
|
|
+ // 当前type的值 应该为
|
|
|
+ if (resData.model) this.myType = 'model'
|
|
|
+ else if (resData.video) this.myType = 'video'
|
|
|
+ else if (resData.images) this.myType = 'img'
|
|
|
|
|
|
- this.myTitle = resData.title || '';
|
|
|
- this.myTxt = resData.content || '';
|
|
|
- this.videoTxt = resData.videosDesc || [];
|
|
|
- this.imgTxt = resData.imagesDesc || [];
|
|
|
+ this.myTitle = resData.title || ''
|
|
|
+ this.myTxt = resData.content || ''
|
|
|
+ this.videoTxt = resData.videosDesc || []
|
|
|
+ this.imgTxt = resData.imagesDesc || []
|
|
|
|
|
|
- // 只有 标题和 文字介绍(没有视频,没有模型,没有图片)
|
|
|
- if (!obj.model && !obj.video && !obj.img && !resData.backgroundMusic) {
|
|
|
- this.oneTxt = true;
|
|
|
- }
|
|
|
+ // 只有 标题和 文字介绍(没有视频,没有模型,没有图片)
|
|
|
+ if (!obj.model && !obj.video && !obj.img && !resData.backgroundMusic) {
|
|
|
+ this.oneTxt = true
|
|
|
}
|
|
|
- },
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- handleTab(item) {
|
|
|
- this.myInd = 0;
|
|
|
- this.myType = item.type;
|
|
|
- },
|
|
|
+ handleTab(item) {
|
|
|
+ this.myInd = 0
|
|
|
+ this.myType = item.type
|
|
|
+ },
|
|
|
|
|
|
- initSwiper(swiper) {
|
|
|
- this.swiper = swiper;
|
|
|
- },
|
|
|
- handleChange({ activeIndex }) {
|
|
|
- this.myInd = activeIndex;
|
|
|
- },
|
|
|
- handlePre() {
|
|
|
- if (this.myType === 'video') {
|
|
|
- this.myInd = this.myInd > 0 ? this.myInd - 1 : this.curList.length - 1;
|
|
|
- } else {
|
|
|
- this.swiper?.slidePrev();
|
|
|
- }
|
|
|
- },
|
|
|
- handleNext() {
|
|
|
- if (this.myType === 'video') {
|
|
|
- this.myInd = this.myInd < this.curList.length - 1 ? this.myInd + 1 : 0;
|
|
|
- } else {
|
|
|
- this.swiper?.slideNext();
|
|
|
- }
|
|
|
- },
|
|
|
+ initSwiper(swiper) {
|
|
|
+ this.swiper = swiper
|
|
|
+ },
|
|
|
+ handleChange({ activeIndex }) {
|
|
|
+ this.myInd = activeIndex
|
|
|
+ },
|
|
|
+ handlePre() {
|
|
|
+ if (this.myType === 'video') {
|
|
|
+ this.myInd = this.myInd > 0 ? this.myInd - 1 : this.curList.length - 1
|
|
|
+ } else {
|
|
|
+ this.swiper?.slidePrev()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleNext() {
|
|
|
+ if (this.myType === 'video') {
|
|
|
+ this.myInd = this.myInd < this.curList.length - 1 ? this.myInd + 1 : 0
|
|
|
+ } else {
|
|
|
+ this.swiper?.slideNext()
|
|
|
+ }
|
|
|
},
|
|
|
- };
|
|
|
+ },
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
|
- @use './index.wsyd.scss';
|
|
|
+@use './index.wsyd.scss';
|
|
|
</style>
|