Browse Source

style: --

chenlei 1 year ago
parent
commit
2a4905d05e
43 changed files with 586 additions and 214 deletions
  1. 4 4
      public/relic-data/data.json
  2. 1 1
      public/sceneTree.js
  3. 67 22
      src/App.vue
  4. BIN
      src/assets/images/CameraContent-1-2-3-img-1.jpg
  5. BIN
      src/assets/images/CameraContent-1-2-3-img-2.jpg
  6. BIN
      src/assets/images/CameraContent-1-2-3-img-3.jpg
  7. BIN
      src/assets/images/CameraContent-1-2-3-img-4.jpg
  8. BIN
      src/assets/images/CameraContent-1-2-3-img-5.jpg
  9. BIN
      src/assets/images/CameraContent-1-2-3-img-6.jpg
  10. BIN
      src/assets/images/CameraContent-1-2-3-img-7.jpg
  11. BIN
      src/assets/images/CameraContent-3-1-3-img-6.png
  12. BIN
      src/assets/images/btn_restart-min.png
  13. BIN
      src/assets/images/camera-content-1-1-3-img.jpg
  14. BIN
      src/assets/images/camera-content-1-1-3-img.png
  15. BIN
      src/assets/images/camera-content-2-3-1-img-2.png
  16. BIN
      src/assets/images/camera-content-2-3-2-tab-5-img.png
  17. 40 5
      src/components/CameraContent-1-1-1.vue
  18. 2 11
      src/components/CameraContent-1-1-2.vue
  19. 2 3
      src/components/CameraContent-1-1-3.vue
  20. 5 1
      src/components/CameraContent-1-2-1.vue
  21. 93 24
      src/components/CameraContent-1-2-3.vue
  22. 11 15
      src/components/CameraContent-1-3-1.vue
  23. 31 1
      src/components/CameraContent-1-3-2.vue
  24. 22 16
      src/components/CameraContent-1-3-3.vue
  25. 11 12
      src/components/CameraContent-2-1-1.vue
  26. 2 1
      src/components/CameraContent-2-1-2.vue
  27. 23 7
      src/components/CameraContent-2-1-3.vue
  28. 4 4
      src/components/CameraContent-2-2-1.vue
  29. 21 3
      src/components/CameraContent-2-3-2.vue
  30. 27 13
      src/components/CameraContent-3-1-1.vue
  31. 6 12
      src/components/CameraContent-3-2-1.vue
  32. 2 2
      src/components/CameraContent-3-2-3.vue
  33. 2 1
      src/components/HotspotDialog-1.vue
  34. 4 7
      src/components/MutiRelicHotSpot.vue
  35. 30 40
      src/components/StartUp.vue
  36. 3 0
      src/components/UserGuide.vue
  37. 119 0
      src/hooks/usePreloader.js
  38. 3 0
      src/main.js
  39. 1 0
      src/preloadList.js
  40. 4 7
      src/views/HomeView.vue
  41. 7 2
      src/views/PanoView.vue
  42. 25 0
      src/views/RelicList.vue
  43. 14 0
      src/views/ShipGame/ShipGameView.vue

File diff suppressed because it is too large
+ 4 - 4
public/relic-data/data.json


+ 1 - 1
public/sceneTree.js

