chenlei 8 ماه پیش
والد
کامیت
5b1f28bb36
29فایلهای تغییر یافته به همراه7950 افزوده شده و 8550 حذف شده
  1. 0 5
      components.d.ts
  2. 3 0
      package.json
  3. 7296 8545
      pnpm-lock.yaml
  4. BIN
      public/favicon/favicon-syjy.ico
  5. BIN
      public/images/syjy/icon-hot-min.png
  6. BIN
      src/assets/images/syjy/icon-back-1-min.png
  7. BIN
      src/assets/images/syjy/icon-back-min.png
  8. BIN
      src/assets/images/syjy/icon-daolan-1-min.png
  9. BIN
      src/assets/images/syjy/icon-daolan-min.png
  10. BIN
      src/assets/images/syjy/icon-dingbu-1-min.png
  11. BIN
      src/assets/images/syjy/icon-dingbu-min.png
  12. BIN
      src/assets/images/syjy/icon-home-1-min.png
  13. BIN
      src/assets/images/syjy/icon-home-min.png
  14. BIN
      src/assets/images/syjy/icon-manyou-1-min.png
  15. BIN
      src/assets/images/syjy/icon-manyou-min.png
  16. BIN
      src/assets/images/syjy/icon-mini-1-min.png
  17. BIN
      src/assets/images/syjy/icon-mini-min.png
  18. BIN
      src/assets/images/syjy/icon-quanjing-1-min.png
  19. BIN
      src/assets/images/syjy/icon-quanjing-min.png
  20. BIN
      src/assets/images/syjy/icon-redian-1-min.png
  21. BIN
      src/assets/images/syjy/icon-redian-min.png
  22. BIN
      src/assets/images/syjy/icon-share-1-min.png
  23. BIN
      src/assets/images/syjy/icon-share-min.png
  24. BIN
      src/assets/images/syjy/icon-shengyin-1-min.png
  25. BIN
      src/assets/images/syjy/icon-shengyin-min.png
  26. 238 0
      src/views/home/components/menu/index.syjy.scss
  27. 209 0
      src/views/home/components/menu/index.syjy.vue
  28. 99 0
      src/views/home/index.syjy.scss
  29. 105 0
      src/views/home/index.syjy.tsx

+ 0 - 5
components.d.ts

@@ -7,14 +7,9 @@ export {}
 
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
-    ElCollapse: typeof import('element-plus/es')['ElCollapse']
-    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
-    ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
-    ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
     ElImage: typeof import('element-plus/es')['ElImage']
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
-    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
   }

+ 3 - 0
package.json

@@ -9,6 +9,9 @@
     "serve:zgrs": "cross-env SCENE=zgrs TITLE=光大汇晨养老 HOT_DOMAIN=/hotspot.html vue-cli-service serve",
     "build:zgrs:test": "cross-env SCENE=zgrs TITLE=光大汇晨养老 HOT_DOMAIN=/zgrs-hotspot.html vue-cli-service build",
     "push:zgrs": "cross-env SCENE=zgrs node ./scripts/publish.js",
+    "serve:syjy": "cross-env SCENE=syjy TITLE=中国民族博物馆-三亚家园线上展厅 HOT_DOMAIN=/hotspot.html vue-cli-service serve",
+    "build:syjy:test": "cross-env SCENE=syjy TITLE=中国民族博物馆-三亚家园线上展厅 HOT_DOMAIN=/syjy-hotspot.html vue-cli-service build",
+    "push:syjy": "cross-env SCENE=syjy node ./scripts/publish.js",
     "lint": "vue-cli-service lint",
     "prepare": "husky install"
   },

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7296 - 8545
pnpm-lock.yaml


BIN
public/favicon/favicon-syjy.ico


BIN
public/images/syjy/icon-hot-min.png


BIN
src/assets/images/syjy/icon-back-1-min.png


BIN
src/assets/images/syjy/icon-back-min.png


BIN
src/assets/images/syjy/icon-daolan-1-min.png


BIN
src/assets/images/syjy/icon-daolan-min.png


BIN
src/assets/images/syjy/icon-dingbu-1-min.png


BIN
src/assets/images/syjy/icon-dingbu-min.png


BIN
src/assets/images/syjy/icon-home-1-min.png


BIN
src/assets/images/syjy/icon-home-min.png


BIN
src/assets/images/syjy/icon-manyou-1-min.png


BIN
src/assets/images/syjy/icon-manyou-min.png


BIN
src/assets/images/syjy/icon-mini-1-min.png


BIN
src/assets/images/syjy/icon-mini-min.png


BIN
src/assets/images/syjy/icon-quanjing-1-min.png


