浏览代码

style: --

chenlei 7 月之前
父节点
当前提交
e4735d76a4
共有 59 个文件被更改,包括 1384 次插入25 次删除
  1. 0 1
      components.d.ts
  2. 3 0
      package.json
  3. 二进制
      public/favicon/favicon-sea.ico
  4. 二进制
      public/images/sea/Volume btn_off.png
  5. 二进制
      public/images/sea/Volume btn_on.png
  6. 二进制
      public/images/sea/auto-suspend.png
  7. 二进制
      public/images/sea/auto.png
  8. 二进制
      public/images/sea/border.png
  9. 二进制
      public/images/sea/close.png
  10. 二进制
      public/images/sea/dollhouse.png
  11. 二进制
      public/images/sea/enlarge_on.png
  12. 二进制
      public/images/sea/floor.png
  13. 二进制
      public/images/sea/hot-list-bg.jpg
  14. 二进制
      public/images/sea/hotlist-title.png
  15. 二进制
      public/images/sea/hotlist.png
  16. 二进制
      public/images/sea/inside.png
  17. 二进制
      public/images/sea/like.png
  18. 二进制
      public/images/sea/liked.png
  19. 二进制
      public/images/sea/menu-bg.png
  20. 二进制
      public/images/sea/mobile/bg.png
  21. 二进制
      public/images/sea/mobile/hot-bg.jpg
  22. 二进制
      public/images/sea/narrow_off.png
  23. 二进制
      public/images/sea/pause.png
  24. 二进制
      public/images/sea/play.png
  25. 二进制
      public/images/sea/share.png
  26. 二进制
      public/images/sea/view.png
  27. 5 5
      public/js/main_2020_show.js
  28. 4 4
      public/js/manage.js
  29. 二进制
      src/hotspot/assets/images/sea/hot-bg.png
  30. 二进制
      src/hotspot/assets/images/sea/mb-hot-bg.png
  31. 204 0
      src/hotspot/views/hotspot/index.sea.scss
  32. 277 0
      src/hotspot/views/hotspot/index.sea.vue
  33. 1 1
      src/index/app.scss
  34. 二进制
      src/index/assets/images/sea/close.png
  35. 二进制
      src/index/assets/images/sea/hotlist-title.png
  36. 21 0
      src/index/router/index.sea.ts
  37. 6 0
      src/index/utils/index.ts
  38. 二进制
      src/index/views/cover/images/sea/bg.jpg
  39. 二进制
      src/index/views/cover/images/sea/btn.png
  40. 二进制
      src/index/views/cover/images/sea/date.png
  41. 二进制
      src/index/views/cover/images/sea/en-sub-title.png
  42. 二进制
      src/index/views/cover/images/sea/en-title.png
  43. 二进制
      src/index/views/cover/images/sea/logo.png
  44. 二进制
      src/index/views/cover/images/sea/mobile/bg.jpg
  45. 二进制
      src/index/views/cover/images/sea/mobile/info.png
  46. 二进制
      src/index/views/cover/images/sea/mobile/title.png
  47. 二进制
      src/index/views/cover/images/sea/sub-title.png
  48. 二进制
      src/index/views/cover/images/sea/title.png
  49. 72 0
      src/index/views/cover/index.scss
  50. 28 0
      src/index/views/cover/index.vue
  51. 2 14
      src/index/views/home/components/guide/index.scss
  52. 140 0
      src/index/views/home/components/hot-spot-list/index.sea.scss
  53. 27 0
      src/index/views/home/components/hot-spot-list/index.sea.tsx
  54. 171 0
      src/index/views/home/components/menu/index.sea.scss
  55. 100 0
      src/index/views/home/components/menu/index.sea.tsx
  56. 49 0
      src/index/views/home/components/popup/index.sea.scss
  57. 14 0
      src/index/views/home/components/popup/index.sea.tsx
  58. 167 0
      src/index/views/home/components/share-popup/index.sea.vue
  59. 93 0
      src/index/views/home/index.sea.tsx

+ 0 - 1
components.d.ts

@@ -7,7 +7,6 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
-    ElDialog: typeof import('element-plus/es')['ElDialog']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     RouterLink: typeof import('vue-router')['RouterLink']

+ 3 - 0
package.json

@@ -16,6 +16,9 @@
     "serve:ylct": "cross-env VITE_APP_SCENE=ylct VITE_APP_TITLE=家国天下-勇立潮头 VITE_APP_HOT_DOMAIN=./hotspot.html vite",
     "build:ylct:test": "cross-env VITE_APP_SCENE=ylct VITE_APP_TITLE=家国天下-勇立潮头 VITE_APP_HOT_DOMAIN=./hotspot.html run-p type-check \"build-only {@}\" --",
     "push:ylct": "cross-env VITE_APP_SCENE=ylct node ./scripts/publish.js",
+    "serve:sea": "cross-env VITE_APP_SCENE=sea VITE_APP_TITLE=深蓝宝藏 vite",
+    "build:sea:test": "cross-env VITE_APP_SCENE=sea VITE_APP_TITLE=深蓝宝藏 run-p type-check \"build-only {@}\" --",
+    "push:sea": "cross-env VITE_APP_SCENE=sea node ./scripts/publish.js",
     "preview": "vite preview",
     "build-only": "vite build",
     "type-check": "vue-tsc --build --force"

二进制
public/favicon/favicon-sea.ico


二进制
public/images/sea/Volume btn_off.png


