lanxin 7 ay önce
ebeveyn
işleme
24654c32a2

BIN
src/hotspot/assets/images/hot-bg-QA.png


+ 69 - 0
src/hotspot/views/hotspot/index.wsyd.scss

@@ -12,6 +12,7 @@
   z-index: var(--z-index-popper);
 
   h3 {
+    text-align: center;
     padding: 22px 10px 10px;
     font-family: 'Source Han Sans CN-Bold';
     font-size: 48px;
@@ -134,6 +135,52 @@
   }
 }
 
+.hotspot-page-QA {
+  height: 95%;
+  background: url('@hotspot/assets/images/hot-bg-QA.png') no-repeat center / cover;
+  display: flex;
+ 
+  padding: 30px;
+  padding-top: 50px;
+  &-scroll {
+    display: flex;
+    width: 100%;
+    height: 100%;
+    align-items: center;
+    justify-content: space-between;
+    flex-wrap: wrap;
+  }
+  &-list {
+    width: 48%;
+    height: 23%;
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    &-question {
+      color: #b21e26;
+      font-size: 20px;
+    }
+    &-answer {
+      width: 100%;
+      height: 100%;
+      font-size: 16px;
+      color: rgba(178, 30, 38, 0.8);
+      text-align: justify;
+    }
+    &-button {
+      width: 65px;
+      height: 30px;
+      font-size: 16px;
+      border-radius: 5px;
+      background: #b21e26;
+      color: rgba(255, 255, 255, 0.8);
+      text-align: center;
+      line-height: 30px;
+      cursor: pointer;
+    }
+  }
+}
+
 @media only screen and (max-width: 600px) {
   .hotspot-page {
     padding-left: 0;
@@ -188,4 +235,26 @@
       }
     }
   }
+
+  .hotspot-page-QA {
+    padding: 10px 5px;
+    height: 100%;
+    &-scroll {
+      height: 100%;
+      padding: 10px 15px;
+      overflow: auto;
+      &::-webkit-scrollbar {
+        width: 2px;
+        background-color: rgba(178, 30, 38, 0.2);
+      }
+      &::-webkit-scrollbar-thumb {
+        background: #b21e26;
+        border-radius: 2px;
+      }
+    }
+    &-list {
+      width: 100%;
+      height: 38%;
+    }
+  }
 }

+ 228 - 205
src/hotspot/views/hotspot/index.wsyd.vue

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

BIN
src/index/assets/images/wsyd/close-QA.png


BIN
src/index/assets/images/wsyd/mobile/closeM-QA.png


BIN
src/index/assets/images/wsyd/mobile/hotM-bg-QA.png


+ 2 - 1
src/index/views/home/components/guide/index.scss

@@ -70,7 +70,7 @@
 }
 
 .frame .slidee li {
-  width: 136px;
+  width: 145px;
   margin: 0 12px 0 0;
   position: relative;
 }
@@ -213,6 +213,7 @@
   #thumb-container .thumbImg img,
   .frame {
     height: 70px;
+    justify-content: left;
   }
   .frame .slidee li {
     width: 103px;

+ 20 - 0
src/index/views/home/components/popup/index.wsyd.scss

@@ -17,6 +17,9 @@
     transform: translate(-50%, -50%);
     background: url('@/assets/images/wsyd/hot-bg.png') no-repeat center / contain;
   }
+  .popup-wrap-QA {
+    background: none;
+  }
   &.wait {
     opacity: 0.1;
   }
@@ -41,6 +44,16 @@
   text-indent: -999em;
   background: url('@/assets/images/wsyd/sidebar-close-min.png') no-repeat center / contain;
 }
+#closepop-QA {
+  position: absolute;
+  top: 17px;
+  right: 22px;
+  width: 45px;
+  height: 45px;
+  cursor: pointer;
+  text-indent: -999em;
+  background: url('@/assets/images/wsyd/close-QA.png') no-repeat center / contain;
+}
 
 @media only screen and (max-width: 600px) {
   #popup {
@@ -57,4 +70,11 @@
     width: 35px;
     height: 35px;
   }
+  #closepop-QA {
+    top: 96%;
+    right: 50%;
+    transform: translate(50%, 0);
+    width: 45px;
+    height: 45px;
+  }
 }

+ 24 - 5
src/index/views/home/components/popup/index.wsyd.tsx

@@ -1,14 +1,33 @@
-import { defineComponent } from 'vue';
+import { defineComponent, ref, onMounted, onBeforeUnmount } from 'vue';
 import './index.wsyd.scss';
 
 export default defineComponent({
   name: 'HomePopup',
-  render() {
-    return (
+  setup() {
+    const isQA = ref(false); // 使用 ref 来管理状态
+
+    const receiveMessageFromChild = (event: MessageEvent) => {
+      const msg = event.data;
+      if (msg === '互动体验') {
+        isQA.value = true; // 更新状态
+      } else {
+        isQA.value = false;
+      }
+    };
+
+    onMounted(() => {
+      window.addEventListener('message', receiveMessageFromChild);
+    });
+
+    onBeforeUnmount(() => {
+      window.removeEventListener('message', receiveMessageFromChild);
+    });
+
+    return () => (
       <div id="popup">
-        <div class="popup-wrap">
+        <div class={['popup-wrap', isQA.value && 'popup-wrap-QA']}>
           <div class="popup-content"></div>
-          <div id="closepop">close</div>
+          <div id={isQA.value ? 'closepop-QA' : 'closepop'}>close</div>
         </div>
       </div>
     );