BIN
src/assets/images/syjy/icon-quanjing-min.png


BIN
src/assets/images/syjy/icon-redian-1-min.png


BIN
src/assets/images/syjy/icon-redian-min.png


BIN
src/assets/images/syjy/icon-share-1-min.png


BIN
src/assets/images/syjy/icon-share-min.png


BIN
src/assets/images/syjy/icon-shengyin-1-min.png


BIN
src/assets/images/syjy/icon-shengyin-min.png


+ 238 - 0
src/views/home/components/menu/index.syjy.scss

@@ -0,0 +1,238 @@
+.pinBottom-container {
+  position: absolute;
+  bottom: 0px;
+  width: 100%;
+  transition: all 0.5s;
+  z-index: var(--z-index-top);
+
+  .pinBottom.playing {
+    bottom: 20px;
+  }
+}
+
+.pinBottom.open.noScroll.playing {
+  bottom: 175px;
+}
+
+.pinBottom {
+  position: absolute;
+  bottom: 0;
+  line-height: 1;
+  transition: all 0.5s;
+
+  &.left {
+    left: 0;
+    width: 450px;
+    height: 67px;
+    background: url('@/assets/images/zgrs/Subtract-min.png') no-repeat center right / contain;
+  }
+  &.right {
+    right: 40px;
+    bottom: 10px;
+  }
+  &.open {
+    bottom: 155px;
+
+    &.playing {
+      bottom: 165px;
+    }
+  }
+}
+
+.viewContainer,
+.rightViewContainer,
+#gui-modes-map {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+  height: 100%;
+}
+
+.viewContainer {
+  padding-left: 35px;
+}
+
+#play,
+#pause {
+  cursor: pointer;
+
+  img {
+    width: 57px;
+    height: 57px;
+  }
+}
+
+#pullTab,
+.helper-btn,
+.good-btn,
+.hotList,
+#gui-modes-dollhouse,
+#gui-modes-floorplan,
+#volume,
+#sharing {
+  display: block;
+  width: 57px;
+  height: 57px;
+  cursor: pointer;
+}
+
+#pullTab {
+  background: url('@/assets/images/zgrs/auto-suspend.png') no-repeat center / contain;
+
+  &.opened {
+    background-image: url('@/assets/images/zgrs/auto.png');
+  }
+}
+
+.hotList {
+  background: url('@/assets/images/zgrs/hotlist.png') no-repeat center / contain;
+
+  &.active {
+    background-image: url('@/assets/images/zgrs/hotlist-active.png');
+  }
+}
+
+#gui-modes-dollhouse {
+  background: url('@/assets/images/zgrs/dollhouse.png') no-repeat center / contain;
+
+  &.active {
+    background-image: url('@/assets/images/zgrs/dollhouse-active.png');
+  }
+}
+
+#gui-modes-floorplan {
+  background: url('@/assets/images/zgrs/floor.png') no-repeat center / contain;
+
+  &.active {
+    background-image: url('@/assets/images/zgrs/floor-active.png');
+  }
+}
+
+#volume {
+  background: url('@/assets/images/zgrs/Volume btn_off.png') no-repeat center / contain;
+
+  &.active {
+    background-image: url('@/assets/images/zgrs/Volume btn_on.png');
+  }
+}
+
+#sharing {
+  background: url('@/assets/images/zgrs/share.png') no-repeat center / contain;
+}
+
+.helper-btn {
+  background: url('@/assets/images/zgrs/helper.png') no-repeat center / contain;
+}
+
+.good-btn {
+  position: relative;
+
+  &.active div {
+    background-image: url('@/assets/images/zgrs/good-active.png');
+  }
+  div {
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    width: 58px;
+    height: 67px;
+    transition: background-image 0.3s ease-in-out;
+    background: url('@/assets/images/zgrs/good.png') no-repeat center / contain;
+  }
+  span {
+    position: absolute;
+    top: -9px;
+    left: 50%;
+    font-size: 12px;
+    color: white;
+    transform: translateX(-50%);
+  }
+}
+
+.terms2 {
+  display: none;
+}
+
+@media only screen and (max-width: 600px) {
+  .pinBottom {
+    &.open {
+      bottom: 122px;
+
+      &.noScroll.playing {
+        bottom: 142px;
+      }
+    }
+    &.open.right {
+      bottom: 152px;
+
+      &.noScroll.playing {
+        bottom: 172px;
+      }
+    }
+    &.left {
+      width: 100%;
+      height: 55px;
+
+      .viewContainer {
+        padding-left: 15px;
+      }
+    }
+    &.right {
+      right: 13px;
+      bottom: 30px;
+
+      &.playing {
+        bottom: 50px;
+      }
+      .rightViewContainer {
+        flex-direction: column;
+
+        .helper-btn,
+        #sharing,
+        #volume,
+        .good-btn {
+          width: 47px;
+          height: 47px;
+        }
+        .good-btn {
+          &.active {
+            div {
+              background-image: url('@/assets/images/zgrs/good-active-m.png');
+            }
+          }
+          div {
+            width: 47px;
+            height: 54px;
+            background-image: url('@/assets/images/zgrs/good-m.png');
+          }
+          span {
+            top: -7px;
+          }
+        }
+        .helper-btn {
+          background-image: url('@/assets/images/zgrs/helper-m.png');
+        }
+        #sharing {
+          background-image: url('@/assets/images/zgrs/share-m.png');
+        }
+        #volume {
+          background-image: url('@/assets/images/zgrs/Volume btn_off-m.png');
+
+          &.active {
+            background-image: url('@/assets/images/zgrs/Volume btn_on-m.png');
+          }
+        }
+      }
+    }
+  }
+  #play img,
+  #pause img,
+  #gui-modes-map > div,
+  .hotList {
+    width: 47px;
+    height: 47px;
+  }
+  #gui-modes-map {
+    gap: 5px;
+  }
+}