二进制
public/images/sea/Volume btn_on.png


二进制
public/images/sea/auto-suspend.png


二进制
public/images/sea/auto.png


二进制
public/images/sea/border.png


二进制
public/images/sea/close.png


二进制
public/images/sea/dollhouse.png


二进制
public/images/sea/enlarge_on.png


二进制
public/images/sea/floor.png


二进制
public/images/sea/hot-list-bg.jpg


二进制
public/images/sea/hotlist-title.png


二进制
public/images/sea/hotlist.png


二进制
public/images/sea/inside.png


二进制
public/images/sea/like.png


二进制
public/images/sea/liked.png


二进制
public/images/sea/menu-bg.png


二进制
public/images/sea/mobile/bg.png


二进制
public/images/sea/mobile/hot-bg.jpg


二进制
public/images/sea/narrow_off.png


二进制
public/images/sea/pause.png


二进制
public/images/sea/play.png


二进制
public/images/sea/share.png


二进制
public/images/sea/view.png


+ 5 - 5
public/js/main_2020_show.js

@@ -6485,7 +6485,7 @@ window.Modernizr = function(n, e, t) {
                             for (var i = 0; i < t.elements.length; i++)
                                 $(t.elements[i]).hide()
                     }
-                je.highlight.visible && $(".pinBottom").addClass("highlightExists"),
+                je.highlight.visible && $(".pinBottom-container").addClass("highlightExists"),
                 je.tourControls.visible === !1 && $("#drawer").addClass("fullWidth"),
                 n()
             }
