소스 검색

feat: 湖南省博物馆 - 遇见庞贝展

chenlei 1 일 전
부모
커밋
2b259166e7

+ 4 - 0
README.md

@@ -1,3 +1,7 @@
+## 湖南省博物馆 - 遇见庞贝展
+
+SG-MKBSii25xMt
+
 ### 初始化
 ### 初始化
 
 
 ```bash
 ```bash

+ 2 - 0
components.d.ts

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

+ 2 - 0
package.json

@@ -8,6 +8,8 @@
     "build:test": "cross-env VITE_APP_TITLE=大理洱海科普馆 VITE_APP_HOT_DOMAIN=./hotspot.html run-p type-check \"build-only {@}\" --",
     "build:test": "cross-env VITE_APP_TITLE=大理洱海科普馆 VITE_APP_HOT_DOMAIN=./hotspot.html run-p type-check \"build-only {@}\" --",
     "build:offline": "cross-env VITE_APP_OFFLINE=1 npm run build:test && cross-env node ./scripts/generate-offline-config.js && replace-in-file --configFile ./scripts/offline-replace-config.json",
     "build:offline": "cross-env VITE_APP_OFFLINE=1 npm run build:test && cross-env node ./scripts/generate-offline-config.js && replace-in-file --configFile ./scripts/offline-replace-config.json",
     "push:test": "cross-env node ./scripts/publish.js",
     "push:test": "cross-env node ./scripts/publish.js",
+    "serve:pb": "cross-env VITE_APP_SCENE=pb VITE_APP_TITLE=湖南省博物馆-遇见庞贝展 VITE_APP_HOT_DOMAIN=./hotspot.html vite",
+    "build:pb:test": "cross-env VITE_APP_SCENE=pb VITE_APP_TITLE=湖南省博物馆-遇见庞贝展 VITE_APP_HOT_DOMAIN=./hotspot.html run-p type-check \"build-only {@}\" --",
     "preview": "vite preview",
     "preview": "vite preview",
     "build-only": "vite build",
     "build-only": "vite build",
     "type-check": "vue-tsc --build --force"
     "type-check": "vue-tsc --build --force"

BIN
public/fonts/FZQKBYSJW.TTF


BIN
public/images/pb/antlist.png


BIN
public/images/pb/auto.png


BIN
public/images/pb/chapter.png


BIN
public/images/pb/dislike.png


BIN
public/images/pb/enlarge_on.png


BIN
public/images/pb/hotlist.png


BIN
public/images/pb/like.png


BIN
public/images/pb/model.png


BIN
public/images/pb/narrow_off.png


BIN
public/images/pb/pause.png


BIN
public/images/pb/play.png


BIN
public/images/pb/share.png


BIN
public/images/pb/simple.png


+ 7 - 3
src/index/app.scss

@@ -4,7 +4,7 @@
   --z-index-popper: 2000;
   --z-index-popper: 2000;
   --z-hot-popper: 3000;
   --z-hot-popper: 3000;
   --design-width: 1920;
   --design-width: 1920;
-  --design-height: 920;
+  --design-height: 1000;
   --swiper-theme-color: white;
   --swiper-theme-color: white;
   --swiper-pagination-bullet-inactive-color: white;
   --swiper-pagination-bullet-inactive-color: white;
 }
 }