+ 209 - 0
src/views/home/components/menu/index.syjy.vue

@@ -0,0 +1,209 @@
+<template>
+  <div class="pinBottom-container">
+    <div class="pinBottom left">
+      <div class="viewContainer">
+        <div id="previous" class="previous desktop-only ui-icon" style="display: none">
+          <a>
+            <img :src="PauseIcon" width="24" height="24" data-original-title="播放" />
+          </a>
+        </div>
+        <div id="play" class="ui-icon" data-original-title="播放">
+          <a>
+            <img :src="PauseIcon" width="24" height="24" title="播放" />
+          </a>
+        </div>
+        <div id="pause" class="ui-icon" style="display: none">
+          <a>
+            <img title="暂停" :src="PlayIcon" 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>
+        <div id="gui-modes-map" class="ui-icon double active">
+          <div data-original-title="导览" id="pullTab" title="导览" />
+
+          <div id="hotList" class="hidden" />
+          <el-dropdown
+            trigger="click"
+            placement="top"
+            popper-class="scene-title-popper"
+            @visible-change="(v: boolean) => (hotspotActive = v)"
+          >
+            <div
+              data-original-title="热点列表"
+              class="hotList"
+              title="热点列表"
+              :class="{ active: hotspotActive }"
+            ></div>
+
+            <template #dropdown>
+              <hot-spot-list />
+            </template>
+          </el-dropdown>
+          <div
+            data-original-title="迷你模型"
+            id="gui-modes-dollhouse"
+            title="迷你模型"
+            class=""
+          ></div>
+          <div data-original-title="俯视图" id="gui-modes-floorplan" title="俯视图"></div>
+          <div data-original-title="VR" id="vr" title="" style="display: none"></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>
+    <div class="pinBottom right hideTarget">
+      <div class="rightViewContainer clearfix">
+        <div class="helper-btn" title="指引" @click="openHelper"></div>
+        <div class="good-btn" title="点赞" :class="{ active: staring }" @click="handleStar">
+          <div />
+          <span v-if="staring">{{ staringString }}</span>
+        </div>
+        <div id="sharing" class="ui-icon wide" title="分享" @click="copyUrl"></div>
+        <div id="volume" class="ui-icon wide" style="display: none"></div>
+        <div id="vr" class="ui-icon wide hidden" style="display: none">
+          <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 }]}"
+          style="display: none"
+        >
+          <a>
+            <i class="icon icon-fullscreen"></i>
+          </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>
+          </a>
+        </div>
+        <div class="pull-right terms terms2"></div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+  import { computed, onMounted, onUnmounted, ref } from 'vue';
+  import clipboard from 'clipboard';
+  import PlayIcon from '@/assets/images/zgrs/play.png';
+  import PauseIcon from '@/assets/images/zgrs/pause.png';
+  import { homeApi } from '@/api';
+  import HotSpotList from '../hot-spot-list';
+
+  let helperVisible = false;
+  const hotspotActive = ref(false);
+  const starSum = ref(0);
+  const staring = ref(false);
+  const staringString = computed(() => {
+    const value = starSum.value;
+    if (value >= 10000) {
+      return `${Math.floor(value / 10000)}w+`;
+    } else if (value >= 1000) {
+      return `${Math.floor(value / 1000)}k+`;
+    } else {
+      return value.toString();
+    }
+  });
+
+  const copyUrl = () => {
+    clipboard.copy(window.location.href);
+
+    ElNotification({
+      title: '提示',
+      type: 'success',
+      message: '链接已复制',
+      position: 'bottom-right',
+    });
+  };
+
+  const openHelper = () => {
+    window
+      .$('#interaction-modal')
+      // @ts-ignore
+      .addClass(`fadeIn ${window.browser.isMobile() ? 'mobile' : 'desktop'}`);
+    helperVisible = true;
+  };
+
+  const closeHelper = () => {
+    window.$('#interaction-modal').removeClass('fadeIn');
+    helperVisible = false;
+  };
+
+  const handleKeydown = () => {
+    helperVisible && closeHelper();
+  };
+  const handleClick = (e: MouseEvent | TouchEvent) => {
+    const clickedElement = e.target;
+    // @ts-ignore
+    const modalElement = clickedElement?.closest('#interaction-modal');
+    // @ts-ignore
+    const btnElement = clickedElement?.closest('.helper-btn');
+    if (!modalElement && !btnElement && helperVisible) {
+      closeHelper();
+    }
+  };
+
+  const getDetail = async () => {
+    const { data } = await homeApi.getSceneDetail(window.number);
+
+    if (!data) return;
+    starSum.value = data.starSum;
+  };
+
+  const handleStar = async () => {
+    if (staring.value) return;
+
+    staring.value = true;
+    starSum.value++;
+
+    try {
+      await homeApi.saveStar(window.number);
+
+      setTimeout(() => {
+        staring.value = false;
+      }, 1000);
+    } catch (err) {
+      starSum.value--;
+    }
+  };
+
+  onMounted(() => {
+    getDetail();
+
+    window.addEventListener('keydown', handleKeydown);
+    window.addEventListener('click', handleClick);
+    window.addEventListener('touchmove', handleClick);
+  });
+
+  onUnmounted(() => {
+    window.removeEventListener('keydown', handleKeydown);
+    window.removeEventListener('click', handleClick);
+    window.removeEventListener('touchmove', handleClick);
+  });
+</script>
+
+<style lang="scss" scoped>
+  @import './index.zgrs.scss';
+</style>