@@ -6496,7 +6496,7 @@ window.Modernizr = function(n, e, t) {
             }
             function a() {
                 c(),
-                $(".pinBottom").toggleClass("open"),
+                $(".pinBottom-container").toggleClass("open"),
                 $("#drawer").toggleClass("open"),
                 $(".footer").toggleClass("open"),
                 $("#drawer").hasClass("open") ? ($("#pullTab .icon").attr("data-original-title", Re.CLOSE_HIGHLIGHTS),
@@ -6505,7 +6505,7 @@ window.Modernizr = function(n, e, t) {
                 setTimeout(function() {
                     $("#pullTab").toggleClass("opened");
                 }, $("#drawer").hasClass("open") ? 0 : Q.highlightAnimationDuration),
-                $(".pinBottom").hasClass("open") && s($(".vr-popup")) && $(".vr-popup").is(":visible") && Ae.dismiss()
+                $(".pinBottom-container").hasClass("open") && s($(".vr-popup")) && $(".vr-popup").is(":visible") && Ae.dismiss()
             }
             function s(e) {
                 var t;
@@ -6936,7 +6936,7 @@ window.Modernizr = function(n, e, t) {
                 var e = $("#player").width() - 20
                   , t = $("#scroller")
                   , i = $("#drawer")
-                  , n = $(".pinBottom");
+                  , n = $(".pinBottom-container");
                 if ($("#player").width() < 488 || $("#player").height() < 488)
                     t.addClass("hidden"),
                     i.addClass("noScroll"),
@@ -7076,7 +7076,7 @@ window.Modernizr = function(n, e, t) {
                 });
                 var l = $("#play").eq(0)
                   , c = $("#pause").eq(0)
-                  , h = $(".pinBottom").toArray()
+                  , h = $(".pinBottom-container").toArray()
                   , u = $("#drawer").eq(0)
                   , d = $("#playHead").eq(0)
                   , p = $("#progressBar").eq(0)

+ 4 - 4
public/js/manage.js

@@ -2805,10 +2805,10 @@ Manage.prototype.loadAudio = function() { //相关:g_tourAudio \  g_playAudio
         },
         callback:(state)=>{//play或pause时随之触发的函数(即使还没开始播放)
             if(state){
-                $("#volume a img").attr("src", "./images/Volume btn_off.png")
+                $("#volume").addClass('active')
                 $("#volume").attr("title", "关闭声音");
             }else{
-                $("#volume a img").attr("src", "./images/Volume btn_on.png")
+                $("#volume").removeClass('active')
                 $("#volume").attr("title", "打开声音");
             }
         }
@@ -2844,11 +2844,11 @@ Manage.prototype.loadAudio = function() { //相关:g_tourAudio \  g_playAudio
     
     
     $("#volume").find("a").on("click", ()=> {  
-        if($("#volume img")[0].src.indexOf("btn_on.png")>-1)
+        if(!$("#volume").hasClass('active'))
         { 
             this.switchBgmState(true); 
         }
-        else if($("#volume img")[0].src.indexOf("btn_off.png")>-1)
+        else
         {
             this.switchBgmState(false);    
         }

二进制
src/hotspot/assets/images/sea/hot-bg.png


二进制
src/hotspot/assets/images/sea/mb-hot-bg.png


+ 204 - 0
src/hotspot/views/hotspot/index.sea.scss

@@ -0,0 +1,204 @@
+@use '@/assets/utils.scss';
+
+.hotspot-page {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  background: rgba(0, 0, 0, 0.8);
+  z-index: var(--z-index-popper);
+
+  h3 {
+    margin-bottom: 18px;
+    font-size: 48px;
+    font-family: 'Source Han Sans CN-Bold';
+    text-align: center;
+  }
+  .audioIcon {
+    img {
+      width: 57px;
+      height: 57px;
+      cursor: pointer;
+    }
+  }
+  &-info {
+    display: flex;
+    flex-direction: column;
+    margin-top: 37px;
+    width: 835px;
+    color: white;
+    font-size: 18px;
+
+    p {
+      text-indent: 2em;
+    }
+    span {
+      padding-bottom: 20px;
+      font-size: 24px;
+    }
+  }
+
+  &-container {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 60px 0;
+    width: 1591px;
+    height: 824px;
+    background: url('@hotspot/assets/images/sea/hot-bg.png') no-repeat center / 100% 100%;
+    box-sizing: border-box;
+  }
+
+  &-swiper {
+    max-width: 835px;
+    height: 461px;
+
+    &__left,
+    &__right {
+      position: absolute;
+      top: 50%;
+      width: 25px;
+      height: 24px;
+      cursor: pointer;
+      transform: translateY(-50%);
+      z-index: 1;
+    }
+    &__left {
+      left: -70px;
+      background: url('@hotspot/assets/images/icon-previous@2x-min.png') no-repeat center / contain;
+    }
+    &__right {
+      right: -70px;
+      background: url('@hotspot/assets/images/icon-next@2x-min.png') no-repeat center / contain;
+    }
+  }
+  &-model {
+    iframe {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  .swiper-slide {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  &-img {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: inherit;
+  }
+  &-video {
+    video {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  &-nav {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    gap: 10px;
+
+    &__item {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      gap: 9px;
+      width: 57px;
+      height: 57px;
+      box-sizing: border-box;
+      cursor: pointer;
+
+      img {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }
+}
+
+.el-image-viewer__close {
+  right: 150px;
+}
+
+@media only screen and (max-width: 600px) {
+  .el-image-viewer__close {
+    top: 20px;
+    right: 20px;
+    width: 30px;
+    height: 30px;
+  }
+  .el-image-viewer__actions {
+    bottom: utils.vh-calc(140);
+  }
+
+  .hotspot-page {
+    h3 {
+      margin-bottom: utils.vh-calc(30);
+      font-size: 24px;
+    }
+    &-container {
+      margin-bottom: utils.vh-calc(33);
+      padding: utils.vh-calc(200) 15px utils.vh-calc(60);
+      max-width: calc(100% - 36px);
+      width: calc(100% - 36px);
+      height: utils.vh-calc(1390);
+      background-image: url('@hotspot/assets/images/sea/mb-hot-bg.png');
+    }
+    &-info {
+      margin-top: utils.vh-calc(30);
+      width: 100%;
+
+      span {
+        padding-bottom: 10px;
+        font-size: 18px;
+      }
+      p {
+        font-size: 14px;
+      }
+    }
+    &-swiper {
+      max-width: 100%;
+      height: utils.vh-calc(450);
+
+      &__left,
+      &__right {
+        top: unset;
+        bottom: 12px;
+        transform: none;
+      }
+      &__left {
+        left: 14px;
+      }
+      &__right {
+        right: 14px;
+      }
+    }
+    &-nav {
+      bottom: 0;
+
+      &__item {
+        width: 48px;
+        height: 48px;
+      }
+    }
+    .audioIcon {
+      right: 35px;
+      bottom: 1px;
+
+      img {
+        width: 48px;
+        height: 48px;
+      }
+    }
+  }
+}

+ 277 - 0
src/hotspot/views/hotspot/index.sea.vue

@@ -0,0 +1,277 @@
+<template>
+  <div class="hotspot-page">
+    <el-scrollbar class="hotspot-page-container">
+      <h3>{{ myTitle }}</h3>
+
+      <!-- 音频播放器 -->
+      <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"
+      >
+        <SwiperSlide v-for="(item, index) in curList" :key="item.url">
+          <iframe v-if="index === myInd" :src="item" frameborder="0" />
+        </SwiperSlide>
+      </Swiper>
+
+      <!-- 视频页面 -->
+      <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
+          />
+        </template>
+      </div>
+
+      <!-- 图片页面 -->
+      <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"
+            />
+          </div>
+        </SwiperSlide>
+      </Swiper>
+
+      <template v-if="curList.length > 1">
+        <div class="hotspot-page-swiper__left" @click="handlePre" />
+        <div class="hotspot-page-swiper__right" @click="handleNext" />
+      </template>
+
+      <!-- 底部的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)"
+        >
+          <img :class="`${item.type}-icon`" :src="myType === item.type ? item.acIcon : item.icon" />
+          <!-- {{ item.name }}
+          {{ item.type === 'img' ? `${myInd + 1}/${data.img.length}` : '' }} -->
+        </div>
+
+        <!-- 音频图标 -->
+        <div
+          v-if="audio && !isOneAduio"
+          class="audioIcon"
+          :title="audioSta ? '关闭音频' : '打开音频'"
+          @click="audioSta = !audioSta"
+        >
+          <img :src="audioSta ? VolumeOff : VolumeOn" alt="" />
+        </div>
+      </div>
+      <div class="hotspot-page-info">
+        <span>简介</span>
+        <p>{{ myTxt }}</p>
+      </div>
+    </el-scrollbar>
+  </div>
+</template>
+
+<script>
+  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';
+
+  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,
+
+        data: {
+          // 模型数组
+          model: [],
+          // 视频数组
+          video: [],
+          // 图片数组
+          img: [],
+        },
+        // 当前 type
+        myType: '',
+
+        // 当前索引
+        myInd: 0,
+
+        // 底部的tab
+        flooTab: [],
+
+        // 标题
+        myTitle: '',
+        // 内容
+        myTxt: '',
+        // 视频内容
+        videoTxt: [],
+        imgTxt: [],
+
+        // 只有标题和文字(没有视频,没有模型,没有图片)
+        oneTxt: false,
+      };
+    },
+    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();
+      },
+    },
+    mounted() {
+      this.getData();
+    },
+    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';
+
+          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;
+          }
+        }
+      },
+
+      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();
+        }
+      },
+    },
+  };
+</script>
+
+<style lang="scss">
+  @use './index.sea.scss';
+</style>

+ 1 - 1
src/index/app.scss

@@ -128,6 +128,6 @@ iframe {
 @media only screen and (max-width: 600px) {
   :root {
     --design-width: 750;
-    --design-height: 1440;
+    --design-height: 1624;
   }
 }

二进制
src/index/assets/images/sea/close.png


二进制
src/index/assets/images/sea/hotlist-title.png


+ 21 - 0
src/index/router/index.sea.ts

@@ -0,0 +1,21 @@
+import { createRouter, createWebHashHistory, type RouteRecordRaw } from 'vue-router';
+
+const routes: Array<RouteRecordRaw> = [
+  {
+    path: '/',
+    name: 'cover',
+    component: () => import('@/views/cover/index.vue'),
+  },
+  {
+    path: '/home',
+    name: 'home',
+    component: () => import('@/views/home'),
+  },
+];
+
+const router = createRouter({
+  history: createWebHashHistory(import.meta.env.BASE_URL),
+  routes,
+});
+
+export default router;

+ 6 - 0
src/index/utils/index.ts

@@ -19,3 +19,9 @@ export function parseUrlParams(url: string): Record<string, string> {
 
   return params;
 }
+
+export function judgeIsMobile() {
+  return navigator.userAgent.match(
+    /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
+  );
+}

二进制
src/index/views/cover/images/sea/bg.jpg


二进制
src/index/views/cover/images/sea/btn.png


二进制
src/index/views/cover/images/sea/date.png


二进制
src/index/views/cover/images/sea/en-sub-title.png


二进制
src/index/views/cover/images/sea/en-title.png


二进制
src/index/views/cover/images/sea/logo.png


二进制
src/index/views/cover/images/sea/mobile/bg.jpg


二进制
src/index/views/cover/images/sea/mobile/info.png


二进制
src/index/views/cover/images/sea/mobile/title.png


二进制
src/index/views/cover/images/sea/sub-title.png


二进制
src/index/views/cover/images/sea/title.png


+ 72 - 0
src/index/views/cover/index.scss

@@ -0,0 +1,72 @@
+@use '@/assets/utils.scss';
+
+.cover {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  background: url('./images/sea/bg.jpg') no-repeat center / cover;
+
+  &-title {
+    width: utils.vh-calc(1093);
+    height: utils.vh-calc(228);
+  }
+  &-sub-title {
+    margin: utils.vh-calc(46) 0 utils.vh-calc(62);
+    width: utils.vh-calc(1377);
+    height: utils.vh-calc(72);
+  }
+  &-en-title {
+    width: utils.vh-calc(408);
+    height: utils.vh-calc(35);
+  }
+  &-en-sub-title {
+    margin: utils.vh-calc(19) 0 utils.vh-calc(62);
+    width: utils.vh-calc(668);
+    height: utils.vh-calc(79);
+  }
+  &-date {
+    width: utils.vh-calc(964);
+    height: utils.vh-calc(39);
+  }
+  &-btn {
+    margin: utils.vh-calc(86) 0 utils.vh-calc(24);
+    width: utils.vh-calc(310);
+    height: utils.vh-calc(56);
+    cursor: pointer;
+  }
+  &-logo {
+    width: utils.vh-calc(120);
+    height: utils.vh-calc(54);
+  }
+}
+
+.mb-cover {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  background: url('./images/sea/mobile/bg.jpg') no-repeat center bottom / cover;
+
+  &-title {
+    width: utils.vh-calc(238);
+    height: utils.vh-calc(851);
+  }
+  &-sub-title {
+    margin: utils.vh-calc(37) 0 utils.vh-calc(57);
+    width: utils.vh-calc(485);
+    height: utils.vh-calc(467);
+  }
+  &-btn {
+    margin: 0 0 utils.vh-calc(70);
+    width: utils.vh-calc(310);
+    height: utils.vh-calc(56);
+    cursor: pointer;
+  }
+  &-logo {
+    width: utils.vh-calc(120);
+    height: utils.vh-calc(54);
+  }
+}

+ 28 - 0
src/index/views/cover/index.vue

@@ -0,0 +1,28 @@
+<template>
+  <div v-if="!isMobile" class="cover">
+    <img class="cover-title" src="./images/sea/title.png" />
+    <img class="cover-sub-title" src="./images/sea/sub-title.png" />
+    <img class="cover-en-title" src="./images/sea/en-title.png" />
+    <img class="cover-en-sub-title" src="./images/sea/en-sub-title.png" />
+    <img class="cover-date" src="./images/sea/date.png" />
+    <img class="cover-btn" src="./images/sea/btn.png" @click="$router.push({ name: 'home' })" />
+    <img class="cover-logo" src="./images/sea/logo.png" />
+  </div>
+
+  <div v-else class="mb-cover">
+    <img class="mb-cover-title" src="./images/sea/mobile/title.png" />
+    <img class="mb-cover-sub-title" src="./images/sea/mobile/info.png" />
+    <img class="mb-cover-btn" src="./images/sea/btn.png" @click="$router.push({ name: 'home' })" />
+    <img class="mb-cover-logo" src="./images/sea/logo.png" />
+  </div>
+</template>
+
+<script setup>
+  import { judgeIsMobile } from '@/utils';
+
+  const isMobile = judgeIsMobile();
+</script>
+
+<style lang="scss" scoped>
+  @use './index.scss';
+</style>

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

@@ -30,24 +30,15 @@
     height: 130px;
 
     &.noScroll {
-      height: 107px;
+      height: 115px;
     }
   }
 }
 