@@ -47,7 +47,7 @@ body {
   margin: 0px;
   margin: 0px;
   font-size: 14px;
   font-size: 14px;
   color: rgba(255, 255, 255, 0.9);
   color: rgba(255, 255, 255, 0.9);
-  font-family: 'Source Han Sans CN-Medium';
+  font-family: 'fzq';
   -webkit-tap-highlight-color: transparent;
   -webkit-tap-highlight-color: transparent;
 }
 }
 a {
 a {
@@ -96,6 +96,10 @@ iframe {
   font-family: 'SourceHanSerifCN-Regular';
   font-family: 'SourceHanSerifCN-Regular';
   src: url('/fonts/SOURCEHANSERIFCN-REGULAR.OTF');
   src: url('/fonts/SOURCEHANSERIFCN-REGULAR.OTF');
 }
 }
+@font-face {
+  font-family: 'fzq';
+  src: url('/font/FZQKBYSJW.TTF');
+}
 
 
 .limit-line {
 .limit-line {
   display: -webkit-box;
   display: -webkit-box;
@@ -138,6 +142,6 @@ iframe {
 @media only screen and (max-width: 600px) {
 @media only screen and (max-width: 600px) {
   :root {
   :root {
     --design-width: 750;
     --design-width: 750;
-    --design-height: 1440;
+    --design-height: 1333;
   }
   }
 }
 }

+ 7 - 0
src/index/assets/el.pb.scss

@@ -0,0 +1,7 @@
+@forward 'element-plus/theme-chalk/src/common/var.scss' with (
+  $colors: (
+    'primary': (
+      'base': #e0b387,
+    ),
+  )
+);

+ 21 - 0
src/index/router/index.pb.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: '/scene',
+    name: 'home',
+    component: () => import('@/views/home'),
+  },
+];
+
+const router = createRouter({
+  history: createWebHashHistory(import.meta.env.BASE_URL),
+  routes,
+});
+
+export default router;

BIN
src/index/views/cover/images/bg.jpg


BIN
src/index/views/cover/images/btn.png


BIN
src/index/views/cover/images/mb-bg.jpg


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

@@ -0,0 +1,31 @@
+@use '@/assets/utils.scss';
+
+.cover {
+  position: absolute;
+  inset: 0;
+  background: url('./images/bg.jpg') no-repeat center bottom / 100% 100%;
+
+  &__btn {
+    position: absolute;
+    right: utils.vw-calc(244);
+    bottom: utils.vh-calc(45);
+    width: utils.vw-calc(260);
+    height: utils.vw-calc(54);
+    cursor: pointer;
+  }
+}
+
+.m-cover {
+  position: absolute;
+  inset: 0;
+  background: url('./images/mb-bg.jpg') no-repeat center bottom / 100% 100%;
+
+  &__btn {
+    position: absolute;
+    right: utils.vw-calc(57);
+    bottom: utils.vh-calc(118);
+    width: utils.vh-calc(260);
+    height: utils.vh-calc(54);
+    cursor: pointer;
+  }
+}

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

@@ -0,0 +1,31 @@
+<template>
+  <div :class="isMobile ? 'm-cover' : 'cover'">
+    <template v-if="!isMobile">
+      <img
+        class="cover__btn"
+        src="./images/btn.png"
+        draggable="false"
+        @click="$router.push({ name: 'home' })"
+      />
+    </template>
+
+    <template v-else>
+      <img
+        class="m-cover__btn"
+        src="./images/btn.png"
+        draggable="false"
+        @click="$router.push({ name: 'home' })"
+      />
+    </template>
+  </div>
+</template>
+
+<script setup>
+  import { judgeIsMobile } from '@/utils';
+
+  const isMobile = judgeIsMobile();
+</script>
+
+<style lang="scss" scoped>
+  @use './index.scss';
+</style>

+ 180 - 0
src/index/views/home/components/menu/index.pb.scss

@@ -0,0 +1,180 @@
+@use '@/assets/utils.scss';
+
+.pinBottom-container {
+  position: absolute;
+  bottom: 15px;
+  width: 100%;
+  transition: all 0.5s;
+  z-index: var(--z-index-top);
+
+  &.open {
+    bottom: 145px;
+
+    &.playing {
+      bottom: 165px;
+    }
+    &.noScroll {
+      bottom: 125px;
+
+      &.playing {
+        bottom: 145px;
+      }
+    }
+  }
+  &.playing:not(.open) {
+    bottom: 35px;
+  }
+}
+
+.pinBottom {
+  position: absolute;
+  bottom: 0;
+  line-height: 1;
+  transition: all 0.5s;
+
+  &.left {
+    left: 20px;
+    bottom: 0;
+    overflow: hidden;
+
+    > * {
+      margin-right: 20px;
+
+      &:last-child {
+        margin-right: 0;
+      }
+    }
+  }
+  &.right {
+    right: 20px;
+    bottom: 0;
+
+    > div {
+      width: 40px;
+      height: 40px;
+
+      img {
+        width: 30px;
+        height: 30px;
+      }
+    }
+  }
+  > * {
+    float: left;
+    width: 40px;
+    height: 40px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    cursor: pointer;
+
+    &.active,
+    &:hover,
+    &.opened {
+      opacity: 0.7;
+    }
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  &-exit-simple {
+    position: fixed;
+    left: 50%;
+    bottom: -120px;
+    width: 120px;
+    height: 40px;
+    line-height: 40px;
+    text-align: center;
+    color: #e0b387;
+    border-radius: 50px;
+    background-color: rgba(0, 0, 0, 0.5);
+    cursor: pointer;
+    transform: translateX(-50%);
+
+    &.active {
+      bottom: 20px;
+    }
+  }
+}
+
+#thumb {
+  .icon-slot {
+    width: 100%;
+    height: 100%;
+    transition: background ease-in 0.2s;
+    background: url('/images/pb/dislike.png') no-repeat center / contain;
+  }
+
+  &.active .icon-slot {
+    background-image: url('/images/pb/like.png');
+  }
+}
+
+.el-popper.is-dark {
+  --el-text-color-primary: rgba(0, 0, 0, 0.3);
+  --el-bg-color: #e0b387;
+}
+
+@media only screen and (max-width: 600px) {
+  .pinBottom-container {
+    bottom: 20px;
+
+    &.open {
+      bottom: 120px;
+
+      &.noScroll {
+        bottom: 110px;
+
+        &.playing {
+          bottom: 130px;
+        }
+      }
+    }
+    &.playing:not(.open) {
+      bottom: 40px;
+    }
+  }
+  .pinBottom {
+    display: flex;
+
+    &.left {
+      left: utils.vw-calc(20);
+      right: utils.vw-calc(20);
+      justify-content: center;
+      gap: utils.vw-calc(20);
+
+      > * {
+        margin-right: 0;
+      }
+    }
+    &.right {
+      right: utils.vw-calc(20);
+      bottom: utils.vh-calc(100);
+    }
+    > div {
+      width: utils.vw-calc(50);
+      height: utils.vw-calc(50);
+    }
+  }
+}
+
+.pinBottom-container,
+.home-viewer,
+.home_img {
+  transition:
+    opacity 0.38s ease,
+    transform 0.38s ease,
+    visibility 0.38s;
+}
+
+.simple-mode {
+  .pinBottom-container,
+  .home-viewer,
+  .home_img {
+    opacity: 0;
+    transform: translateY(12px) scale(0.995);
+    pointer-events: none;
+    visibility: hidden;
+  }
+}

+ 215 - 0
src/index/views/home/components/menu/index.pb.tsx

@@ -0,0 +1,215 @@
+import { defineComponent, ref } from 'vue';
+import { homeApi } from '@/api';
+import SharePopup from '../share-popup/index.vue';
+import './index.pb.scss';
+
+export default defineComponent({
+  name: 'HomeMenu',
+  props: {
+    likeCount: {
+      type: Number,
+      required: true,
+    },
+    handleLikeCounter: {
+      type: Function,
+      required: true,
+    },
+  },
+  setup(props) {
+    const isSimpleMode = ref(false);
+    const shareVisible = ref(false);
+    const animationThumb = ref(false);
+
+    const toggleSimpleMode = (on?: boolean) => {
+      const next = typeof on === 'boolean' ? on : !isSimpleMode.value;
+      isSimpleMode.value = next;
+      try {
+        if (next) document.documentElement.classList.add('simple-mode');
+        else document.documentElement.classList.remove('simple-mode');
+      } catch (e) {
+        // ignore
+      }
+    };
+    const handleThumb = () => {
+      if (animationThumb.value) return;
+
+      animationThumb.value = true;
+      homeApi.saveStar(window.number);
+      props.handleLikeCounter(props.likeCount + 1);
+
+      setTimeout(() => {
+        animationThumb.value = false;
+      }, 200);
+    };
+
+    return {
+      isSimpleMode,
+      shareVisible,
+      animationThumb,
+      handleThumb,
+      toggleSimpleMode,
+    };
+  },
+  render() {
+    return (
+      <div>
+        <div class="pinBottom-container">
+          <div class="pinBottom left">
+            <div id="previous" class="previous desktop-only ui-icon" style="display: none;">
+              <a>
+                <img src="images/pb/play.png" width="24" height="24" data-original-title="播放" />
+              </a>
+            </div>
+            <el-tooltip content="播放" show-arrow={false} offset={5}>
+              <div id="play" class="ui-icon">
+                <a>
+                  <img src="images/pb/play.png" width="24" height="24" />
+                </a>
+              </div>
+            </el-tooltip>
+            <div id="pause" class="ui-icon" style="display: none;">
+              <a>
+                <img title="暂停" src="images/pb/pause.png" width="24" height="24" />
+              </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>
+            <el-tooltip content="导览" show-arrow={false} offset={5}>
+              <div id="pullTab" title="">
+                <img
+                  class="icon icon-inside"
+                  src="images/pb/auto.png"
+                  title="导览"
+                  data-default-url="images/pb/auto.png"
+                  data-active-url="images/pb/auto.png"
+                />
+              </div>
+            </el-tooltip>
+            <div id="hotList" title="" style="display: none">
+              <el-tooltip content="热点列表" show-arrow={false} offset={5}>
+                <img class="icon icon-inside" src="images/pb/hotlist.png" title="热点列表" />
+              </el-tooltip>
+            </div>
+            <div
+              data-original-title="全景漫游"
+              id="gui-modes-inside"
+              title=""
+              class=""
+              style="display:none"
+            >
+              <img class="icon icon-inside" src="images/inside.png" title="全景漫游" />
+            </div>
+            <el-tooltip content="迷你模型" show-arrow={false} offset={5}>
+              <div id="gui-modes-dollhouse" title="" class="">
+                <img class="icon icon-inside" src="images/pb/model.png" title="迷你模型" />
+              </div>
+            </el-tooltip>
+            <div
+              data-original-title="俯视图"
+              id="gui-modes-floorplan"
+              title=""
+              style="display:none"
+            >
+              <img class="icon icon-inside" src="images/floor.png" title="俯视图" />
+            </div>
+            <el-tooltip content="展品列表" show-arrow={false} offset={5}>
+              <div id="gui-modes-antlist" title="" class="">
+                <img class="icon icon-inside" src="images/pb/antlist.png" title="展品列表" />
+              </div>
+            </el-tooltip>
+            <el-tooltip content="章节列表" show-arrow={false} offset={5}>
+              <div id="gui-modes-chapter" title="" class="">
+                <img class="icon icon-inside" src="images/pb/chapter.png" title="章节列表" />
+              </div>
+            </el-tooltip>
+            <el-tooltip content={`${this.likeCount}`} show-arrow={false} offset={5}>
+              <div
+                id="thumb"
+                data-original-title="点赞"
+                class={{ active: this.animationThumb }}
+                onClick={this.handleThumb}
+              >
+                <div class="icon icon-slot" title="点赞" />
+              </div>
+            </el-tooltip>
+            <el-tooltip content="分享" show-arrow={false} offset={5}>
+              <div id="sharing" onClick={() => (this.shareVisible = true)}>
+                <img class="icon icon-inside" src="images/pb/share.png" title="分享" />
+              </div>
+            </el-tooltip>
+            <el-tooltip content="全屏" show-arrow={false} offset={5}>
+              <div
+                id="gui-fullscreen"
+                class="ui-icon wide"
+                data-placement="top"
+                title="{[{ VIEW_FULLSCREEN }]}"
+              >
+                <a>
+                  <img class="icon icon-fullscreen" src="images/pb/enlarge_on.png" />
+                </a>
+              </div>
+            </el-tooltip>
+            <div
+              id="gui-fullscreen-exit"
+              class="ui-icon wide"
+              data-placement="top"
+              title="{[{ EXIT_FULLSCREEN }]}"
+              style="display: none;"
+            >
+              <a>
+                <img class="icon icon-fullscreen-exit" src="images/pb/narrow_off.png" />
+              </a>
+            </div>
+            <el-tooltip content="清屏" show-arrow={false} offset={5}>
+              <div onClick={() => this.toggleSimpleMode(true)}>
+                <img class="icon icon-inside" src="images/pb/simple.png" title="清屏" />
+              </div>
+            </el-tooltip>
+
+            <div data-original-title="VR" id="vr" title="" style="display: none;">
+              <img class="icon icon-inside" src="images/VR.png" title="VR" />
+            </div>
+            <div
+              data-original-title="消除外壳"
+              id="gui-remove-face"
+              title=""
+              style="display: none; float: left;"
+            >
+              <img class="icon icon-inside" src="images/face.jpg" />
+            </div>
+          </div>
+        </div>
+        <div class="pinBottom right">
+          <div id="volume" class="ui-icon wide" style="display: none">
+            <a>
+              <img
+                src="images/Volume btn_on.png"
+                width="24"
+                height="24"
+                data-default-url="images/Volume btn_on.png"
+                data-active-url="images/Volume btn_off.png"
+              />
+            </a>
+          </div>
+          <div id="vr" class="ui-icon wide hidden">
+            <a>
+              <i title="{[{ VIEW_IN_VR }]}" class="icon icon-webvr"></i>
+            </a>
+          </div>
+        </div>
+
+        <div
+          class={['pinBottom-exit-simple', { active: this.isSimpleMode }]}
+          onClick={() => this.toggleSimpleMode(false)}
+        >
+          退出清屏
+        </div>
+
+        <SharePopup visible={this.shareVisible} onUpdate:visible={(v) => (this.shareVisible = v)} />
+      </div>
+    );
+  },
+});

BIN
src/index/views/home/images/home.png


BIN
src/index/views/home/images/viewer.png


+ 117 - 0
src/index/views/home/index.pb.scss

@@ -0,0 +1,117 @@
+@use '@/assets/utils.scss';
+
+.home {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  overflow: hidden;
+
+  &-viewer {
+    position: absolute;
+    top: utils.vh-calc(30);
+    left: utils.vw-calc(30);
+    width: utils.vw-calc(260);
+    height: utils.vw-calc(70);
+    background: url('./images/viewer.png') no-repeat center / contain;
+    z-index: 1;
+
+    span {
+      position: absolute;
+      right: utils.vw-calc(20);
+      bottom: utils.vw-calc(7);
+      color: #e0b387;
+      font-size: utils.vw-calc(22);
+      width: utils.vw-calc(85);
+      text-align: center;
+    }
+  }
+  &_img {
+    position: absolute;
+    top: utils.vh-calc(30);
+    right: utils.vw-calc(30);
+    width: utils.vw-calc(168);
+    height: utils.vw-calc(100);
+    cursor: pointer;
+    z-index: 1;
+  }
+  &_logo {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    position: absolute;
+    left: 50%;
+    bottom: 20px;
+    width: 300px;
+    text-align: center;
+    font-size: 14px;
+    transform: translateX(-50%);
+    color: rgba(255, 255, 255, 0.8);
+
+    img {
+      width: 50%;
+    }
+    span {
+      font-size: 16px;
+      padding: 5px 0;
+      color: rgba(255, 255, 255, 0.8);
+      border-bottom: 1px solid rgba(255, 255, 255, 0.8);
+    }
+  }
+}
+
+#player {
+  position: absolute;
+  left: 0;
+  bottom: 0;
+  width: 100%;
+  height: 100%;
+
+  canvas {
+    position: relative;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+  }
+}
+
+#hot {
+  position: absolute;
+  padding: 0;
+  width: 100%;
+  height: 100%;
+  pointer-events: none;
+
+  > div[pos='right'] {
+    transform: translate(20px, -50%);
+  }
+  > div[pos='top'] {
+    transform: translate(-50%, calc(-100% - 20px));
+  }
+  > div[pos='middle'] {
+    transform: translate(-50%, -50%);
+  }
+  > div[pos='bottom'] {
+    transform: translate(-50%, 20px);
+  }
+  > div[pos='left'] {
+    transform: translate(calc(-100% - 20px), -50%);
+  }
+  > div {
+    position: absolute;
+    color: #fff;
+    user-select: none;
+    border-radius: 5px;
+    background-color: rgba(34, 34, 34, 0.3);
+    padding: 10px;
+    max-width: 400px;
+    letter-spacing: 1px;
+    line-height: 20px;
+    z-index: var(--z-index-top);
+  }
+}
+
+@media only screen and (max-width: 600px) {
+}