@@ -69,7 +69,7 @@ export default [
         `,
         contentPageBtnNameList: [
           '菏泽沉船',
-          '磁县漕船',
+          '运河上的船',
           '聊城古船',
         ],
       },

+ 67 - 22
src/App.vue

@@ -11,6 +11,7 @@
             draggable="false"
           >
           <span>请横屏浏览</span>
+          <span v-if="$isMobile && $isWeChat && $uaInfo.os.name === 'Android'">请确认微信-通用“开启横屏模式”按钮是否开启</span>
         </div>
       </div>
     </Teleport>
@@ -27,19 +28,45 @@
       @click="store.dispatch('closeIframePage')"
     >
     <iframe
+      v-if="!$isMobile || (!store.state.iframeAttrs.portrait || (store.state.iframeAttrs.portrait && isPortrait))"
       :src="store.state.iframeAttrs.url"
       :style="store.state.iframeAttrs.style"
     />
+
+    <div
+      v-if="store.state.iframeAttrs.portrait && $isMobile"
+      class="screen-rotate-tip portrait"
+    >
+      <div class="inner-wrapper">
+        <img
+          class=""
+          src="@/assets/images/tip-screen-rotate.png"
+          alt=""
+          draggable="false"
+        >
+        <span>请竖屏浏览</span>
+      </div>
+    </div>
   </div>
 </template>
 
 <script setup>
-import { provide, inject } from 'vue'
+import { provide, inject, ref } from 'vue'
 import { useStore } from "vuex"
 import { useRouter } from "vue-router"
 
 const store = useStore()
 const router = useRouter()
+const {
+  windowSizeInCssForRef,
+  windowSizeWhenDesignForRef,
+} = useSizeAdapt(1920, 970)
+const isPortrait = ref(false)
+
+window.addEventListener("resize", () => {
+  console.log(window.innerWidth)
+  isPortrait.value = window.innerWidth < window.innerHeight
+})
 
 /**
  * 背景音乐
@@ -123,13 +150,14 @@ router.beforeEach((to, from) => {
   sessionStorage.setItem(HISTORY_KEY, JSON.stringify(cache))
 })
 
+const $uaInfo = inject('$uaInfo')
 const $isMobile = inject('$isMobile')
+const $isWeChat = inject('$isWeChat')
 const fakeBack = () => {
   if ($isMobile) {
     const cache = sessionStorage.getItem(HISTORY_KEY) ? JSON.parse(sessionStorage.getItem(HISTORY_KEY)) : []
     if (cache.length) {
       const info = cache.pop()
-      console.log(info)
       router.replace(info).then(() => {
         sessionStorage.setItem(HISTORY_KEY, JSON.stringify(cache))
       })
@@ -167,7 +195,7 @@ provide('fakeBack', fakeBack)
     right: 58px;
     width: 72px;
     cursor: pointer;
-    z-index: 8;
+    z-index: 10001;
   }
 }
 
@@ -339,42 +367,42 @@ button.logo{
   height: 100%;
   background: rgba(0, 0, 0, 0.8);
   display: none;
-  z-index: 100;
+  z-index: 9990;
   @media (max-aspect-ratio: 1/1) {
     display: initial;
   }
   > .inner-wrapper {
-    position: absolute;
-    left: 50%;
-    top: 50%;
-    transform: translate(-50%, -50%);
-    width: 700px;
-    height: 700px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 80px;
+    width: 100%;
+    height: 100%;
+    box-sizing: border-box;
     > img {
-      width: 100%;
-      height: 100%;
+      width: 650px;
     }
     > span {
-      position: absolute;
-      left: 50%;
-      bottom: -8px;
-      transform: translate(-50%, 100%);
       font-size: 80px;
-      font-family: Source Han Sans-Regular, Source Han Sans;
-      font-weight: 400;
+      font-family: "Source Han Sans SC light";
       color: #ffffff;
-      white-space: pre;
+      text-align: center;
+
+      &:not(:first-child) {
+        margin-top: 40px;
+      }
     }
   }
 }
 
 .card-title {
   position: relative;
-  height: 44px;
-  line-height: 44px !important;
+  height: calc(44 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+  line-height: calc(44 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef')) !important;
   text-align: center;
   font-family: "SourceHanSerifCN-SemiBold" !important;
-  font-size: 28px;
+  font-size: calc(28 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
   color: #6A3906;
   background: linear-gradient(90deg, rgba(255,226,122,0) 0%, #E3C67F 26%, #C9AD83 49%, #DDC38A 70%, rgba(249,226,148,0) 100%);
 
@@ -459,4 +487,21 @@ button.logo{
   width: 100%;
   height: 100%;
 }
+
+.screen-rotate-tip.portrait {
+  display: block;
+  z-index: 10000;
+
+  @media (max-aspect-ratio: 1/1) {
+    display: none;
+  }
+  .inner-wrapper {
+    img {
+      width: 300px;
+    }
+    span {
+      font-size: 40px;
+    }
+  }
+}
 </style>

BIN
src/assets/images/CameraContent-1-2-3-img-1.jpg


BIN
src/assets/images/CameraContent-1-2-3-img-2.jpg


BIN
src/assets/images/CameraContent-1-2-3-img-3.jpg


BIN
src/assets/images/CameraContent-1-2-3-img-4.jpg


BIN
src/assets/images/CameraContent-1-2-3-img-5.jpg


BIN
src/assets/images/CameraContent-1-2-3-img-6.jpg


BIN
src/assets/images/CameraContent-1-2-3-img-7.jpg


BIN
src/assets/images/CameraContent-3-1-3-img-6.png


BIN
src/assets/images/btn_restart-min.png


BIN
src/assets/images/camera-content-1-1-3-img.jpg


BIN
src/assets/images/camera-content-1-1-3-img.png


BIN
src/assets/images/camera-content-2-3-1-img-2.png


BIN
src/assets/images/camera-content-2-3-2-tab-5-img.png


+ 40 - 5
src/components/CameraContent-1-1-1.vue

@@ -381,7 +381,7 @@ setInterval(() => {
         >span:first-of-type{
           display: block;
           writing-mode: vertical-lr;
-          font-size: calc(23 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-size: 23px;
           font-family: "SourceHanSerifCN-SemiBold";
           color: #FFF7D9;
           line-height: calc(27 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -391,7 +391,7 @@ setInterval(() => {
           margin-top: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           display: block;
           writing-mode: vertical-lr;
-          font-size: calc(18 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          font-size: 18px;
           font-family: "Source Han Sans SC Regular";
           color: #43310E;
           line-height: calc(23 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -403,10 +403,10 @@ setInterval(() => {
         top: calc(80 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         left: calc(120 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         width: calc(16 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        height: calc(47 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        min-height: calc(47 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         background: #796545;
         border-radius: calc(8 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        font-size: calc(10 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        font-size: 10px;
         font-family: "SourceHanSerifCN-SemiBold";
         color: #FFFFFF;
         line-height: calc(12 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -697,4 +697,39 @@ setInterval(() => {
     }
   }
 }
-</style>
+
+@media screen and (max-width: 1500px) {
+  .camera-content-1-1 > .content-wrap {
+    top: 50%;
+    width: calc(2020 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(823 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+
+    .design-wrap {
+      h2.character-name {
+        top: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        left: calc(0px - 5 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: calc(162 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        min-height: calc(479 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+
+        span {
+          &:last-child {
+            margin-top: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          }
+        }
+      }
+      .zhuanchang {
+        left: calc(135 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        font-size: 8PX;
+        width: calc(36 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        min-height: calc(67 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      }
+      .zhuanchang-tag.one {
+        left: calc(195 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      }
+      .zhuanchang-tag.two {
+        left: calc(255 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      }
+    }
+  }
+}
+</style>

+ 2 - 11
src/components/CameraContent-1-1-2.vue

@@ -81,19 +81,13 @@
 </template>
 
 <script setup>
-import { ref, computed, watch, onMounted } from "vue"
-import { useRoute, useRouter } from "vue-router"
-import { useStore } from "vuex"
+import { ref } from "vue"
 
 const {
   windowSizeInCssForRef,
   windowSizeWhenDesignForRef,
 } = useSizeAdapt(1920, 970)
 
-const route = useRoute()
-const router = useRouter()
-const store = useStore()
-
 const emit = defineEmits(['close'])
 
 const activeTabIdx = ref(1)
@@ -261,7 +255,7 @@ const tab1ContentPageNumber = ref(1)
       align-items: center;
       >p{
         width: calc(809 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        max-height: calc(250 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        max-height: calc(300 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         overflow: auto;
         font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         font-family: Source Han Sans CN, Source Han Sans CN;
@@ -278,9 +272,6 @@ const tab1ContentPageNumber = ref(1)
         background-color: rgba(145,129,117,0.25);
         object-fit: cover;
       }
-      >.img-title{
-        margin-top: -2.5em;
-      }
     }
   }
 }

+ 2 - 3
src/components/CameraContent-1-1-3.vue

@@ -23,7 +23,7 @@
       <div class="right">
         <img
           class=""
-          src="@/assets/images/camera-content-1-1-3-img.png"
+          src="@/assets/images/camera-content-1-1-3-img.jpg"
           alt=""
           draggable="false"
         >
@@ -100,10 +100,9 @@ const emit = defineEmits(['close'])
         background-repeat: no-repeat;
         background-position: center center;
         display: flex;
-        justify-content: center;
         align-items: center;
         padding-top: calc(2 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        padding-left: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        padding-left: calc(70 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         margin-bottom: calc(15 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       }
       >p{

+ 5 - 1
src/components/CameraContent-1-2-1.vue

@@ -138,9 +138,13 @@ const layoutDataList = [
     title: '延春阁',
     detail: '大明殿北部为延春阁,是为后庭,为皇后居所。'
   },
+  {
+    title: '皇城与宫城',
+    detail: '皇城与宫城是元大都城的核心,围绕太液池规划。皇城包含宫城,宫城里的建筑分南、北两组,南面是以大明殿为主体的前朝,北面是以延春阁为主体的后廷。宫城以北是御苑,以西即是太液池。'
+  },
 ]
 
-const displayingHotspotIdx = ref(-1)
+const displayingHotspotIdx = ref(4)
 const checkedHotspotIdx = ref(-1)
 
 const hotspotIdx = computed(() => displayingHotspotIdx.value > - 1 ? displayingHotspotIdx.value : checkedHotspotIdx.value)

+ 93 - 24
src/components/CameraContent-1-2-3.vue

@@ -14,25 +14,42 @@
           赵孟頫觐见忽必烈,得到忽必烈的称许:“果真是一表人才、丰神俊朗,就如那九天之上的仙人啊!朕授予你兵部郎中之职,愿你尽忠职守。”
         </p>
       </div>
-      <div class="right">
-        <video
-          src="@/assets/videos/camera-content-1-2-3.mp4"
-          controls
-          x5-playsinline="true"
-          playsinline="true"
-          webkit-playsinline="true"
-          x-webkit-airplay="true"
-          x5-video-player-type="h5-page"
-          @play="stopBgAudio"
-          @pause="startBgAudio"
-        />
+      <div class="design-wrap-right">
+        <!-- 左右按钮 -->
+        <img
+          class="btn-left"
+          src="@/assets/images/CameraContent-3-1-3-left.png"
+          alt=""
+          :style="{opacity: currentSwitchIdx == 0 ? '0.4':'1'}"
+          @click="previous()"
+        >
+        <img
+          class="btn-right"
+          src="@/assets/images/CameraContent-3-1-3-right.png"
+          alt=""
+          :style="{opacity: currentSwitchIdx == imgTips.length - 1 ? '0.4':'1'}"
+
+          @click="next()"
+        >
+        <img
+          class="detail-img"
+          :src="require(`@/assets/images/CameraContent-1-2-3-img-${currentSwitchIdx + 1}.jpg`)"
+          alt=""
+        >
+
+        <p
+          class="img-tips"
+          style="text-align: center;"
+        >
+          {{ imgTips[currentSwitchIdx] }}
+        </p>
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import { inject, onBeforeUnmount } from 'vue'
+import { ref } from 'vue'
 
 const {
   windowSizeInCssForRef,
@@ -40,12 +57,34 @@ const {
 } = useSizeAdapt(1920, 970)
 
 const emit = defineEmits(['close'])
-const stopBgAudio = inject('stopBgAudio')
-const startBgAudio = inject('startBgAudio')
 
-onBeforeUnmount(() => {
-  startBgAudio()
-})
+const currentSwitchIdx = ref(0)
+const imgTips = [
+  '邀您一起和赵孟頫北上大都',
+  '德清——赵孟頫接获北上诏令',
+  '南浔——赵孟頫南浔北得独孤赠兰亭序,舟中写跋',
+  '宝应——赵孟頫舟中展卷',
+  '济州——赵孟頫济州急登船',
+  '虎陂——赵孟頫虎陂等待放闸',
+  '大都——赵孟頫抵达大都'
+]
+
+const previous = () => {
+  if (currentSwitchIdx.value > 0 ) {
+    console.log('上一页2')
+    currentSwitchIdx.value -= 1
+  } else {
+    return
+  }
+}
+
+const next = () => {
+  if (currentSwitchIdx.value < imgTips.length - 1) {
+    currentSwitchIdx.value += 1
+  } else {
+    return
+  }
+}
 </script>
 
 <style lang="less" scoped>
@@ -93,14 +132,44 @@ onBeforeUnmount(() => {
         font-size: 20px;
       }
     }
-    >.right{
-      flex: 0 0 auto;
-      position: relative;
+    >.design-wrap-right {
+        width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        position: relative;
+        >.btn-left {
+          width: 60px;
+          height: 60px;
+          position: absolute;
+          left: -30px;
+          top: 50%;
+          transform: translateY(-50%);
+          z-index: 2;
+          cursor: pointer;
+        }
+        >.btn-right {
+          width: 60px;
+          height: 60px;
+          position: absolute;
+          right: -30px;
+          top: 50%;
+          transform: translateY(-50%);
+          z-index: 2;
+          cursor: pointer;
+        }
+        .btn-left,
+        .btn-right {
+          transition: all linear .2s;
 
-      video {
-        height: calc(453 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          &:hover {
+            transform: translateY(-50%) scale(1.2);
+          }
+        }
+        >.detail-img {
+          width: 100%;
+        }
+        .img-tips {
+          font-size: 14px;
+        }
       }
-    }
   }
 }
 </style>

+ 11 - 15
src/components/CameraContent-1-3-1.vue

@@ -79,19 +79,13 @@
 </template>
 
 <script setup>
-import { ref, computed, watch, onMounted } from "vue"
-import { useRoute, useRouter } from "vue-router"
-import { useStore } from "vuex"
+import { ref } from "vue"
 
 const {
   windowSizeInCssForRef,
   windowSizeWhenDesignForRef,
 } = useSizeAdapt(1920, 970)
 
-const route = useRoute()
-const router = useRouter()
-const store = useStore()
-
 const emit = defineEmits(['close'])
 
 const activeTabIdx = ref(1)
@@ -157,8 +151,8 @@ const activeTabIdx = ref(1)
         align-items: center;
         color: #FFF3C3;
         background: #AC997F;
-        font-size: 19px;
-        letter-spacing: 8px;
+        font-size: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        letter-spacing: calc(8 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         font-family: "SourceHanSerifCN-SemiBold";
         box-shadow: 3px 4px 9px 0px rgba(0,0,0,0.25);
         cursor: pointer;
@@ -187,7 +181,7 @@ const activeTabIdx = ref(1)
       align-items: flex-start;
 
       img {
-        width: calc(405 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: calc(384 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       }
       .card-title {
         margin-bottom: 30px;
@@ -197,18 +191,20 @@ const activeTabIdx = ref(1)
         padding-right: 20px;
         font-size: 20px;
         overflow: auto;
-        max-height: 475px;
+        max-height: calc(475 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       }
       &__inner {
-        margin-right: 40px;
+        flex: 1;
+        width: 0;
+        margin-right: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       }
       > .img-wrap {
         display: flex;
         flex-direction: column;
         justify-content: center;
         align-items: center;
-        >img{
-        }
+        flex-shrink: 1;
+
         >.img-title{
           margin-top: 0.5em;
           color: #6A3906;
@@ -219,7 +215,7 @@ const activeTabIdx = ref(1)
       }
     }
     >.default-content{
-      padding: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'))
+      padding: calc(40 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     }
     >.tab-1-content{
       >div.table{

+ 31 - 1
src/components/CameraContent-1-3-2.vue

@@ -174,7 +174,7 @@ const displayingHotspotIdx = ref(0)
           bottom: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           transform: translate(-50%, 0);
           width: calc(73 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-          height: calc(239 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          min-height: calc(239 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           background-image: url(@/assets/images/camera-content-1-3-2-hotspot-label.png);
           background-size: contain;
           background-repeat: no-repeat;
@@ -285,4 +285,34 @@ const displayingHotspotIdx = ref(0)
     }
   }
 }
+
+@media screen and (max-width: 1500px) {
+  .camera-content-1-3-2 {
+    > .content-wrap {
+      top: 50%;
+      width: calc(2020 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      height: calc(823 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+
+      .map-wrap {
+        > .desc {
+          width: calc(786 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          height: calc(561 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        }
+        button.hotspot {
+          &.active .label {
+            width: calc(117 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            height: calc(315 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          }
+          > .label {
+            width: calc(113 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+            min-height: calc(279 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+          }
+        }
+      }
+    }
+    > h1 {
+      top: calc(14 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+  }
+}
 </style>

+ 22 - 16
src/components/CameraContent-1-3-3.vue

@@ -6,12 +6,14 @@
       @click="emit('close')"
     />
     <div class="content-wrap">
-      <p class="card-title left">
-        重要建筑构件瓦当与滴水
-      </p>
-      <p class="text-indent">
-        瓦当与滴水是用在古代建筑檐口的瓦件,分别与筒瓦、板瓦相连,既具有保护木构的作用,也有装饰和等级意味。元代高等级建筑使用的龙纹瓦当、滴水,在元大都、元中都、元上都都有不少发现,其中以黄绿琉璃最为常见。元人尚白,考古也曾发现白色瓷瓦或琉璃瓦。发现数量更多的是灰陶瓦件,元大都出土的灰陶瓦当、滴水,以花草纹、凤鸟纹、兽面纹为大宗。
-      </p>
+      <div class="design-wrap-left">
+        <p class="card-title left">
+          重要建筑构件瓦当与滴水
+        </p>
+        <p class="text-indent">
+          瓦当与滴水是用在古代建筑檐口的瓦件,分别与筒瓦、板瓦相连,既具有保护木构的作用,也有装饰和等级意味。元代高等级建筑使用的龙纹瓦当、滴水,在元大都、元中都、元上都都有不少发现,其中以黄绿琉璃最为常见。元人尚白,考古也曾发现白色瓷瓦或琉璃瓦。发现数量更多的是灰陶瓦件,元大都出土的灰陶瓦当、滴水,以花草纹、凤鸟纹、兽面纹为大宗。
+        </p>
+      </div>
       <div class="design-wrap-right">
         <img
           class="detail-img"
@@ -52,12 +54,16 @@ const emit = defineEmits(['close'])
     background-size: contain;
     background-repeat: no-repeat;
     background-position: center center;
+    z-index: 1;
   }
   >.content-wrap{
     position: absolute;
     left: 50%;
     top: 54%;
-    padding: 140px 975px 140px 150px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 0 150px;
     width: 100vw;
     height: calc(723 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     transform: translate(-50%, -50%);
@@ -71,20 +77,20 @@ const emit = defineEmits(['close'])
       margin-bottom: 20px;
     }
     .text-indent {
-      font-size: 20px;
+      font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     }
   }
+  .design-wrap-left {
+    position: relative;
+    top: calc(0px - 30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    width: 690px;
+  }
   .design-wrap-right {
+    margin-left: calc(150 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     display: flex;
     align-items: center;
     justify-content: center;
-    width: calc(719 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    height: calc(196 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    // background: rgba(145,129,117,0.25);
-    // border: 1px solid #FFE88B;
-    position: absolute;
-    top: calc(295 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-    right: calc(149 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    width: 709px;
     >.btn-left {
       width: 60px;
       height: 60px;
@@ -114,7 +120,7 @@ const emit = defineEmits(['close'])
       }
     }
     .detail-img {
-      width: 719px;
+      width: 100%;
     }
   }
 }

+ 11 - 12
src/components/CameraContent-2-1-1.vue

@@ -51,7 +51,7 @@
           </div>
           <div
             v-if="currentSwitchIdx == 2"
-            class="content-box mtNegative70"
+            class="content-box"
           >
             <div class="title text-indent">
               大运河兴建的性质、价值与历史意义
@@ -104,9 +104,6 @@ const title = '大运河的历史演变'
 <style lang="less" scoped>
 @page-height-design-px: 970;
 
-.mtNegative70 {
-  margin-top: -70px;
-}
 .mb27 {
   margin-bottom: 27px;
 }
@@ -214,12 +211,14 @@ const title = '大运河的历史演变'
       }
 
       >.design-wrap-right {
+        position: relative;
         width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         height: calc(438 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         background: url(@/assets/images/CameraContent-2-1-1-right-bg.png);
         background-size: 100% 100%;
-        position: relative;
-        padding: calc(100 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        display: flex;
+        align-items: center;
+        padding: 0 calc(100 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         >.right-title {
           width: calc(80 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           height: calc(250 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -246,6 +245,12 @@ const title = '大运河的历史演变'
         //   line-height: calc(26 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         // }
         >.content-box {
+          margin: 20px 0;
+          padding: 20px 10px 20px 0;
+          overflow-y: auto;
+          max-height: calc(100% - 40px);
+          box-sizing: border-box;
+
           >.title {
             color: #6A3906;
             font-family: "Source Han Sans SC Bold";
@@ -257,12 +262,6 @@ const title = '大运河的历史演变'
             // letter-spacing: 0.2em;
             font-size: 20px;
             line-height: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-
-            &.auto-content {
-              padding-right: 20px;
-              max-height: 300px;
-              overflow: auto;
-            }
           }
         }
       }

+ 2 - 1
src/components/CameraContent-2-1-2.vue

@@ -175,7 +175,7 @@ const next = () => {
       justify-content: space-evenly;
       align-items: center;
       >.design-wrap-left {
-        width: calc(700 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: calc(720 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         >.left-title {
           width: calc(579 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           height: calc(62 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -190,6 +190,7 @@ const next = () => {
         >.left-text {
           // font-family: 'SourceHanSansSC-Normal';
           margin-top: 25px;
+          padding-right: 20px;
           height: calc(300 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           overflow: auto;
           // font-family: 'SourceHanSansSC-Normal';

+ 23 - 7
src/components/CameraContent-2-1-3.vue

@@ -178,8 +178,8 @@ const tab1ContentPageNumber = ref(1)
       top: calc(42 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
 
       >span {
-        width: calc(46 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        height: calc(168 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: 46px;
+        height: 168px;
         writing-mode: vertical-lr;
         display: flex;
         justify-content: center;
@@ -240,13 +240,12 @@ const tab1ContentPageNumber = ref(1)
 
           >p {
             flex: 1;
+            margin-right: -20px;
             max-height: calc(490 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
             overflow: auto;
             font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
             color: #000000;
-            line-height: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-            // letter-spacing: calc(4 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-            padding-right: 0.5em;
+            padding-right: 20px;
           }
           >.img-box {
             margin-left: calc(80 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -389,7 +388,6 @@ const tab1ContentPageNumber = ref(1)
         }
 
         >p {
-          width: calc(809 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           max-height: 80%;
           overflow: auto;
           font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -398,7 +396,8 @@ const tab1ContentPageNumber = ref(1)
           color: #000000;
           line-height: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
           // letter-spacing: calc(4 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-          padding-right: 0.5em;
+          padding-right: 20px;
+          box-sizing: border-box;
         }
       }
 
@@ -425,4 +424,21 @@ const tab1ContentPageNumber = ref(1)
     }
   }
 }
+
+@media screen and (max-height: 480px) {
+  .camera-content-1-1 > .content-wrap {
+    top: 50%;
+    width: calc(1685 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(919 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+
+    h1 {
+      top: calc(230 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      left: calc(140 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+    .tab-content {
+      left: calc(500 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      width: calc(1005 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+  }
+}
 </style>

+ 4 - 4
src/components/CameraContent-2-2-1.vue

@@ -77,6 +77,7 @@ const emit = defineEmits(['close'])
     position: absolute;
     left: 50%;
     top: 54%;
+    padding: 0 calc(150 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     width: 100%;
     // width: calc(1920 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     height: calc(723 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -89,8 +90,7 @@ const emit = defineEmits(['close'])
     justify-content: space-evenly;
     align-items: center;
     >.left{
-      flex: 0 0 auto;
-      width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      flex: 1;
       >h2{
         width: calc(616 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         height: calc(62 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
@@ -120,10 +120,10 @@ const emit = defineEmits(['close'])
       }
     }
     >.right{
-      flex: 0 0 auto;
+      margin-left: 150px;
+      flex-shrink: 0;
       position: relative;
       width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      height: calc(438 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       display: flex;
       flex-direction: column;
       justify-content: center;

+ 21 - 3
src/components/CameraContent-2-3-2.vue

@@ -60,7 +60,7 @@
         <div
           class="table1"
         >
-          <h3>全国唯一一所为皇室烧瓷的官署机构</h3>
+          <h3>全国唯一一所为皇室烧瓷的官署机构</h3>
           <div
             class="content text-indent"
           >
@@ -194,7 +194,7 @@ const activeTabIdx = ref(1)
 }
 .tab5img {
   margin-bottom: calc(10 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-  width: calc(246 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+  width: calc(200 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
 }
 .camera-content-1-1 {
   position: absolute;
@@ -262,11 +262,14 @@ const activeTabIdx = ref(1)
         align-items: center;
         background: #AC997F;
         color: #FFF3C3;
-        font-size: 19px;
+        overflow: hidden;
+        white-space: nowrap;
+        font-size: calc(19 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         letter-spacing: calc(1 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         font-family: "SourceHanSerifCN-SemiBold";
         box-shadow: 3px 4px 9px 0px rgba(0, 0, 0, 0.25);
         cursor: pointer;
+        box-sizing: border-box;
       }
 
       >span.active {
@@ -472,4 +475,19 @@ const activeTabIdx = ref(1)
     }
   }
 }
+
+@media screen and (max-width: 1500px) {
+  .camera-content-1-1 >  div.content-wrap {
+    top: 50%;
+    width: calc(1685 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(919 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+
+    .tab-content {
+      width: calc(1050 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+    > div.tabbar > span {
+      height: calc(167 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+  }
+}
 </style>

+ 27 - 13
src/components/CameraContent-3-1-1.vue

@@ -143,8 +143,8 @@ const activeTabIdx = ref(1)
       left: calc(373 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       top: calc(42 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       >span{
-        width: calc(46 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        height: calc(168 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: 46px;
+        height: 168px;
         writing-mode: vertical-lr;
         display: flex;
         justify-content: center;
@@ -176,7 +176,6 @@ const activeTabIdx = ref(1)
       left: calc(450 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       top: calc(42 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       width: calc(950 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      height: calc(750 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       display: flex;
       flex-direction: column;
       justify-content: flex-start;
@@ -202,16 +201,13 @@ const activeTabIdx = ref(1)
     }
     >.tab-1-content{
       >p{
-        width: calc(809 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: 95%;
         max-height: 80%;
         overflow: auto;
         font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        // font-family: Source Han Sans SC, Source Han Sans SC;
-        font-weight: 300;
         color: #000000;
-        line-height: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        // letter-spacing: calc(4 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        padding-right: 0.5em;
+        margin-right: -20px;
+        padding-right: 20px;
       }
       >div.table{
         position: absolute;
@@ -271,12 +267,13 @@ const activeTabIdx = ref(1)
       justify-content: flex-start;
       align-items: center;
       >p{
-        width: calc(809 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        width: 95%;
         font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        font-family: Source Han Sans CN, Source Han Sans CN;
-        font-weight: 300;
         color: #000000;
-        line-height: 30px;
+        margin-right: -20px;
+        padding-right: 20px;
+        overflow-y: auto;
+        max-height: calc(460 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         // letter-spacing: calc(8 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       }
       >img{
@@ -290,4 +287,21 @@ const activeTabIdx = ref(1)
     }
   }
 }
+
+@media screen and (max-height: 480px) {
+  .camera-content-1-1 > .content-wrap {
+    top: 50%;
+    width: calc(1685 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    height: calc(919 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+
+    h1 {
+      top: calc(230 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      left: calc(140 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+    .tab-content {
+      left: calc(500 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+      width: calc(1005 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+    }
+  }
+}
 </style>

+ 6 - 12
src/components/CameraContent-3-2-1.vue

@@ -178,7 +178,6 @@ const activeTabIdx = ref(1)
       left: calc(450 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       top: calc(42 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       width: calc(950 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-      height: calc(750 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
       display: flex;
       flex-direction: column;
       justify-content: flex-start;
@@ -206,15 +205,12 @@ const activeTabIdx = ref(1)
     >.tab-1-content{
       >p{
         width: calc(809 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        max-height: 80%;
+        max-height: calc(480 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         overflow: auto;
         font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        font-family: Source Han Sans SC, Source Han Sans SC;
-        font-weight: 300;
         color: #000000;
-        line-height: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        // letter-spacing: calc(4 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        padding-right: 0.5em;
+        margin-right: -20px;
+        padding-right: 20px;
       }
       >div.table{
         position: absolute;
@@ -275,14 +271,12 @@ const activeTabIdx = ref(1)
       align-items: center;
       >p{
         width: calc(809 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        max-height: calc(400 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        max-height: calc(480 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
         overflow: auto;
         font-size: calc(20 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
-        font-family: Source Han Sans CN, Source Han Sans CN;
-        font-weight: 300;
         color: #000000;
-        line-height: 30px;
-        // letter-spacing: calc(8 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
+        margin-right: -20px;
+        padding-right: 20px;
       }
       >img{
         width: calc(818 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));

+ 2 - 2
src/components/CameraContent-3-2-3.vue

@@ -18,10 +18,10 @@
         </div>
         <div class="content-wrap__right text-indent">
           <div>
-            <p>
+            <p class="text-indent">
               大都的著名女演员,有珠帘秀、顺时秀、天然秀、赛帘秀、燕山秀(均为艺名)等。珠帘秀本姓朱,她的“杂剧为当今独步”,名震一时。赛帘秀、燕山秀等,都是她的门徒,后辈都尊称她为朱娘娘。顺时秀原名郭顺卿,元代中期也很有名,“教坊女乐顺时秀,岂独歌博天下名!意态由来看不足,揭帘半面已倾城”。
             </p>
-            <p>
+            <p class="text-indent">
               大都著名的男演员有魏、武、刘三人,“魏长于念诵,武长于筋斗,刘长于科泛(表演动作之意——引者),后代乐人“皆宗之”。可惜他们的名字都没有流传下来。
             </p>
           </div>

+ 2 - 1
src/components/HotspotDialog-1.vue

@@ -710,7 +710,8 @@ const isDDLS = computed(() =>
 const openNewWindow = async() => {
   store.dispatch('openIframePage', {
     url: 'https://houseoss.4dkankan.com/project/yzdyh-dadu/game/index.html',
-    style: $isMobile ? 'width: 100vh; height: 100%' : 'width: 375px; height: 812px'
+    style: $isMobile ? 'width: 100vw; height: 100vh' : 'width: 375px; height: 812px',
+    portrait: true
   })
 }
 

+ 4 - 7
src/components/MutiRelicHotSpot.vue

@@ -191,13 +191,14 @@ const showRandomPoster = () => {
 <style lang="less" scoped>
 .muti-relic {
   display: flex;
+  flex-direction: column;
   align-items: center;
   justify-content: center;
   position: fixed;
   top: 0;
   left: 0;
-  width: 100vw;
-  height: 100vh;
+  width: 100%;
+  height: 100%;
   z-index: 9;
 
   .mask {
@@ -210,18 +211,15 @@ const showRandomPoster = () => {
     z-index: -1;
   }
   &__btn {
+    margin-top: calc(30 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     display: flex;
     align-items: center;
     justify-content: center;
-    position: absolute;
-    left: 50%;
-    bottom: 60px;
     width: 259px;
     height: 67px;
     cursor: pointer;
     font-size: 28px;
     font-family: "Source Han Serif CN Heavy";
-    transform: translateX(-50%);
     background: url('@/assets/images/hotspot-relic/btn-min.png') no-repeat center / contain;
 
     span {
@@ -239,7 +237,6 @@ const showRandomPoster = () => {
   }
   .my-box {
     position: relative;
-    top: -20px;
     width: calc(1538 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     height: calc(759 / v-bind('windowSizeWhenDesignForRef') * v-bind('windowSizeInCssForRef'));
     background: url('@/assets/images/hotspot-relic/bg_baoxiang-min.png') no-repeat center / contain;

+ 30 - 40
src/components/StartUp.vue

@@ -14,8 +14,13 @@
         draggable="false"
       >
     </div> -->
+    <button
+      v-if="status === 'error'"
+      class="start reload"
+      @click="reload"
+    />
     <div
-      v-if="!canStart"
+      v-else-if="!canStart"
       class="progress"
     >
       {{ loadingProgress }}%
@@ -65,60 +70,41 @@ import { useStore } from "vuex"
 import startVideo from '@/assets/videos/start-up-video.mp4'
 import startVideoMobile from '@/assets/videos/start-up-video-mb.mp4'
 import preloadList from '@/preloadList'
+import { usePreloader } from '@/hooks/usePreloader'
 // import startupVoiceUrl from '@/assets/audios/startup-voice.mp3'
 
 const $isMobile = inject('$isMobile')
 const store = useStore()
+const { percent: loadingProgress, status, start, reload } = usePreloader({
+  list: preloadList,
+  cb: () => {
+    store.commit('declareCanStart')
+  },
+})
 
 onMounted(() => {
-  preloadList.forEach(url => {
-    mediaPreloader(url)
+  Promise.all([
+    preloaderImage(require('@/assets/images/start-up-bg.jpg')),
+    preloaderImage(require('@/assets/images/startup-animation.png'))
+  ]).then(() => {
+    start()
   })
 })
 
-let downloadSize = 0
-let mediaSizeStack = []
-const mediaPreloader = url => {
-  fetch(url)
-    .then(response => {
-      const contentLength = +response.headers.get('Content-Length')
-      mediaSizeStack.push(contentLength)
-
-      if (response.ok) {
-        return response
-      }
-    })
-    .then(response => response.body)
-    .then(async body => {
-      const reader = body.getReader()
-      const loop = true
-
-      while (loop) {
-        const { value, done } = await reader.read()
-
-        if (done) break
-
-        downloadSize += value.length
-
-        if (mediaSizeStack.length === preloadList.length) {
-          const mediaSize = mediaSizeStack.reduce((pre, cur) => pre + cur)
-          const percent = Math.floor(downloadSize / mediaSize * 100)
-          loadingProgress.value = percent
-
-          if (downloadSize === mediaSize) {
-            store.commit('declareCanStart')
-          }
-        }
-      }
-    })
+const preloaderImage = (url) => {
+  return new Promise(res => {
+    const img = new Image()
+    img.onload = () => {
+      res()
+    }
+    img.src = url
+  })
 }
 
 const canStart = computed(() => {
   return store.state.canStart
 })
 
-const loadingProgress = ref(0)
-
 const isShowVideo = ref(false)
 function onClickStart() {
   isShowVideo.value = true
@@ -211,6 +197,10 @@ function onClickSkip() {
     background-position: center center;
     transform: translate(-50%, -50%);
     z-index: 1;
+
+    &.reload {
+      background-image: url('@/assets/images/btn_restart-min.png');
+    }
   }
   >img.person-animation{
     position: absolute;

+ 3 - 0
src/components/UserGuide.vue

@@ -227,6 +227,9 @@ const handleClose = () => {
       margin-left: 2px;
       bottom: 550px;
     }
+    img {
+      width: 38400px;
+    }
   }
   span,
   p {

+ 119 - 0
src/hooks/usePreloader.js

@@ -0,0 +1,119 @@
+import { ref } from "vue"
+import { throttle } from "lodash"
+
+export function usePreloader(params) {
+  const decimals = params.decimals ? params.decimals * 10 : 1
+  let fetchControllerStack = []
+
+  /**
+   * 总字节长度
+   */
+  let totalLength = 0
+  let fileSizeStack = []
+  /**
+   * 已接收字节长度
+   */
+  let downloadLength = 0
+  /**
+   * 进度
+   */
+  const percent = ref('0')
+  const status = ref('waiting')
+
+  const setThrottlePercent = throttle((val) => percent.value = val, 200)
+
+  const handlePreload = (url) => {
+    const controller = new AbortController()
+    const signal = controller.signal
+
+    return new Promise((res, rej) => {
+      fetch(url, { signal })
+        .then((response) => {
+          const contentLength = Number(response.headers.get("Content-Length"))
+          fileSizeStack.push(contentLength)
+
+          if (response.ok) {
+            return response.body
+          }
+        })
+        .then(async (body) => {
+          if (!body) return
+
+          const reader = body.getReader()
+          const loop = true
+
+          while (loop) {
+            const { value, done } = await reader.read()
+
+            if (done) break
+
+            downloadLength += value.length
+
+            if (fileSizeStack.length === params.list.length) {
+              const mediaSize = fileSizeStack.reduce(
+                (pre, cur) => pre + cur
+              )
+              const percent = Math.round(
+                (downloadLength / mediaSize) * 100 * decimals
+              )
+
+              setThrottlePercent((percent / decimals).toFixed(params.decimals))
+            }
+          }
+
+          res(true)
+        })
+        .catch((err) => {
+          rej(err)
+        })
+
+      fetchControllerStack.push(controller)
+    })
+  }
+
+  const start = () => {
+    console.log(status)
+    if (status.value !== 'waiting') return
+
+    status.value = 'loading'
+
+    Promise.all(params.list.map((url) => handlePreload(url)))
+      .then(() => {
+        params.cb?.()
+        status.value = 'done'
+      })
+      .catch(() => {
+        abort()
+        status.value = 'error'
+      })
+  }
+
+  const reload = () => {
+    abort()
+
+    totalLength = 0
+    downloadLength = 0
+    fileSizeStack = []
+    setThrottlePercent("0")
+    status.value = 'waiting'
+
+    start()
+  }
+
+  const abort = () => {
+    fetchControllerStack.forEach((controller) => {
+      controller.abort()
+    })
+    fetchControllerStack = []
+  }
+
+  return {
+    status,
+    totalLength,
+    downloadLength,
+    percent,
+    start,
+    reload,
+    abort,
+  }
+}

+ 3 - 0
src/main.js

@@ -12,6 +12,9 @@ import VueViewer from 'v-viewer'
 import ElementPlus from 'element-plus'
 import 'element-plus/dist/index.css'
 import 'lib-flexible'
+import VConsole from 'vconsole'
+
+new VConsole()
 
 console.log(`version: ${process.env.VUE_APP_VERSION}`)
 console.log(`Build time: ${process.env.VUE_APP_UPDATE_TIME}`)

+ 1 - 0
src/preloadList.js

@@ -20,6 +20,7 @@ export default [
   require('@/assets/images/scene-1-preview.jpg'),
   require('@/assets/images/scene-2-preview.jpg'),
   require('@/assets/images/scene-3-preview.jpg'),
+  require('@/assets/images/character-luibingzhong-2.png'),
 
   require('@/assets/videos/guide.mp4'),
   require('@/assets/videos/epilogue.mp4'),

+ 4 - 7
src/views/HomeView.vue

@@ -54,10 +54,7 @@
     <template v-else-if="store.state.haveShownStartUp">
       <Swiper
         class="scene-preview swiper-scene-preview"
-        :autoplay="{
-          delay: 3000,
-          disableOnInteraction: false
-        }"
+        :initial-slide="hoveringEntryIdx - 1"
         auto-height
         @slide-change="(e) => {
           hoveringEntryIdx = e.activeIndex + 1
@@ -157,9 +154,9 @@ onMounted(() => {
 watch(() => store.state.haveShownStartUp, e => {
   if (e) {
     showHelper.value = true
-    setTimeout(() => {
-      showHelper.value = false
-    }, 4000)
+    // setTimeout(() => {
+    //   showHelper.value = false
+    // }, 4000)
   }
 })
 

+ 7 - 2
src/views/PanoView.vue

@@ -1329,8 +1329,7 @@ onMounted(() => {
           margin-left: 120px;
           display: none;
           font-size: 23px;
-          font-family: Source Han Serif SC, Source Han Serif SC;
-          font-weight: 600;
+          font-family: "Source Han Sans SC Bold";
           color: #FFF1BE;
           line-height: 27px;
           letter-spacing: 5px;
@@ -1636,4 +1635,10 @@ onMounted(() => {
    * end of 场景切换过渡
    */
 }
+
+@media screen and (max-height: 480px) {
+  .pano-view .pano-wrap > .character-wrap > button.btn-on-track > span {
+    font-size: 1.3vw;
+  }
+}
 </style>

+ 25 - 0
src/views/RelicList.vue

@@ -385,7 +385,32 @@ const handleScroll = debounce(() => {
     padding-left: calc(54 / @page-height-design-px * 100vh);
     box-sizing: border-box;
 
+    &.scene1 {
+      .content-wrap::after {
+        background: #B8AD9C;
+      }
+    }
+    &.scene2 {
+      .content-wrap::after {
+        background: #AEC5BB;
+      }
+    }
+    &.scene3 {
+      .content-wrap::after {
+        background: #A6A3AD;
+      }
+    }
     >.content-wrap {
+      position: relative;
+      &::after {
+        content: '';
+        position: absolute;
+        top: calc(42 / @page-height-design-px * 100vh);
+        left: 0;
+        right: 0;
+        bottom: calc(42 / @page-height-design-px * 100vh);
+        z-index: -1;
+      }
       &::-webkit-scrollbar {
         height: 0;
       }

+ 14 - 0
src/views/ShipGame/ShipGameView.vue

@@ -119,6 +119,12 @@
           @ended="back"
         />
 
+        <img
+          class="video-skip"
+          src="@/assets/images/startup-video-skip.png"
+          @click="back"
+        >
+
         <div
           v-if="showVideoPlay"
           class="play-icon"
@@ -218,6 +224,14 @@ const back = () => {
 </script>
 
 <style lang="less" scoped>
+.video-skip {
+  position: absolute;
+  right: 43px;
+  bottom: 20px;
+  width: 291px;
+  cursor: pointer;
+  z-index: 10;
+}
 .play-icon {
   position: absolute;
   top: 0;