-#drawer-container.drawerOpen #drawer.open {
-  height: 136px;
-}
-
 #drawer.open.fadeOut {
   pointer-events: none;
 }
 
-#drawer-container.drawerOpen #drawer.open.noScroll,
-#drawer.open.noScroll.playing {
-  height: 113px;
-}
-
 #thumb-container {
   .thumbImg {
     cursor: pointer;
@@ -227,14 +218,11 @@
 @media only screen and (max-width: 487px), (max-height: 487px) {
   #thumb-container .thumbImg img,
   .frame {
-    height: 77px;
+    height: 72px;
   }
   .frame .slidee li {
     width: 103px;
   }
-  #drawer-container.drawerOpen #drawer.open.noScroll {
-    height: 94px;
-  }
   #drawer.open.noScroll,
   #drawer.open.noScroll.playing {
     height: 88px;

+ 140 - 0
src/index/views/home/components/hot-spot-list/index.sea.scss

@@ -0,0 +1,140 @@
+@use '@/assets/utils.scss';
+
+#hotListWrap {
+  display: flex;
+  flex-direction: column;
+  position: absolute;
+  top: 0;
+  right: -400px;
+  width: 330px;
+  max-width: 330px;
+  height: 100%;
+  transition: right 0.4s, width 0.5s;
+  background: url('/images/sea/hot-list-bg.jpg') no-repeat center bottom / 100% 100%;
+  z-index: var(--z-index-popper);
+}
+
+.hotListActive {
+  right: 0 !important;
+}
+
+#hotListTitle {
+  margin: 72px 0 30px;
+  text-align: center;
+}
+
+#hotListContent {
+  width: 100%;
+  /* opacity: 0.65; */
+  flex-grow: 1;
+  height: 100%;
+  overflow-y: scroll;
+  overflow-x: hidden;
+}
+
+#hotListBottom {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 70px 0;
+}
+
+#hotListClose {
+  width: 40px;
+  height: 40px;
+  cursor: pointer;
+}
+
+#hotListContent ul {
+  padding: 0 43px 0 49px;
+  font-size: 20px;
+  letter-spacing: 3px;
+}
+
+#hotListContent ul li {
+  height: 40px;
+  line-height: 40px;
+  color: #ffffff;
+  transition: color 0.3s, background 0.6s;
+  border-radius: 10px;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  cursor: pointer;
+}
+
+#hotListContent ul li:hover {
+  color: white;
+}
+
+#hotListContent ul li.active {
+  color: #ecd2a8;
+}
+
+#hotListText {
+  width: 226px;
+  height: 49px;
+}
+
+#hotListIcon {
+  width: 34px;
+  margin-left: 48px;
+}
+
+#hotListContent::-webkit-scrollbar {
+  width: 6px;
+}
+
+#hotListContent::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  background-color: #979cab;
+}
+
+#hotListContent::-webkit-scrollbar-track {
+  border-radius: 10px;
+}
+
+@media only screen and (max-width: 910px) {
+  .hotListActive + .hotList-mask {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(0, 0, 0, 0.7);
+    z-index: var(--z-index-popper);
+  }
+
+  #hotListWrap {
+    top: -120vh;
+    right: 20px !important;
+    width: calc(100vw - 40px);
+    height: utils.vh-calc(1390);
+    transition: top 0.4s, width 0.5s;
+    z-index: 2001;
+  }
+  .hotListActive {
+    top: utils.vh-calc(80) !important;
+  }
+  #hotListTitle {
+    margin: utils.vh-calc(110) 0 utils.vh-calc(50);
+  }
+  #hotListText {
+    width: utils.vh-calc(260);
+    height: utils.vh-calc(57);
+  }
+  #hotListBottom {
+    position: absolute;
+    left: 50%;
+    bottom: utils.vh-calc(-80);
+    padding: 0;
+    transform: translateX(-50%);
+  }
+  #hotListContent ul {
+    font-size: 18px;
+  }
+  #hotListClose {
+    width: utils.vh-calc(40);
+    height: utils.vh-calc(40);
+  }
+}