+ 138 - 0
src/index/views/home/index.pb.tsx

@@ -0,0 +1,138 @@
+import { defineComponent, onMounted, 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/index.pb';
+import GuiLoading from './components/gui-loading';
+import Popup from './components/popup';
+import HotSpotList from './components/hot-spot-list';
+import Img from './images/home.png';
+import './index.pb.scss';
+import { useRouter } from 'vue-router';
+import { homeApi } from '@/api';
+
+// 自定义热点图标
+// @ts-ignore
+// window.hoticon = {
+//   default: '/images/point.png',
+//   higt: '/images/point2.png',
+// };
+
+export default defineComponent({
+  name: 'home',
+  components: {
+    Title,
+    WebVr,
+    Other,
+    Vrcon,
+    GuiLoading,
+    JsScript,
+    Popup,
+  },
+  setup() {
+    const router = useRouter();
+    const manageJsLoaded = ref(false);
+    const hotJsLoaded = ref(false);
+    const visitCount = ref(0);
+    const likeCount = ref(0);
+
+    const getSceneDetail = async () => {
+      const { data } = await homeApi.getSceneDetail(window.number);
+      if (!data) return;
+      visitCount.value = data.visitSum;
+      likeCount.value = data.starSum;
+    };
+
+    const handleLikeCounter = (num: number) => {
+      likeCount.value += num;
+    };
+
+    onMounted(() => {
+      getSceneDetail();
+
+      homeApi.saveSceneVisit(window.number);
+    });
+
+    return {
+      router,
+      manageJsLoaded,
+      hotJsLoaded,
+      visitCount,
+      likeCount,
+      handleLikeCounter,
+    };
+  },
+  render() {
+    return (
+      <div class="home">
+        {/* 进度条加载 */}
+        <GuiLoading />
+
+        <div class="home-viewer">
+          <span class="limit-line">{this.visitCount}</span>
+        </div>
+
+        <img class="home_img" src={Img} onClick={() => this.router.replace({ name: 'cover' })} />
+
+        {/* 加载初始页面 */}
+        <div id="gui-thumb" />
+
+        {/* 热点弹出框 */}
+        <Popup />
+
+        {/* 场景canvs主容器 */}
+        <div id="player" />
+
+        {/* 底部菜单 */}
+        <div id="gui-parent">
+          {/* 热点气泡 */}
+          <div id="hot" />
+
+          <div id="gui" style="display: none;">
+            {/* 标题 */}
+            <Title style={{ display: 'none' }} />
+
+            {/* 热点列表 */}
+            <HotSpotList />
+
+            {/* 底部菜单 */}
+            <Menu likeCount={this.likeCount} handleLikeCounter={this.handleLikeCounter} />
+
+            {/* 导览 */}
+            <Guide />
+
+            {/* <div class="home_logo">
+              <img src="images/btm_logo.png" />
+              <span>提供技术支持</span>
+            </div> */}
+          </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>
+    );
+  },
+});

+ 1 - 0
vite.config.ts

@@ -70,6 +70,7 @@ export default defineConfig(() => {
             importStyle: 'sass',
             importStyle: 'sass',
           }),
           }),
         ],
         ],
+        include: [/\.vue$/, /\.vue\?vue/, /\.jsx$/, /\.tsx$/],
       }),
       }),
     ],
     ],
     resolve: {
     resolve: {