+ 99 - 0
src/views/home/index.syjy.scss

@@ -0,0 +1,99 @@
+.home {
+  width: 100%;
+  height: 100%;
+
+  &__back {
+    position: fixed;
+    top: 30px;
+    left: 30px;
+    cursor: pointer;
+    z-index: var(--z-index-top);
+  }
+  &_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) {
+  .home {
+    &__back {
+      top: 12px;
+      left: 12px;
+      width: 35px;
+      height: 35px;
+      z-index: 1001;
+    }
+  }
+}

+ 105 - 0
src/views/home/index.syjy.tsx

@@ -0,0 +1,105 @@
+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 BackIcon from '@/assets/images/zgrs/back.png';
+import './index.zgrs.scss';
+
+// @ts-ignore
+window.hoticon = {
+  default: '/images/zgrs/point.png',
+  higt: '/images/zgrs/point2.png',
+};
+
+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">
+        <img
+          class="home__back"
+          src={BackIcon}
+          onClick={() => {
+            window.location.href = 'https://houseoss.4dkankan.com/project/GDHCYL/home/index.html';
+          }}
+        />
+
+        {/* 进度条加载 */}
+        <GuiLoading />
+
+        {/* 加载初始页面 */}
+        <div id="gui-thumb" />
+
+        {/* 热点弹出框 */}
+        <Popup />
+
+        {/* 场景canvs主容器 */}
+        <div id="player" />
+
+        {/* 底部菜单 */}
+        <div id="gui-parent">
+          {/* 热点气泡 */}
+          <div id="hot" />
+
+          <div id="gui" style="display: none;">
+            {/* 标题 */}
+            {/* @ts-ignore */}
+            <Title isInit={this.manageJsLoaded} />
+
+            {/* 底部菜单 */}
+            <Menu />
+
+            {/* 导览 */}
+            <Guide />
+          </div>
+
+          <WebVr />
+          <Vrcon />
+          <Other />
+        </div>
+
+        {/* TODO: 没有控制权,耦合严重;放在此处为了防止元素未渲染导致报错 */}
+        <JsScript src="/js/manage.js" onLoad={() => (this.manageJsLoaded = true)} />
+        {this.manageJsLoaded && (
+          <>
+            <JsScript src="/js/Hot.js" onLoad={() => (this.hotJsLoaded = true)} />
+            {this.hotJsLoaded && (
+              <>
+                <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>
+    );
+  },
+});