+ 27 - 0
src/index/views/home/components/hot-spot-list/index.sea.tsx

@@ -0,0 +1,27 @@
+import { defineComponent } from 'vue';
+import titleImg from '@/assets/images/sea/hotlist-title.png';
+import closeIcon from '@/assets/images/sea/close.png';
+import './index.sea.scss';
+
+export default defineComponent({
+  name: 'HomeHotSpotList',
+  render() {
+    return (
+      <div>
+        <div id="hotListWrap">
+          <div id="hotListTitle">
+            <img id="hotListText" src={titleImg} />
+          </div>
+          <div id="hotListContent">
+            <ul></ul>
+          </div>
+          <div id="hotListBottom">
+            <img id="hotListClose" src={closeIcon} alt="" />
+          </div>
+        </div>
+
+        <div class="hotList-mask" />
+      </div>
+    );
+  },
+});

+ 171 - 0
src/index/views/home/components/menu/index.sea.scss

@@ -0,0 +1,171 @@
+.pinBottom-container {
+  position: absolute;
+  left: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  bottom: 15px;
+  width: 1087px;
+  height: 102px;
+  transition: all 0.5s;
+  transform: translate(-50%);
+  background: url('/images/sea/menu-bg.png') no-repeat center / 100% 100%;
+  z-index: var(--z-index-top);
+
+  &.playing {
+    bottom: 35px;
+  }
+  &.open {
+    bottom: 130px;
+
+    &.playing {
+      bottom: 148px;
+    }
+  }
+  .pinBottom {
+    display: flex;
+    align-items: center;
+    gap: 34px;
+
+    &.left {
+      position: relative;
+      margin-right: 28px;
+      padding-right: 36px;
+
+      &::after {
+        content: '';
+        position: absolute;
+        top: 50%;
+        right: 0;
+        width: 2px;
+        height: 49px;
+        background: url('/images/sea/border.png') no-repeat center / contain;
+        transform: translateY(-50%);
+      }
+    }
+    > div,
+    > div > a {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      font-size: 14px;
+      cursor: pointer;
+
+      &:hover,
+      &.active,
+      &.opened {
+        color: #ecd2a8;
+      }
+      img,
+      .icon {
+        width: 39px;
+        height: 36px;
+      }
+      p {
+        margin-top: 12px;
+      }
+    }
+  }
+}
+
+#pullTab {
+  .icon {
+    background: url('/images/sea/auto.png') no-repeat center / contain;
+  }
+  &.opened .icon {
+    background-image: url('/images/sea/auto-suspend.png');
+  }
+}
+
+#volume {
+  .icon {
+    background: url('/images/sea/Volume btn_on.png') no-repeat center / contain;
+  }
+  &.active .icon {
+    background-image: url('/images/sea/Volume btn_off.png');
+  }
+}
+
+.terms2,
+#vr {
+  display: none !important;
+}
+
+.icon-fullscreen {
+  background: url('/images/sea/enlarge_on.png') no-repeat center / contain;
+}
+.icon-fullscreen-exit {
+  background: url('/images/sea/narrow_off.png') no-repeat center / contain;
+}
+
+@media only screen and (max-width: 600px) {
+  .pinBottom-container {
+    bottom: 0;
+    width: 100%;
+    height: unset;
+    background: none;
+
+    &.playing {
+      bottom: 20px;
+    }
+    &.open {
+      bottom: 88px;
+
+      &.playing {
+        bottom: 108px;
+      }
+    }
+    .pinBottom {
+      gap: 15px;
+
+      &.left {
+        position: absolute;
+        left: 4px;
+        bottom: 0;
+        margin: 0;
+        padding: 28px 0 18px;
+        flex-direction: column;
+        justify-content: center;
+        width: 51px;
+        background: url('/images/sea/mobile/bg.png') no-repeat center top / cover;
+      }
+      &.right {
+        padding: 60px 0 37px;
+        gap: 30px;
+        position: absolute;
+        right: 4px;
+        bottom: 0;
+        flex-direction: column;
+        justify-content: center;
+        width: 51px;
+        background: url('/images/sea/mobile/bg.png') no-repeat center top / cover;
+      }
+      > div,
+      > div > a {
+        font-size: 10px;
+
+        img,
+        .icon {
+          width: 19.5px;
+          height: 18px;
+        }
+        p {
+          margin-top: 3px;
+        }
+      }
+    }
+  }
+}
+
+@media only screen and (max-width: 487px), (max-height: 487px) {
+  .pinBottom-container.drawerOpen.duringTour {
+    bottom: 6px;
+  }
+  #gui .pinBottom.open.noScroll {
+    bottom: 93px;
+  }
+  .pinBottom.open.noScroll.playing {
+    bottom: 108px;
+  }
+}

+ 100 - 0
src/index/views/home/components/menu/index.sea.tsx

@@ -0,0 +1,100 @@
+import { defineComponent } from 'vue';
+import './index.sea.scss';
+
+export default defineComponent({
+  name: 'HomeMenu',
+  render() {
+    return (
+      <div class="pinBottom-container">
+        <div class="pinBottom left">
+          <div id="previous" class="previous desktop-only ui-icon" style="display: none;">
+            <a>
+              <img src="images/sea/play.png" width="24" height="24" data-original-title="播放" />
+            </a>
+          </div>
+          <div id="play" class="ui-icon" data-original-title="自动漫游">
+            <a>
+              <img src="images/sea/play.png" width="24" height="24" />
+              <p>自动漫游</p>
+            </a>
+          </div>
+          <div id="pause" class="ui-icon" style="display: none;">
+            <a>
+              <img title="暂停" src="images/sea/pause.png" width="24" height="24" />
+              <p>自动漫游</p>
+            </a>
+          </div>
+          <div id="next" class="next desktop-only ui-icon wide" style="display: none;">
+            <a>
+              <i title="" class="icon icon-dpad-right" data-original-title="下一个"></i>
+            </a>
+          </div>
+          <div data-original-title="导览" id="pullTab" title="">
+            <i class="icon icon-inside" title="场景导览" />
+            <p>场景导览</p>
+          </div>
+          <div data-original-title="热点列表" id="hotList" title="" style="display: none">
+            <img class="icon icon-inside" src="images/sea/hotlist.png" title="热点列表" />
+            <p>热点列表</p>
+          </div>
+          <div data-original-title="全景漫游" id="gui-modes-inside" title="" class="hidden">
+            <img class="icon icon-inside" src="images/sea/inside.png" title="全景漫游" />
+            <p>全景漫游</p>
+          </div>
+          <div data-original-title="迷你模型" id="gui-modes-dollhouse" title="" class="">
+            <img class="icon icon-inside" src="images/sea/dollhouse.png" title="迷你模型" />
+            <p>迷你模型</p>
+          </div>
+          <div data-original-title="顶部视图" id="gui-modes-floorplan" title="">
+            <img class="icon icon-inside" src="images/sea/floor.png" title="顶部视图" />
+            <p>顶部视图</p>
+          </div>
+          <div
+            data-original-title="消除外壳"
+            id="gui-remove-face"
+            title=""
+            style="display: none; float: left;"
+          >
+            <img class="icon icon-inside" src="images/sea/face.jpg" />
+          </div>
+        </div>
+        <div class="pinBottom right hideTarget">
+          <div id="volume" class="ui-icon wide" style="display: none">
+            <a>
+              <i class="icon icon-inside" />
+              <p>音乐</p>
+            </a>
+          </div>
+          <div id="vr" class="ui-icon wide hidden">
+            <a>
+              <i title="{[{ VIEW_IN_VR }]}" class="icon icon-webvr"></i>
+            </a>
+          </div>
+          <div
+            id="gui-fullscreen"
+            class="ui-icon wide"
+            data-placement="top"
+            title="{[{ VIEW_FULLSCREEN }]}"
+          >
+            <a>
+              <i class="icon icon-fullscreen"></i>
+              <p>全屏</p>
+            </a>
+          </div>
+          <div
+            id="gui-fullscreen-exit"
+            class="ui-icon wide"
+            data-placement="top"
+            title="{[{ EXIT_FULLSCREEN }]}"
+            style="display: none;"
+          >
+            <a>
+              <i class="icon icon-fullscreen-exit"></i>
+              <p>全屏</p>
+            </a>
+          </div>
+        </div>
+      </div>
+    );
+  },
+});

+ 49 - 0
src/index/views/home/components/popup/index.sea.scss

@@ -0,0 +1,49 @@
+@use '@/assets/utils.scss';
+
+#popup {
+  display: none;
+  position: relative;
+  padding: 0;
+  width: 100%;
+  height: 100%;
+  text-align: center;
+  background: rgba(0, 0, 0, 0.6);
+  z-index: var(--z-hot-popper);
+
+  &.wait {
+    opacity: 0.1;
+  }
+}
+#id1 {
+  width: 100%;
+  height: 100%;
+}
+.popup-content {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+}
+#closepop {
+  position: absolute;
+  top: 43px;
+  right: 65px;
+  width: 40px;
+  height: 40px;
+  cursor: pointer;
+  text-indent: -999em;
+  background-size: 100% 100%;
+  background: url('/images/sea/close.png') no-repeat center / contain;
+}
+
+@media only screen and (max-width: 600px) {
+  #closepop {
+    top: unset;
+    left: 50%;
+    right: unset;
+    bottom: utils.vh-calc(70);
+    width: utils.vh-calc(40);
+    height: utils.vh-calc(40);
+    transform: translateX(-50%);
+  }
+}

+ 14 - 0
src/index/views/home/components/popup/index.sea.tsx

@@ -0,0 +1,14 @@
+import { defineComponent } from 'vue';
+import './index.sea.scss';
+
+export default defineComponent({
+  name: 'HomePopup',
+  render() {
+    return (
+      <div id="popup">
+        <div class="popup-content"></div>
+        <div id="closepop">close</div>
+      </div>
+    );
+  },
+});

+ 167 - 0
src/index/views/home/components/share-popup/index.sea.vue

@@ -0,0 +1,167 @@
+<template>
+  <el-dialog class="share-popup" v-model="show" title="分享">
+    <p>请使用手机扫描二维码或 复制分享链接</p>
+
+    <vue-qrcode
+      :value="url"
+      :width="isMobile ? 150 : 180"
+      class="share-popup__qrcode"
+      :color="{}"
+      type="image/jpeg"
+    />
+
+    <div class="share-popup-tools">
+      <div class="share-popup__btn" @click="copyUrl">复制分享链接</div>
+      <div v-if="isMobile" class="share-popup__btn" @click="saveQRCode">保存二维码</div>
+    </div>
+  </el-dialog>
+</template>
+
+<script setup lang="ts">
+  import { computed, ref, watch } from 'vue';
+  import VueQrcode from 'vue-qrcode';
+  import clipboard from 'clipboard';
+  import { storeToRefs } from 'pinia';
+  import useBaseStore from '@/store/module/base';
+
+  const baseStore = useBaseStore();
+  const { manageJsLoaded } = storeToRefs(baseStore);
+  const url = window.location.href;
+  const isMobile = ref(false);
+  const props = defineProps<{
+    visible: boolean;
+  }>();
+  const emits = defineEmits(['update:visible']);
+
+  const show = computed({
+    get() {
+      return props.visible;
+    },
+    set(v) {
+      emits('update:visible', v);
+    },
+  });
+
+  const copyUrl = () => {
+    clipboard.copy(url);
+
+    ElNotification({
+      title: '提示',
+      type: 'success',
+      message: '链接已复制',
+      position: 'bottom-right',
+    });
+  };
+
+  const saveQRCode = () => {
+    const img = document.getElementsByClassName('share-popup__qrcode');
+    if (img && img.length) {
+      const a = document.createElement('a');
+      // @ts-ignore
+      a.href = img[0].src;
+      a.download = '三亚家园.jpg';
+      a.click();
+    }
+  };
+
+  watch(manageJsLoaded, (v) => {
+    if (v) {
+      isMobile.value = window.browser.isMobile();
+    }
+  });
+</script>
+
+<style lang="scss">
+  .share-popup {
+    --el-dialog-width: 420px;
+    --el-dialog-border-radius: 0;
+    --el-dialog-title-font-size: 24px;
+    height: 580px;
+    background: url('./images/bg-share-min.jpg') no-repeat center / contain;
+
+    .el-dialog__header {
+      padding: 50px 40px;
+    }
+    .el-dialog__title {
+      color: #f5dd8c;
+      font-weight: 700;
+    }
+    .el-dialog__body {
+      padding: 0 60px;
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      justify-content: center;
+
+      p {
+        width: 220px;
+        color: white;
+        font-size: 20px;
+        text-align: center;
+      }
+    }
+    .el-dialog__headerbtn {
+      --el-color-info: white;
+      top: 35px;
+      right: 20px;
+      font-size: 26px;
+    }
+    &__qrcode {
+      margin: 25px 0 40px;
+      overflow: hidden;
+      border-radius: 10px;
+    }
+    &__btn {
+      flex: 1;
+      height: 50px;
+      line-height: 50px;
+      text-align: center;
+      color: #9d222d;
+      font-size: 20px;
+      background: #f5dd8c;
+      border-radius: 100px;
+      cursor: pointer;
+    }
+    &-tools {
+      display: flex;
+      align-items: center;
+      gap: 12px;
+      width: 100%;
+    }
+  }
+
+  @media only screen and (max-width: 600px) {
+    .share-popup {
+      --el-dialog-width: 314px;
+      --el-dialog-border-radius: 0;
+      --el-dialog-title-font-size: 16px;
+      height: 433px;
+
+      .el-dialog__header {
+        padding: 30px;
+      }
+      .el-dialog__body {
+        padding: 0 30px;
+
+        p {
+          width: 160px;
+          font-size: 16px;
+        }
+      }
+      .el-dialog__headerbtn {
+        top: 15px;
+        right: 6px;
+        font-size: 23px;
+      }
+      &__qrcode {
+        margin: 18px 0 37px;
+        border-radius: 3px;
+      }
+      &__btn {
+        height: 43px;
+        line-height: 43px;
+        font-size: 16px;
+      }
+    }
+  }
+</style>

+ 93 - 0
src/index/views/home/index.sea.tsx

@@ -0,0 +1,93 @@
+import { defineComponent, ref } from 'vue';
+import JsScript from '@/components/js-script';
+import Title from './components/title';
+import WebVr from './components/web-vr';
+import Other from './components/other';
+import Guide from './components/guide';
+import Vrcon from './components/vrcon';
+import Menu from './components/menu';
+import GuiLoading from './components/gui-loading';
+import Popup from './components/popup';
+import HotSpotList from './components/hot-spot-list';
+import './index.scss';
+
+export default defineComponent({
+  name: 'home',
+  components: {
+    Title,
+    WebVr,
+    Other,
+    Vrcon,
+    GuiLoading,
+    JsScript,
+    Popup,
+  },
+  setup() {
+    const manageJsLoaded = ref(false);
+    const hotJsLoaded = ref(false);
+
+    return {
+      manageJsLoaded,
+      hotJsLoaded,
+    };
+  },
+  render() {
+    return (
+      <div class="home">
+        {/* 进度条加载 */}
+        <GuiLoading />
+
+        {/* 加载初始页面 */}
+        <div id="gui-thumb" />
+
+        {/* 热点弹出框 */}
+        <Popup />
+
+        {/* 场景canvs主容器 */}
+        <div id="player" />
+
+        {/* 底部菜单 */}
+        <div id="gui-parent">
+          {/* 热点气泡 */}
+          <div id="hot" />
+
+          <div id="gui" style="display: none;">
+            {/* 标题 */}
+            <Title />
+
+            {/* 热点列表 */}
+            <HotSpotList />
+
+            {/* 底部菜单 */}
+            <Menu />
+
+            {/* 导览 */}
+            <Guide />
+          </div>
+
+          <WebVr />
+          <Vrcon />
+          <Other />
+        </div>
+
+        {/* TODO: 没有控制权,耦合严重;放在此处为了防止元素未渲染导致报错 */}
+        <JsScript src="./js/manage.js" onLoad={() => (this.manageJsLoaded = true)} />
+        {this.manageJsLoaded && (
+          <div>
+            <JsScript src="./js/Hot.js" onLoad={() => (this.hotJsLoaded = true)} />
+            {this.hotJsLoaded && (
+              <div>
+                <JsScript src="./js/main_2020_show.js" />
+                {/* 延迟加载 */}
+                <JsScript src="./js/lib/player-0.0.12.min.js" />
+                <JsScript src="./js/lib/Tween.js" />
+                <JsScript src="./js/SpecialScene.js" />
+                <JsScript src="./js/loadCAD.js" />
+              </div>
+            )}
+          </div>
+        )}
+      </div>
+    );
+  },
+});