Przeglądaj źródła

Merge branch 'release/1.5.0'

gemercheung 2 lat temu
rodzic
commit
c74211d222
70 zmienionych plików z 8011 dodań i 61750 usunięć
  1. 1 1
      packages/qjkankan-editor/.env.eurprod
  2. 1 1
      packages/qjkankan-editor/.env.eurtestprod
  3. 2 1
      packages/qjkankan-editor/.env.prod
  4. 1 1
      packages/qjkankan-editor/.env.testprod
  5. 0 38364
      packages/qjkankan-editor/package-lock.json
  6. 1 0
      packages/qjkankan-editor/package.json
  7. 2 2
      packages/qjkankan-editor/public/edit.html
  8. 8 5
      packages/qjkankan-editor/src/components/materialListInMaterialSelector.vue
  9. 2 2
      packages/qjkankan-editor/src/components/materialSelectorFromWork.vue
  10. 68 0
      packages/qjkankan-editor/src/directives/vTitleInEditor.js
  11. 456 0
      packages/qjkankan-editor/src/framework/play/pano/components/list copy.vue
  12. 173 59
      packages/qjkankan-editor/src/framework/play/pano/components/list.vue
  13. 4 1
      packages/qjkankan-editor/src/framework/show/list.vue
  14. 2 1
      packages/qjkankan-editor/src/lang/_en.json
  15. 2 1
      packages/qjkankan-editor/src/lang/_zh.json
  16. 1 1
      packages/qjkankan-editor/src/mixins/debuggerHelper.js
  17. 1 0
      packages/qjkankan-editor/src/views/hotspot/hotspotType/pdf.vue
  18. 1 1
      packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue
  19. 2 2
      packages/qjkankan-editor/src/views/material/image/image.js
  20. 41 14
      packages/qjkankan-editor/src/views/material/popup/share.vue
  21. 2 2
      packages/qjkankan-kankan-view/.env.development
  22. 2 2
      packages/qjkankan-kankan-view/.env.testprod
  23. 2 2
      packages/qjkankan-kankan-view/.env.testserve
  24. 0 17918
      packages/qjkankan-kankan-view/package-lock.json
  25. 3 2
      packages/qjkankan-kankan-view/package.json
  26. 5 4
      packages/qjkankan-kankan-view/public/smg.html
  27. 3 3
      packages/qjkankan-kankan-view/public/spg.html
  28. 2 3
      packages/qjkankan-kankan-view/src/components/Controls/Panel/Main.vue
  29. 2 3
      packages/qjkankan-kankan-view/src/components/Controls/tours.mobile.vue
  30. 2 3
      packages/qjkankan-kankan-view/src/components/Controls/tours.vue
  31. 87 12
      packages/qjkankan-kankan-view/src/components/Tags/index.vue
  32. 229 0
      packages/qjkankan-kankan-view/src/components/Tags/metas/metas-video copy.vue
  33. 240 179
      packages/qjkankan-kankan-view/src/components/Tags/old.vue
  34. 702 0
      packages/qjkankan-kankan-view/src/components/Tags/share/entry.vue
  35. 491 227
      packages/qjkankan-kankan-view/src/components/Tags/show-tag.vue
  36. 1 11
      packages/qjkankan-kankan-view/src/components/Tags/tag-view.vue
  37. 240 214
      packages/qjkankan-kankan-view/src/components/shared/Guide.vue
  38. 119 69
      packages/qjkankan-kankan-view/src/pages/SMG.vue
  39. 18 10
      packages/qjkankan-kankan-view/src/pages/SPG.vue
  40. 2 1
      packages/qjkankan-view/.env.eurprod
  41. 1 0
      packages/qjkankan-view/.env.eurtestdev
  42. 2 1
      packages/qjkankan-view/.env.eurtestprod
  43. 1 1
      packages/qjkankan-view/.env.prod
  44. 1 1
      packages/qjkankan-view/.env.testdev
  45. 1 1
      packages/qjkankan-view/.env.testprod
  46. 1 0
      packages/qjkankan-view/package.json
  47. 5 4
      packages/qjkankan-view/public/showMobile.html
  48. 20 7
      packages/qjkankan-view/src/components/Fdkk/index.vue
  49. 2 0
      packages/qjkankan-view/src/components/Pano/index.vue
  50. 2 2
      packages/qjkankan-view/src/components/UIGather/control.vue
  51. 209 69
      packages/qjkankan-view/src/components/UIGather/list.vue
  52. 2 2
      packages/qjkankan-view/src/components/UIGather/logo.vue
  53. 151 67
      packages/qjkankan-view/src/components/UIGather/menu.vue
  54. 4 4
      packages/qjkankan-view/src/components/UIGather/mobile/control.fdkk.vue
  55. 162 61
      packages/qjkankan-view/src/components/UIGather/mobile/list.vue
  56. 100 54
      packages/qjkankan-view/src/components/UIGather/mobile/menu.vue
  57. 4 4
      packages/qjkankan-view/src/components/UIGather/mobile/tips.vue
  58. 2 3
      packages/qjkankan-view/src/components/UIGather/mobile/tours.vue
  59. 17 8
      packages/qjkankan-view/src/components/UIGather/tips.vue
  60. 10 2
      packages/qjkankan-view/src/components/UIGather/tours.vue
  61. 1 1
      packages/qjkankan-view/src/components/assembly/Share.vue
  62. 16 2
      packages/qjkankan-view/src/hooks/useAudio.js
  63. 1 1
      packages/qjkankan-view/src/hooks/useWxshared.js
  64. 0 63
      packages/qjkankan-view/src/locales/zh copy.json
  65. 5 1
      packages/qjkankan-view/src/pages/show.vue
  66. 5 2
      packages/qjkankan-view/src/pages/showMobile.vue
  67. 9 1
      packages/qjkankan-view/src/store/modules/audio.js
  68. 1 1
      packages/qjkankan-view/src/utils/debuggerHelper.js
  69. 19 19
      packages/qjkankan-view/src/utils/wxshare.js
  70. 4336 4246
      yarn.lock

+ 1 - 1
packages/qjkankan-editor/.env.eurprod

@@ -8,4 +8,4 @@ VUE_APP_PROXY_URL='https://eur.4dkankan.com/qjkankan/'
 VUE_APP_ORIGIN=aws
 
 VUE_APP_URL_FILL=/qjkankan
-VUE_APP_DEBBUG_FLAG=0529-01
+VUE_APP_DEBBUG_FLAG=0824-01

+ 1 - 1
packages/qjkankan-editor/.env.eurtestprod

@@ -8,4 +8,4 @@ VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
 VUE_APP_ORIGIN=aws
 
 VUE_APP_URL_FILL=/qjkankan
-VUE_APP_DEBBUG_FLAG=0516-01
+VUE_APP_DEBBUG_FLAG=0824-01

+ 2 - 1
packages/qjkankan-editor/.env.prod

@@ -7,4 +7,5 @@ VUE_APP_PROXY_URL_ROOT='https://www.4dkankan.com'
 VUE_APP_PROXY_URL='https://www.4dkankan.com/qjkankan/'
 VUE_APP_ORIGIN=
 VUE_APP_URL_FILL=/qjkankan
-VUE_APP_DEBBUG_FLAG=0627-01
+VUE_APP_DEBBUG_FLAG=0824-01
+VUE_APP_DEBBUG_NOTIFY=0

+ 1 - 1
packages/qjkankan-editor/.env.testprod

@@ -7,5 +7,5 @@ VUE_APP_PROXY_URL_ROOT='https://test.4dkankan.com'
 VUE_APP_PROXY_URL='https://test.4dkankan.com/qjkankan/'
 VUE_APP_ORIGIN=
 VUE_APP_URL_FILL=/qjkankan
-VUE_APP_DEBBUG_FLAG=0626-02
+VUE_APP_DEBBUG_FLAG=0807-01
 VUE_APP_DEBBUG_NOTIFY=0

Plik diff jest za duży
+ 0 - 38364
packages/qjkankan-editor/package-lock.json


+ 1 - 0
packages/qjkankan-editor/package.json

@@ -37,6 +37,7 @@
     "vue-cropperjs": "^4.2.0",
     "vue-demi": "^0.14.5",
     "vue-i18n": "^8.22.3",
+    "vue-marquee-text-component": "1.2.0",
     "vue-photo-preview": "^1.1.3",
     "vue-router": "^3.4.9",
     "vue-toast-notification": "^3.1.1",

+ 2 - 2
packages/qjkankan-editor/public/edit.html

@@ -18,7 +18,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/animate/animate.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/mCustomScrollbar/jquery.mCustomScrollbar.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.css"/>
-    <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper.min.css" />
+    <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper-bundle.min.css" />
 
     <title>-</title>
   </head>
@@ -30,7 +30,7 @@
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/quill/quill.min.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/mCustomScrollbar/jquery.mCustomScrollbar.concat.min.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.min.js"></script>
-    <script src="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper.min.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper-bundle.min.js"></script>
 
   </body>
 </html>

+ 8 - 5
packages/qjkankan-editor/src/components/materialListInMaterialSelector.vue

@@ -37,6 +37,7 @@
         >
         </span>
       </div> -->
+
       <div
         v-show="listLocalLength !== 0 || hasMoreData"
         class="table-body"
@@ -287,7 +288,7 @@
             alt=""
           />
           <span>{{ $i18n.t("gather.no_material_result") }}</span>
-          <a v-if="!canUpload" href="/#/">
+          <a v-if="!canUpload" href="/#/" target="_blank">
             <button class="ui-button">
               {{ $i18n.t("gather.how_to_shoot") }}
             </button>
@@ -548,7 +549,6 @@ export default {
           this.longPollingIntervalId = null;
           // 最后上传成功能状态
           if (!newVal && oldValue) {
-            // debugger;
             this.refreshMaterialList();
           }
         } else {
@@ -666,12 +666,15 @@ export default {
           });
 
         const res = new Map();
-
+        const lastItem = this.folderPath[this.folderPath.length - 1];
         const latestUploadlist = this.uploadStatusList
           .concat(uploadlist)
-          .filter((a) => !res.has(a.backendId) && res.set(a.backendId, 1));
+          .filter((a) => !res.has(a.backendId) && res.set(a.backendId, 1))
+          .filter((i) => i.parentFolderId === lastItem.id);
         console.log("latestUploadlist", latestUploadlist);
-        // console.log("origin-list", this.list);
+
+        console.log("lastItem", lastItem);
+
         const capitalizedMaterialType = capitalize(this.materialType);
         this.$store.commit(
           `setUploadStatusList${capitalizedMaterialType}`,

+ 2 - 2
packages/qjkankan-editor/src/components/materialSelectorFromWork.vue

@@ -43,7 +43,7 @@
 
     <div class="table table-pano" v-show="currentMaterialType === 'pano'">
       <div v-show="panoList.length !== 0" class="table-body">
-       <!-- 测试数据-- {{
+        <!-- 测试数据-- {{
           panoList.map((i) => {
             let t = {};
             t["id"] = i.id;
@@ -104,7 +104,7 @@
       <div v-show="scene3DList.length !== 0" class="table-body">
         <div
           class="table-body-row"
-          v-for="(item) in scene3DList"
+          v-for="item in scene3DList"
           :key="`${item.id}`"
           @click="onClickRow"
         >

+ 68 - 0
packages/qjkankan-editor/src/directives/vTitleInEditor.js

@@ -83,4 +83,72 @@ Vue.directive("title", {
     el.addEventListener("dragover", removeTitle);
     el.addEventListener("dragleave", removeTitle);
   },
+  update: function (el, binding) {
+    removeTitle();
+    if (!binding.value) {
+      return;
+    }
+    el.addEventListener(
+      "mousemove",
+      function (e) {
+        if (!isShowTitle) {
+          clearTimeout(timerId);
+          timerId = setTimeout(() => {
+            isShowTitle = true;
+
+            titleNode = document.createElement("div");
+
+            titleNode.style.position = "fixed";
+            titleNode.style.zIndex = 2147483647;
+            titleNode.style.backgroundColor = "#191A1C";
+            titleNode.style.borderRadius = "2px";
+            titleNode.style.border = "1px solid rgba(151, 151, 151, 0.2)";
+            titleNode.style.padding = "2px 6px";
+            titleNode.style.fontSize = "12px";
+            titleNode.style.color = "rgba(255, 255, 255, 0.6)";
+            titleNode.innerText = binding.value;
+            titleNode.style.left = e.clientX + 11 + "px";
+            titleNode.style.top = e.clientY + 18 + "px";
+
+            document.body.appendChild(titleNode);
+
+            if (
+              e.clientX + 11 + titleNode.offsetWidth >
+              document.documentElement.clientWidth
+            ) {
+              titleNode.style.left =
+                document.documentElement.clientWidth -
+                titleNode.offsetWidth +
+                "px";
+            }
+            if (
+              e.clientY + 18 + titleNode.offsetHeight >
+              document.documentElement.clientHeight
+            ) {
+              titleNode.style.top =
+                document.documentElement.clientHeight -
+                titleNode.offsetHeight +
+                "px";
+            }
+
+            intervalId = setInterval(() => {
+              if (!document.contains(el)) {
+                removeTitle();
+              }
+            }, 300);
+          }, 500);
+        }
+      },
+      {
+        passive: false,
+      }
+    );
+
+    el.addEventListener("mouseleave", removeTitle);
+    el.addEventListener("mousedown", removeTitle);
+    el.addEventListener("keydown", removeTitle);
+    el.addEventListener("scroll", removeTitle);
+    el.addEventListener("dragover", removeTitle);
+    el.addEventListener("dragleave", removeTitle);
+  },
 });

+ 456 - 0
packages/qjkankan-editor/src/framework/play/pano/components/list copy.vue

@@ -0,0 +1,456 @@
+<template>
+  <div class="bar-list" v-if="show" :class="{ disable: isEditing }">
+    <div
+      class="top-con"
+      v-show="currentScenesList.length > 0"
+      :style="`width:${
+        Math.max(scenesListW, secondaryW) > 1150
+          ? '100%'
+          : Math.max(scenesListW, secondaryW) + 120 + 'px'
+      }`"
+    >
+      <div
+        class="swiper-container"
+        :style="`width:${scenesListW > 1150 ? '100%' : scenesListW + 'px'}`"
+        id="swScenes"
+        ref="sw"
+        v-swiper:mySwiper="swiperOptions"
+        v-if="currentScenesList.length > 0"
+      >
+        <ul class="swiper-wrapper">
+          <li
+            v-tooltip="
+              item.type === '4dkk' ? $i18n.t('navigation.scene_edit_tips') : ''
+            "
+            @click="tabCurrentScene(item)"
+            class="swiper-slide"
+            :class="{
+              active: currentScene.id == item.id,
+              loopspan:
+                item.sceneTitle.length > spanlength &&
+                currentScene.id == item.id,
+            }"
+            :style="{ backgroundImage: `url(${item.icon})` }"
+            v-for="(item, i) in currentScenesList"
+            :key="item.id"
+          >
+            <i
+              class="iconfont icon-edit_type_3d"
+              :class="{ iconedit_type_panorama: item.type !== '4dkk' }"
+            ></i>
+            <div>
+              <span v-if="currentScene.id == item.id">{{
+                item.sceneTitle
+              }}</span>
+              <span v-else>{{
+                item.sceneTitle.length > spanlength
+                  ? item.sceneTitle.slice(0, spanlength)
+                  : item.sceneTitle
+              }}</span>
+            </div>
+          </li>
+        </ul>
+      </div>
+
+      <div
+        class="swiper-container"
+        :style="`width:${Math.min(secondaryW, innerW)}px`"
+        id="swSecondary"
+        ref="sw1"
+        v-swiper:mySwipera="swiperOptions"
+        v-if="
+          !(
+            secondaryList.length === 1 &&
+            (secondaryList[0].name === '默认二级分组' ||
+              secondaryList[0].name === $i18n.t('navigation.default_group_two'))
+          )
+        "
+      >
+        <ul class="swiper-wrapper">
+          <li
+            class="swiper-slide"
+            @click="tabSecondary(item)"
+            :class="{
+              active: currentSecondary.id == item.id,
+              loopspan:
+                fixTitle(item.name).length > spanlength &&
+                currentSecondary.id == item.id,
+            }"
+            v-for="(item, i) in secondaryList"
+            :key="i"
+          >
+            <span v-if="currentSecondary.id == item.id">{{
+              fixTitle(item.name)
+            }}</span>
+            <span v-else>{{
+              fixTitle(item.name).length > spanlength
+                ? fixTitle(item.name).slice(0, spanlength)
+                : fixTitle(item.name)
+            }}</span>
+          </li>
+        </ul>
+      </div>
+    </div>
+
+    <div
+      class="swiper-container"
+      :style="`width:${catalogRootW > innerW ? '100%' : catalogRootW + 'px'}`"
+      id="swcatalogRoot"
+      ref="sw2"
+      v-swiper:mySwiperb="swiperOptions"
+      v-if="metadata.catalogRoot.length > 0 && metadata.catalogs.length > 1"
+    >
+      <ul class="swiper-wrapper" v-if="metadata.catalogRoot.length > 1">
+        <li
+          class="swiper-slide"
+          :class="{
+            active: currentCatalogRoot.id == item.id,
+            loopspan:
+              fixTitle(item.name).length > spanlength &&
+              currentCatalogRoot.id == item.id,
+          }"
+          @click="tabRoot(item)"
+          v-for="(item, i) in metadata.catalogRoot"
+          :key="i"
+        >
+          <span v-if="currentCatalogRoot.id == item.id">{{
+            fixTitle(item.name)
+          }}</span>
+          <span v-else>{{
+            fixTitle(item.name).length > spanlength
+              ? fixTitle(item.name).slice(0, spanlength)
+              : fixTitle(item.name)
+          }}</span>
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+import { directive } from "vue-awesome-swiper";
+// import style (<= Swiper 5.x)
+import "swiper/css/swiper.css";
+
+export default {
+  data() {
+    return {
+      spanlength: 6,
+      show: false,
+      innerW: 1150,
+      swidth: {
+        swcatalogRoot: 104,
+        swSecondary: 84,
+        swScenes: 72,
+      },
+    };
+  },
+  directives: {
+    swiper: directive,
+  },
+
+  watch: {
+    currentSecondary() {
+      this.loadList();
+    },
+    currentScenesList() {
+      this.loadList();
+    },
+    metadata: {
+      deep: true,
+      handler: function (newVal) {
+        if (newVal.scenes) {
+          this.$store.commit("scene/setScenes", newVal.scenes);
+          if (!this.show) {
+            this.show = true;
+            this.loadList();
+          } else {
+            // 更新列表
+            this.tabRoot(this.currentCatalogRoot);
+          }
+        }
+      },
+    },
+  },
+  computed: {
+    ...mapGetters({
+      metadata: "scene/metadata",
+      scenes: "scene/list",
+      currentScene: "scene/currentScene",
+      currentCatalogRoot: "scene/currentCatalogRoot",
+      currentSecondary: "scene/currentSecondary",
+      secondaryList: "scene/secondaryList",
+      isShowScenesList: "scene/isShowScenesList",
+      currentScenesList: "scene/currentScenesList",
+      isEditing: "isEditing",
+    }),
+
+    scenesListW() {
+      return this.currentScenesList.length * (this.swidth["swScenes"] + 10);
+    },
+    secondaryW() {
+      return this.secondaryList.length * (this.swidth["swSecondary"] + 10);
+    },
+    catalogRootW() {
+      return (
+        this.metadata.catalogRoot.length * (this.swidth["swcatalogRoot"] + 10)
+      );
+    },
+    swiperOptions() {
+      return {
+        slidesPerView: "auto",
+        centeredSlides: true,
+        centerInsufficientSlides: true,
+        centeredSlidesBounds: true,
+        freeMode: {
+          enabled: true,
+          sticky: false,
+        },
+      };
+    },
+  },
+  methods: {
+    fixTitle(name) {
+      if (name == "默认二级分组") {
+        name = this.$i18n.t("navigation.default_group_two");
+      } else if (name == "一级分组") {
+        name = this.$i18n.t("navigation.group_one");
+      } else {
+        name = name;
+      }
+      return name;
+    },
+    loadList() {
+      this.$nextTick(() => {
+        // let t = setTimeout(() => {
+        //   clearTimeout(t);
+        //   ["#swcatalogRoot", "#swSecondary", "#swScenes"].forEach((item) => {
+        //     new Swiper(item, {
+        //       slidesPerView: "auto",
+        //       spaceBetween: 10,
+        //       centeredSlides: true,
+        //       centerInsufficientSlides: true,
+        //       centeredSlidesBounds: true,
+        //       freeMode: true,
+        //     });
+        //   });
+        // }, 100);
+      });
+    },
+
+    tabCurrentScene(data) {
+      this.$store.commit("scene/setCurrentScene", data);
+    },
+
+    tabSecondary(data) {
+      this.$store.commit("scene/setCurrentSecondary", data);
+    },
+
+    tabRoot(data) {
+      this.$store.commit("scene/setCurrentCatalogRoot", data);
+    },
+  },
+
+  mounted() {
+    // console.log(this.metadata,'metadata');
+    // this.loadList();
+  },
+};
+</script>
+
+<style lang="less" scoped>
+@width: 1150px;
+
+.bar-list {
+  position: absolute;
+  bottom: 28px;
+  left: 50%;
+  transform: translateX(-50%);
+  text-align: center;
+  max-width: @width;
+  overflow: hidden;
+  transition: 0.3s all ease;
+  .swiper-container {
+    width: 100%;
+    position: relative;
+
+    > ul {
+      margin: 0 auto;
+      > li {
+        margin: 0 5px;
+        white-space: nowrap;
+
+        > span,
+        > div > span {
+          cursor: pointer;
+          display: inline-block;
+          color: rgba(255, 255, 255, 0.6);
+        }
+
+        &.loopspan {
+          > span,
+          > div > span {
+            animation: 5s wordsLoop linear infinite normal;
+          }
+        }
+
+        &.active {
+          > span,
+          > div > span {
+            color: rgba(255, 255, 255, 1);
+          }
+        }
+      }
+    }
+  }
+
+  .top-con {
+    margin: 0 auto 10px;
+    padding: 10px 0;
+    background: linear-gradient(
+      268deg,
+      rgba(0, 0, 0, 0) 0%,
+      rgba(0, 0, 0, 0.4) 25%,
+      rgba(0, 0, 0, 0.4) 75%,
+      rgba(0, 0, 0, 0) 100%
+    );
+  }
+
+  #swcatalogRoot {
+    > ul {
+      > li {
+        width: 104px;
+        background: rgba(0, 0, 0, 0.5);
+        border-radius: 4px;
+        padding: 4px 10px;
+        border: 1px solid rgba(255, 255, 255, 0.5);
+        box-sizing: border-box;
+        overflow: hidden;
+
+        > span {
+          width: 100%;
+          word-break: keep-all;
+        }
+
+        &.active {
+          border: 1px solid rgba(255, 255, 255, 1);
+        }
+      }
+    }
+  }
+
+  #swSecondary {
+    margin: 20px auto 10px;
+
+    > ul {
+      > li {
+        width: 84px;
+        box-sizing: border-box;
+        overflow: hidden;
+        padding-bottom: 6px;
+
+        > span {
+          width: 100%;
+          word-break: keep-all;
+        }
+
+        &.active {
+          position: relative;
+
+          &::before {
+            content: "";
+            display: inline-block;
+            position: absolute;
+            bottom: 0;
+            width: 20px;
+            height: 2px;
+            z-index: 9999;
+            left: 50%;
+            transform: translateX(-50%);
+            background: @color;
+          }
+        }
+      }
+    }
+  }
+
+  #swScenes {
+    > ul {
+      > li {
+        cursor: pointer;
+        width: 72px;
+        height: 72px;
+        border-radius: 6px;
+        border: 1px solid #ffffff;
+        background-size: cover;
+        position: relative;
+        overflow: hidden;
+
+        .iconfont {
+          position: absolute;
+          left: 4px;
+          top: 4px;
+          z-index: 99;
+
+          &::after {
+            background: rgba(0, 0, 0, 0.3);
+            content: "";
+            width: 14px;
+            height: 14px;
+            display: inline-block;
+            position: absolute;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            z-index: -1;
+            filter: blur(4px);
+          }
+        }
+
+        > div {
+          position: absolute;
+          bottom: 0;
+          left: 0;
+          height: 20px;
+          background: rgba(0, 0, 0, 0.5);
+          width: 100%;
+          overflow: hidden;
+
+          > span {
+            width: 100%;
+            line-height: 20px;
+            word-break: keep-all;
+          }
+        }
+
+        &.active {
+          border: 1px solid @color;
+
+          > div {
+            > span {
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+.barshow {
+  max-height: 520px;
+}
+
+@keyframes wordsLoop {
+  0% {
+    transform: translateX(100%);
+    -webkit-transform: translateX(100%);
+  }
+
+  100% {
+    transform: translateX(-100%);
+    -webkit-transform: translateX(-100%);
+  }
+}
+</style>

+ 173 - 59
packages/qjkankan-editor/src/framework/play/pano/components/list.vue

@@ -6,7 +6,7 @@
       :style="`width:${
         Math.max(scenesListW, secondaryW) > 1150
           ? '100%'
-          : Math.max(scenesListW, secondaryW) + 120 + 'px'
+          : Math.max(scenesListW, secondaryW) + 'px'
       }`"
     >
       <div
@@ -14,7 +14,6 @@
         :style="`width:${scenesListW > 1150 ? '100%' : scenesListW + 'px'}`"
         id="swScenes"
         ref="sw"
-        v-swiper:mySwiper="swiperOptions"
         v-if="currentScenesList.length > 0"
       >
         <ul class="swiper-wrapper">
@@ -26,9 +25,9 @@
             class="swiper-slide"
             :class="{
               active: currentScene.id == item.id,
-              loopspan:
-                item.sceneTitle.length > spanlength &&
-                currentScene.id == item.id,
+              // loopspan:
+              //   item.sceneTitle.length > spanlength &&
+              //   currentScene.id == item.id,
             }"
             :style="{ backgroundImage: `url(${item.icon})` }"
             v-for="(item, i) in currentScenesList"
@@ -38,7 +37,7 @@
               class="iconfont icon-edit_type_3d"
               :class="{ iconedit_type_panorama: item.type !== '4dkk' }"
             ></i>
-            <div>
+            <!-- <div>
               <span v-if="currentScene.id == item.id">{{
                 item.sceneTitle
               }}</span>
@@ -47,6 +46,22 @@
                   ? item.sceneTitle.slice(0, spanlength)
                   : item.sceneTitle
               }}</span>
+            </div> -->
+            <div class="marquee">
+              <marquee-text
+                :repeat="1"
+                :duration="Math.ceil(item.sceneTitle.length / 10) * 5"
+                :key="item.id"
+                v-if="
+                  item.sceneTitle.length > spanlength &&
+                  currentScene.id == item.id
+                "
+              >
+                {{ item.sceneTitle }}
+              </marquee-text>
+              <span v-else>
+                {{ item.sceneTitle }}
+              </span>
             </div>
           </li>
         </ul>
@@ -54,10 +69,9 @@
 
       <div
         class="swiper-container"
-        :style="`width:${secondaryW}px`"
+        :style="`width:${Math.min(secondaryW, innerW)}px`"
         id="swSecondary"
         ref="sw1"
-        v-swiper:mySwipera="swiperOptions"
         v-if="
           !(
             secondaryList.length === 1 &&
@@ -79,14 +93,20 @@
             v-for="(item, i) in secondaryList"
             :key="i"
           >
-            <span v-if="currentSecondary.id == item.id">{{
-              fixTitle(item.name)
-            }}</span>
-            <span v-else>{{
-              fixTitle(item.name).length > spanlength
-                ? fixTitle(item.name).slice(0, spanlength)
-                : fixTitle(item.name)
-            }}</span>
+          <marquee-text
+              :duration="Math.ceil(fixTitle(item.name).length / 10) * 5"
+              :key="item.id"
+              :repeat="1"
+              v-if="
+                fixTitle(item.name).length > spanlength &&
+                currentSecondary.id == item.id
+              "
+            >
+              {{ fixTitle(item.name) }}
+            </marquee-text>
+            <span v-else>
+              {{ fixTitle(item.name) }}
+            </span>
           </li>
         </ul>
       </div>
@@ -97,7 +117,6 @@
       :style="`width:${catalogRootW > innerW ? '100%' : catalogRootW + 'px'}`"
       id="swcatalogRoot"
       ref="sw2"
-      v-swiper:mySwiperb="swiperOptions"
       v-if="metadata.catalogRoot.length > 0 && metadata.catalogs.length > 1"
     >
       <ul class="swiper-wrapper" v-if="metadata.catalogRoot.length > 1">
@@ -113,14 +132,20 @@
           v-for="(item, i) in metadata.catalogRoot"
           :key="i"
         >
-          <span v-if="currentCatalogRoot.id == item.id">{{
-            fixTitle(item.name)
-          }}</span>
-          <span v-else>{{
-            fixTitle(item.name).length > spanlength
-              ? fixTitle(item.name).slice(0, spanlength)
-              : fixTitle(item.name)
-          }}</span>
+        <marquee-text
+            :duration="Math.ceil(fixTitle(item.name).length / 10) * 5"
+            :key="item.id"
+            :repeat="1"
+            v-if="
+              fixTitle(item.name).length > spanlength &&
+              currentCatalogRoot.id == item.id
+            "
+          >
+            {{ fixTitle(item.name) }}
+          </marquee-text>
+          <span v-else>
+            {{ fixTitle(item.name) }}
+          </span>
         </li>
       </ul>
     </div>
@@ -129,12 +154,11 @@
 
 <script>
 import { mapGetters } from "vuex";
-
-import { directive } from "vue-awesome-swiper";
-// import style (<= Swiper 5.x)
-import "swiper/css/swiper.css";
+import { debounce } from "lodash";
+import MarqueeText from "vue-marquee-text-component";
 
 export default {
+  components: { MarqueeText },
   data() {
     return {
       spanlength: 6,
@@ -147,16 +171,41 @@ export default {
       },
     };
   },
-  directives: {
-    swiper: directive,
-  },
 
   watch: {
-    currentSecondary() {
-      this.loadList();
+    "metadata.catalogRoot": function (val) {
+      if (val.length > 0) {
+        this.initMainSwiper();
+      } else {
+        if (window.mainNatSwiper) {
+          window.mainNatSwiper.destroy();
+          window.mainNatSwiper = null;
+        }
+      }
+    },
+    currentSecondary(val) {},
+    secondaryList(val) {
+      if (val.length > 1) {
+        console.log("secondaryList", val);
+        this.initsencordNatSwiper();
+      } else {
+        if (window.sencordNatSwiper) {
+          window.sencordNatSwiper.destroy();
+          window.sencordNatSwiper = null;
+        }
+      }
     },
-    currentScenesList() {
-      this.loadList();
+    currentScenesList(val) {
+      // this.loadList();
+      if (val.length > 0) {
+        // console.warn("initScenesSwiper", val);
+        this.initScenesSwiper();
+      } else {
+        if (window.scenesNatSwiper) {
+          window.scenesNatSwiper.destroy();
+          window.scenesNatSwiper = null;
+        }
+      }
     },
     metadata: {
       deep: true,
@@ -165,7 +214,6 @@ export default {
           this.$store.commit("scene/setScenes", newVal.scenes);
           if (!this.show) {
             this.show = true;
-            this.loadList();
           } else {
             // 更新列表
             this.tabRoot(this.currentCatalogRoot);
@@ -204,7 +252,10 @@ export default {
         centeredSlides: true,
         centerInsufficientSlides: true,
         centeredSlidesBounds: true,
-        freeMode: true,
+        freeMode: {
+          enabled: true,
+          sticky: false,
+        },
       };
     },
   },
@@ -215,44 +266,107 @@ export default {
       } else if (name == "一级分组") {
         name = this.$i18n.t("navigation.group_one");
       } else {
+        // eslint-disable-next-line no-self-assign
         name = name;
       }
       return name;
     },
-    loadList() {
-      this.$nextTick(() => {
-        // let t = setTimeout(() => {
-        //   clearTimeout(t);
-        //   ["#swcatalogRoot", "#swSecondary", "#swScenes"].forEach((item) => {
-        //     new Swiper(item, {
-        //       slidesPerView: "auto",
-        //       spaceBetween: 10,
-        //       centeredSlides: true,
-        //       centerInsufficientSlides: true,
-        //       centeredSlidesBounds: true,
-        //       freeMode: true,
-        //     });
-        //   });
-        // }, 100);
-      });
-    },
-
+    loadList: debounce(function () {
+      // console.log("hello", this.$refs);
+      this.$nextTick(() => {});
+    }, 200),
     tabCurrentScene(data) {
       this.$store.commit("scene/setCurrentScene", data);
+      this.scenesSwiperFocus();
     },
 
     tabSecondary(data) {
       this.$store.commit("scene/setCurrentSecondary", data);
+      this.sencordNatSwiperFocus();
     },
 
     tabRoot(data) {
       this.$store.commit("scene/setCurrentCatalogRoot", data);
+      this.mainNatSwiperFocus();
+    },
+    initMainSwiper() {
+      this.$nextTick(() => {
+        console.warn("initMainSwiper");
+        if (window.mainNatSwiper) {
+          window.mainNatSwiper = null;
+        }
+        window.mainNatSwiper = new window.Swiper(
+          "#swcatalogRoot",
+          this.swiperOptions
+        );
+      });
+    },
+    mainNatSwiperFocus() {
+      this.$nextTick(() => {
+        console.warn(
+          "catalogRoot-mainNatSwiperFocus",
+          this.metadata.catalogRoot
+        );
+        const current = Array.from(this.metadata.catalogRoot).findIndex(
+          (item) => item.id === this.currentCatalogRoot.id
+        );
+        if (window.mainNatSwiper && this.metadata.catalogRoot.length > 1) {
+          const index = current < 0 ? 0 : current;
+          window.mainNatSwiper.slideTo(index);
+        }
+      });
+    },
+    initsencordNatSwiper() {
+      this.$nextTick(() => {
+        if (window.sencordNatSwiper) {
+          window.sencordNatSwiper = null;
+        }
+        window.sencordNatSwiper = new window.Swiper(
+          "#swSecondary",
+          this.swiperOptions
+        );
+        this.sencordNatSwiperFocus();
+      });
+    },
+    sencordNatSwiperFocus() {
+      this.$nextTick(() => {
+        const current = Array.from(this.secondaryList).findIndex(
+          (item) => item.id === this.currentSecondary.id
+        );
+        if (window.sencordNatSwiper) {
+          const index = current < 0 ? 0 : current;
+          window.sencordNatSwiper.slideTo(index);
+        }
+      });
+    },
+    initScenesSwiper() {
+      this.$nextTick(() => {
+        if (window.scenesNatSwiper) {
+          window.scenesNatSwiper = null;
+        }
+        window.scenesNatSwiper = new window.Swiper(
+          "#swScenes",
+          this.swiperOptions
+        );
+
+        this.scenesSwiperFocus();
+      });
+    },
+    scenesSwiperFocus() {
+      const sceneIndex = Array.from(this.currentScenesList).findIndex(
+        (item) => item.id === this.currentScene.id
+      );
+      if (window.scenesNatSwiper) {
+        const index = sceneIndex < 0 ? 0 : sceneIndex;
+        window.scenesNatSwiper.slideTo(index);
+      }
     },
   },
 
   mounted() {
     // console.log(this.metadata,'metadata');
     // this.loadList();
+    // this.initMainSwiper();
   },
 };
 </script>
@@ -272,6 +386,7 @@ export default {
   .swiper-container {
     width: 100%;
     position: relative;
+    margin: 0 auto;
 
     > ul {
       margin: 0 auto;
@@ -444,10 +559,9 @@ export default {
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
   }
 }
 </style>

+ 4 - 1
packages/qjkankan-editor/src/framework/show/list.vue

@@ -169,7 +169,10 @@ export default {
         centeredSlides: true,
         centerInsufficientSlides: true,
         centeredSlidesBounds: true,
-        freeMode: true,
+        freeMode: {
+          enabled: true,
+          sticky: false,
+        },
       };
     },
   },

+ 2 - 1
packages/qjkankan-editor/src/lang/_en.json

@@ -747,7 +747,8 @@
     "material": "Material",
     "name": "Title",
     "fileSize": "Size",
-    "detail": "Resolution",
+    "detail": "",
+    "dpi": "Resolution",
     "createTime": "Created",
     "updateTime": "Modified"
   },

+ 2 - 1
packages/qjkankan-editor/src/lang/_zh.json

@@ -747,7 +747,8 @@
     "material": "素材",
     "name": "名称",
     "fileSize": "大小",
-    "detail": "分辨率",
+    "detail": "",
+    "dpi": "分辨率",
     "createTime": "创建时间",
     "updateTime": "修改时间"
   },

+ 1 - 1
packages/qjkankan-editor/src/mixins/debuggerHelper.js

@@ -1,6 +1,6 @@
 import Vue from "vue";
 export const debuggerHelper = (show = true) => {
-  const version = "1.4.0--" + process.env.VUE_APP_DEBBUG_FLAG;
+  const version = "1.5.0--" + process.env.VUE_APP_DEBBUG_FLAG;
   if (show) {
     // log.setColors({
     var css = "background: #28b561; color:#fff;font-size:14px;padding:5px;";

+ 1 - 0
packages/qjkankan-editor/src/views/hotspot/hotspotType/pdf.vue

@@ -43,6 +43,7 @@ export default {
   methods: {
     del() {
       this.hotspot.pdfInfo = {};
+      this.$refs["file-input"].value = "";
     },
     onClickSelect() {
       this.$refs["file-input"].click();

+ 1 - 1
packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue

@@ -17,7 +17,7 @@
       </div>
       <div class="right-wrap">
         <button class="ui-button submit" @click="showScene = true">{{$i18n.t('hotspot.change_scene')}}</button>
-        <div class="scene-title" v-title="selected.sceneTitle">{{selected.sceneTitle}}</div>
+        <div class="scene-title" v-title="selected.sceneTitle" >{{selected.sceneTitle}}</div>
       </div>
     </div>
     

+ 2 - 2
packages/qjkankan-editor/src/views/material/image/image.js

@@ -27,8 +27,8 @@ let data = [
   },
   {
     key: 'dpi',
-    name: 'detail',
-    en: 'detail',
+    name: 'dpi',
+    en: 'dpi',
     width: 120,
   },
   {

+ 41 - 14
packages/qjkankan-editor/src/views/material/popup/share.vue

@@ -1,8 +1,11 @@
 <template>
   <popup v-if="show">
-    <div class="ui-message ui-message-confirm message-material" style="width: 500px">
+    <div
+      class="ui-message ui-message-confirm message-material"
+      style="width: 500px"
+    >
       <div class="ui-message-header header-material">
-        <span>{{share}}</span>
+        <span>{{ share }}</span>
         <span @click="$emit('close')">
           <i class="iconfont icon-close"></i>
         </span>
@@ -10,11 +13,19 @@
       <div class="ui-message-main">
         <ul>
           <li>
-            <span>{{work_link}}</span>
-            <input :title="item.share+`&lang=${$lang}`" class="ui-input" disabled type="text" maxlength="15"  v-model="item.share" />
+            <span>{{ work_link }}</span>
+            <input
+              :title="item.share + `&vr=${defaultscenesCode}&lang=${$lang}`"
+              class="ui-input"
+              disabled
+              type="text"
+              maxlength="15"
+              v-model="item.share"
+            />
           </li>
           <li>
-            <span>{{work_qrCode}}</span>
+            <span>{{ work_qrCode }} </span>
+
             <img :src="item.qrCode + `?${Math.random()}` || $thumb" alt="" />
           </li>
         </ul>
@@ -22,10 +33,13 @@
 
       <div class="ui-message-footer footer-material">
         <button @click="downloadImg(item)" class="ui-button">
-          {{download_qrCode}}
+          {{ download_qrCode }}
         </button>
-        <button @click="copy(item.share+`&lang=${$lang}`)" class="ui-button submit">
-          {{copy_link}}
+        <button
+          @click="copy(item.share + `&vr=${defaultscenesCode}&lang=${$lang}`)"
+          class="ui-button submit"
+        >
+          {{ copy_link }}
         </button>
       </div>
     </div>
@@ -34,9 +48,9 @@
 
 <script>
 import Popup from "@/components/shared/popup";
-import {i18n} from "@/lang"
+import { i18n } from "@/lang";
 
-let dataUrlToBold = function(url) {
+let dataUrlToBold = function (url) {
   let arr = url.split(","),
     mime = arr[0].match(/:(.*?);/)[1],
     bStr = atob(arr[1]),
@@ -64,10 +78,21 @@ export default {
       key: "",
     };
   },
+  computed: {
+    defaultscenesCode: function () {
+      if (this.item.firstScene) {
+        return this.item.firstScene.sceneCode || "";
+      } else {
+        return Array.from(this.item.scenes).length > 0
+          ? Array.from(this.item.scenes)[0].sceneCode
+          : "";
+      }
+    },
+  },
   mounted() {},
   methods: {
     downloadImg(workItem) {
-      let val = workItem.qrCode
+      let val = workItem.qrCode;
       // var a = document.createElement("a");
       // a.download = 'qrcode';
       // a.href = 'https://4dkk.4dage.com/720yun_fd_manage/620/qrCode.jpg';
@@ -79,7 +104,7 @@ export default {
       let image = new Image();
       image.setAttribute("crossOrigin", "anonymous"); //消除跨域
       image.src = val;
-      image.onload = function() {
+      image.onload = function () {
         //借助canvas实现 消除 图片地址会先直接窗口打开图片地址
         let canvas = document.createElement("canvas");
         canvas.width = image.width;
@@ -116,9 +141,11 @@ export default {
       textArea.select();
 
       try {
-        document.execCommand("copy") ? this.$msg.success(this.$i18n.t('gather.scene_link_copy_tips')) : this.$msg.error(this.$i18n.t('gather.scene_link_copy_failed'));
+        document.execCommand("copy")
+          ? this.$msg.success(this.$i18n.t("gather.scene_link_copy_tips"))
+          : this.$msg.error(this.$i18n.t("gather.scene_link_copy_failed"));
       } catch (err) {
-        this.$msg.error(this.$i18n.t('gather.scene_link_copy_failed'));
+        this.$msg.error(this.$i18n.t("gather.scene_link_copy_failed"));
       }
 
       document.body.removeChild(textArea);

+ 2 - 2
packages/qjkankan-kankan-view/.env.development

@@ -4,8 +4,8 @@ VUE_APP_RESOURCE_URL=https://4dkk.4dage.com/
 # 静态资源地址
 VUE_APP_CDN_URL=https://4dkk.4dage.com/v4/www/
 # sdk文件地址
-VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
-# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/
+# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
+VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/
 
 
 

+ 2 - 2
packages/qjkankan-kankan-view/.env.testprod

@@ -4,9 +4,9 @@ VUE_APP_RESOURCE_URL=https://4dkk.4dage.com/
 # 静态资源地址
 VUE_APP_CDN_URL=https://4dkk.4dage.com/v4/www/
 # sdk 正式服
-VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
+# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
 # sdk 测试服
-# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/ 
+VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/ 
 
 
 

+ 2 - 2
packages/qjkankan-kankan-view/.env.testserve

@@ -4,8 +4,8 @@ VUE_APP_RESOURCE_URL=https://4dkk.4dage.com/
 # 静态资源地址
 VUE_APP_CDN_URL=https://4dkk.4dage.com/v4/www/
 # sdk文件地址
-VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
-# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/
+# VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4/www/sdk/
+VUE_APP_SDK_DIR=https://4dkk.4dage.com/v4-test/www/sdk/
 
 
 

Plik diff jest za duży
+ 0 - 17918
packages/qjkankan-kankan-view/package-lock.json


+ 3 - 2
packages/qjkankan-kankan-view/package.json

@@ -12,10 +12,11 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
-    "core-js": "^3.8.3",
-    "vue": "^3.2.36",
     "axios": "^0.21.1",
     "clipboard": "^2.0.8",
+    "core-js": "^3.8.3",
+    "qrcode": "^1.5.3",
+    "vue": "^3.2.36",
     "vue-i18n": "9",
     "vue-router": "4.0.12",
     "vuex": "^4.0.2"

+ 5 - 4
packages/qjkankan-kankan-view/public/smg.html

@@ -28,8 +28,9 @@
 
         <script src="<%= BASE_URL %><%= VUE_APP_STATIC_DIR %>/static/lib/jweixin-1.6.0.js"></script>
 
-        <!-- <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.8.4"></script>
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.8.4"></script> -->
+        <!-- <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.10.0-alpha.43"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.10.0-alpha.43"></script> -->
+
 
         <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js"></script>
         <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js"></script>
@@ -40,10 +41,10 @@
         <!-- <script src="https://eurs3.4dkankan.com/v4/cdfg/sdk/kankan-sdk-deps.js?v=4.0.0-alpha.45"></script>
         <script src="https://eurs3.4dkankan.com/v4/cdfg/sdk/kankan-sdk.js?v=4.0.0-alpha.45"></script> -->
         <!-- built files will be auto injected -->
-        <script>
+        <!-- <script>
             if ((query = window.location.href.indexOf('vlog') != -1)) {
                 var vConsole = new window.VConsole()
             }
-        </script>
+        </script> -->
     </body>
 </html>

+ 3 - 3
packages/qjkankan-kankan-view/public/spg.html

@@ -16,10 +16,10 @@
             <strong>We're sorry but doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
         </noscript>
         <div id="app"></div>
-        <!-- <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=4.8.4"></script>
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=4.8.4"></script>    -->
+        <!-- <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js?v=v=4.10.0-alpha.43"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?v=v=4.10.0-alpha.43"></script>    -->
         <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk-deps.js"></script>
-        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js?"></script>
+        <script src="<%= VUE_APP_SDK_DIR %>kankan-sdk.js"></script>
 
         <!-- built files will be auto injected -->
     </body>

+ 2 - 3
packages/qjkankan-kankan-view/src/components/Controls/Panel/Main.vue

@@ -451,10 +451,9 @@ onMounted(() => {
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
   }
 }
 

+ 2 - 3
packages/qjkankan-kankan-view/src/components/Controls/tours.mobile.vue

@@ -513,10 +513,9 @@ onMounted(() => {
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
   }
 }
 </style>

+ 2 - 3
packages/qjkankan-kankan-view/src/components/Controls/tours.vue

@@ -519,10 +519,9 @@ $width: 1150px;
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
   }
 }
 </style>

+ 87 - 12
packages/qjkankan-kankan-view/src/components/Tags/index.vue

@@ -1,17 +1,12 @@
 <template>
   <teleport :to="tags$" v-if="tags$">
     <template v-for="(tag, index) in tags">
-      <!-- <div
-                :tag-sid="tag.sid"
-                @mouseleave.prevent="onMouseLeave($event, tag)"
-                :style="{ left: `${tag.x}px`, top: `${tag.y}px`, 'z-index': hotData?.sid == tag.sid ? 1 : 0 }"
-                :class="{ visible: tag.visible || (tours.length && hotData && tours[partId].list[frameId].tagId == tag.sid && getApp().config.mobile) }"
-            > -->
       <div
         :tag-sid="tag.sid"
         @mouseleave.prevent="onMouseLeave($event, tag)"
         :style="{
-          transform: `translate3d(${tag.x}px,${tag.y}px,0)`,
+          left: `${tag.x}px`,
+          top: `${tag.y}px`,
           'z-index': hotData?.sid == tag.sid ? 1 : 0,
         }"
         :class="{
@@ -23,17 +18,26 @@
               getApp().config.mobile),
         }"
       >
+        <!-- <div
+              :tag-sid="tag.sid"
+              @mouseleave.prevent="onMouseLeave($event, tag)"
+              :style="{ transform: `translate3d(${tag.x}px,${tag.y}px,0)`, 'z-index': hotData?.sid == tag.sid ? 1 : 0 }"
+              :class="{ visible: tag.visible || (tours.length && hotData && tours[partId].list[frameId].tagId == tag.sid && getApp().config.mobile) }"
+          > -->
         <span
           class="point zoom"
           @mouseenter.prevent="onMouseEnter($event, tag, index)"
           @click.stop="goTag($event, tag, index)"
           :style="{ 'background-image': 'url(' + getUrl(tag.icon) + ')' }"
         ></span>
+        <p class="tag-title" v-if="metadata.controls.showTagTitle">
+          {{ tag.title }}
+        </p>
         <div class="content">
           <div
             class="trans"
             :class="{
-              fixed: isPlay,
+              fixed: isPlay || getApp().config.mobile,
               active:
                 (isFixed && hotData && tag.sid == hotData.sid) ||
                 (showInfo && hotData && tag.sid == hotData.sid),
@@ -48,6 +52,7 @@
                 ></ui-icon>
               </div>
               <ShowTag
+                :moveDistance="moveDistance"
                 @click.stop=""
                 v-if="!isEdit && hotData"
                 @open="openInfo"
@@ -85,6 +90,7 @@ import ShowTag from "./show-tag.vue";
 import { useRoute } from "vue-router";
 import { useMusicPlayer } from "@/utils/sound";
 import browser from "@/utils/browser";
+
 // import { Track, startTrack, endTrack } from "@/utils/track.js";
 const musicPlayer = useMusicPlayer();
 let init = true;
@@ -99,6 +105,7 @@ const hotData = computed(() => {
   }
   return data;
 });
+const metadata = computed(() => store.getters["scene/metadata"]);
 const isPlay = computed(() => store.getters["tour/isPlay"]);
 const tours = computed(() => store.getters["tour/tours"]);
 const partId = computed(() => store.getters["tour/partId"]);
@@ -159,6 +166,9 @@ const closeTag = async () => {
   if (!app.Scene.isCurrentPanoHasVideo && !player.isPlaying) {
     if (hotData.value.type == "audio" || hotData.value.type == "video") {
       // console.log('resume')
+      // if (!isPlay.value) {
+      //   musicPlayer.resume();
+      // }
       window.parent.postMessage(
         {
           source: "qjkankan",
@@ -181,6 +191,10 @@ const closeTag = async () => {
   showInfo.value = false;
 };
 const goTag = async (event, item, index) => {
+  // Track("view-tag", {
+  //   eventType: "click",
+  //   click: 1,
+  // });
   let player = await getApp().TourManager.player;
   if (isPlay.value && !event.fixed) {
     player.pause();
@@ -266,6 +280,22 @@ onMounted(async () => {
     // window.addEventListener('click', onClickHandler)
   }
 });
+
+function getElemDis(el) {
+  var tp = document.documentElement.clientTop,
+    lt = document.documentElement.clientLeft,
+    rect = el.getBoundingClientRect();
+  return {
+    bodyWidth: document.body.clientWidth,
+    bodyHight: document.body.clientHeight,
+    width: rect.width,
+    height: rect.height,
+    top: rect.top - tp,
+    right: rect.right - lt,
+    bottom: rect.bottom - tp,
+    left: rect.left - lt,
+  };
+}
 const getUrl = (icon) => {
   let url =
     icon == "" || !icon
@@ -276,7 +306,32 @@ const getUrl = (icon) => {
 };
 let __fixed = false;
 let __close = false;
+const moveDistance = ref(0);
+let moveTimer = null;
 const onMouseEnter = (event, tag, index) => {
+  if (moveTimer) {
+    clearTimeout(moveTimer);
+    moveTimer = null;
+  }
+  moveTimer = setTimeout(() => {
+    let el = document.getElementById(`tagBox_${tag.sid}`);
+    if (!el) {
+      return;
+    }
+    let data = getElemDis(el);
+    if (data.top < 0) {
+      // console.error('超出上面', Math.abs(data.top))
+      moveDistance.value = Math.abs(data.top);
+    } else if (data.bottom > data.bodyHight) {
+      // console.error('超出下面', data.bodyHight - data.bottom)
+      moveDistance.value = data.bodyHight - data.bottom;
+    } else {
+      // moveDistance.value = 0
+    }
+    clearTimeout(moveTimer);
+    moveTimer = null;
+  }, 50);
+
   if (tag.type == "audio" || tag.type == "video") {
     musicPlayer.pause(true);
   }
@@ -304,10 +359,10 @@ const onMouseEnter = (event, tag, index) => {
       !isEdit.value &&
       !positionInfo.value
     ) {
-    //   Track("view-tag", {
-    //     eventType: "hover",
-    //     hover: 1,
-    //   });
+      // Track("view-tag", {
+      //   eventType: "hover",
+      //   hover: 1,
+      // });
       showInfo.value = true;
       store.commit("tag/show", index);
 
@@ -321,6 +376,11 @@ const onMouseEnter = (event, tag, index) => {
 };
 
 const onMouseLeave = (event, tag) => {
+  if (moveTimer) {
+    clearTimeout(moveTimer);
+    moveTimer = null;
+  }
+  moveDistance.value = 0;
   if (event.unfixed) {
     __fixed = false;
     store.commit("tag/setData", { isFixed: false });
@@ -364,3 +424,18 @@ const onClickHandler = () => {
   }
 };
 </script>
+<style lang="scss" scoped>
+.tag-title {
+  position: absolute;
+  left: 50%;
+  transform: translateX(-50%);
+  top: 100%;
+  max-width: 200%;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  text-align: center;
+  pointer-events: none;
+  text-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
+}
+</style>

+ 229 - 0
packages/qjkankan-kankan-view/src/components/Tags/metas/metas-video copy.vue

@@ -0,0 +1,229 @@
+<!--  -->
+<template>
+    <!-- <div class="video-box" :style="metasHeight ? `height:${metasHeight}px;` : ''"> -->
+    <div class="video-box">
+        <div v-if="isEdit" class="del-btn" @click="delVideo()">
+            <ui-icon type="del"></ui-icon>
+        </div>
+        <ui-icon v-show="loading" class="loading-icon" type="_loading_"></ui-icon>
+        <video
+            @error="filesError"
+            v-show="!loading"
+            id="video"
+            v-for="(i, index) in videoSrc"
+            style="display: block"
+            class="video-item"
+            preload="auto"
+            controlslist="nodownload"
+            x5-video-player-type="h5"
+            playsinline
+            webkit-playsinline
+            :controls="playsinline ? true : false"
+            :muted="playsinline ? false : true"
+            :autoplay="playsinline ? true : false"
+            :src="common.changeUrl(i.src)"
+        ></video>
+        <div class="play-layer" v-if="!playsinline" @click.stop="playLayerVideo">
+            <div class="play-btn"><ui-icon type="rinfo_play"></ui-icon></div>
+        </div>
+    </div>
+    <teleport to="body">
+        <div class="layer-video" v-if="showLayerVideo" @click="showLayerVideo = false">
+            <video
+                @error="filesError"
+                v-show="!loading"
+                id="layerVideo"
+                v-for="(i, index) in videoSrc"
+                style="display: block"
+                class="video-item"
+                preload="auto"
+                controlslist="nodownload"
+                x5-video-player-type="h5"
+                playsinline
+                webkit-playsinline
+                controls
+                autoplay
+                :src="common.changeUrl(i.src)"
+            ></video>
+        </div>
+    </teleport>
+</template>
+
+<script setup>
+import { reactive, toRefs, onBeforeMount, onMounted, nextTick, ref, computed, defineProps } from 'vue'
+import { useStore } from 'vuex'
+import { custom } from '../constant.js'
+import { getApp, useApp } from '@/app'
+import common from '@/utils/common'
+import { Dialog } from '@/global_components'
+import browser from '@/utils/browser'
+const videoNum = ref(0)
+const store = useStore()
+const type = ref('video')
+const controls = ref(false)
+const showLayerVideo = ref(false)
+const hotData = computed(() => store.getters['tag/hotData'])
+const props = defineProps({
+    controls: {
+        type: Boolean,
+        default: true,
+    },
+    metasHeight: {
+        type: Number,
+        default: null,
+    },
+})
+const loading = ref(true)
+const playsinline = computed(() => {
+    let status
+    if (browser.detectAndroidMobile()) {
+        if (browser.detectWeixin() || browser.detectWeixinMiniProgram()) {
+            status = true
+        } else {
+            status = false
+        }
+    } else {
+        status = true
+    }
+
+    return status
+})
+
+const isEdit = computed(() => store.getters['tag/isEdit'])
+const videoSrc = computed(() => {
+    return hotData.value.media.video
+})
+const delVideo = () => {
+    store.commit('tag/delMetas', { type: type.value, index: videoNum.value })
+}
+
+const initVideo = file => {
+    store.commit('tag/setVideo', file)
+}
+const filesError = file => {
+    loading.value = false
+    // Dialog.toast({
+    //     content: '视频文件加载失败',
+    //     type: 'warn',
+    // })
+}
+const playLayerVideo = () => {
+    showLayerVideo.value = true
+    nextTick(() => {
+        let layerVideo = document.getElementById('layerVideo')
+        layerVideo.play()
+    })
+}
+onMounted(() => {
+    nextTick(() => {
+        let myVideo = document.getElementById('video')
+
+        myVideo.oncanplay = function () {
+            loading.value = false
+            if (playsinline.value) {
+                myVideo.play()
+            }
+        }
+        // myVideo.addEventListener('play', () => {
+        //     myVideo.requestFullscreen()
+        //     console.log('play')
+        //     myVideo.muted = true
+        // })
+        // myVideo.addEventListener('pause', () => {
+        //     console.log('play')
+        //     myVideo.muted = true
+        // })
+    })
+})
+</script>
+<style lang="scss" scoped>
+.layer-video {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    background: rgba(0, 0, 0, 0.7);
+    backdrop-filter: blur(4px);
+    z-index: 10000;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    video {
+        max-width: 100%;
+        max-height: 100%;
+        object-fit: fill;
+    }
+}
+.del-btn {
+    width: 24px;
+    height: 24px;
+    background: rgba(0, 0, 0, 0.3);
+    border-radius: 50%;
+    position: absolute;
+    cursor: pointer;
+    top: 10px;
+    right: 10px;
+    z-index: 10;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+.video-box {
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    position: absolute;
+    border-radius: 4px;
+    border: 1px solid rgba(255, 255, 255, 0.2);
+    top: 0;
+    left: 0;
+    z-index: 10;
+    .play-layer {
+        width: 100%;
+        height: 100%;
+        position: absolute;
+        top: 0;
+        left: 0;
+        z-index: 1;
+        .play-btn {
+            width: 0.8rem;
+            height: 0.8rem;
+            font-size: 0.4267rem;
+            position: absolute;
+            z-index: 100;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            border-radius: 50%;
+            // border: 0.0267rem solid #fff;
+            background: rgba(0, 0, 0, 0.7);
+            display: flex;
+            align-items: center;
+            justify-content: center;
+        }
+    }
+    .loading-icon {
+        color: var(--editor-main-color);
+        animation: rotate 2s infinite linear;
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        font-size: 30px;
+    }
+    @keyframes rotate {
+        0% {
+            transform: translate(-50%, -50%) rotate(0deg);
+        }
+        100% {
+            transform: translate(-50%, -50%) rotate(360deg);
+        }
+    }
+    .video-item {
+        width: 100%;
+        height: 100%;
+        object-fit: contain;
+    }
+}
+</style>

+ 240 - 179
packages/qjkankan-kankan-view/src/components/Tags/old.vue

@@ -1,213 +1,274 @@
 <template>
-    <teleport :to="tags$" v-if="tags$">
-        <template v-for="(tag, index) in tags">
-            <div :tag-sid="tag.sid" @mouseleave="onMouseLeave($event, tag)" :style="{ left: tag.x + 'px', top: tag.y + 'px' }" :class="{ visible: tag.visible }">
-                <span @click.stop="goTag(tag, index)" class="point zoom" @mouseenter.stop="onMouseEnter(tag, index)" :style="{ 'background-image': 'url(' + getUrl(tag.icon) + ')' }"></span>
-                <div class="content">
-                    <div class="trans" :class="{ active: (isFixed && hotData && tag.sid == hotData.sid) || (showInfo && hotData && tag.sid == hotData.sid) }">
-                        <template v-if="hotData && tag.sid == hotData.sid && !showMsg">
-                            <div class="arrow" :id="`arrow_${tag.sid}`">
-                                <ui-icon @click.stop="closeTag" v-if="getApp().config.mobile" type="close"></ui-icon>
-                            </div>
-                            <ShowTag @click.stop="" v-if="!isEdit && hotData" @open="openInfo" />
-                        </template>
-                    </div>
-                </div>
-                <TagView @click.stop="" v-if="showMsg && toggleIndex == index" @close="closeInfo" />
-            </div>
-        </template>
-    </teleport>
+  <teleport :to="tags$" v-if="tags$">
+    <template v-for="(tag, index) in tags">
+      <div
+        :tag-sid="tag.sid"
+        @mouseleave="onMouseLeave($event, tag)"
+        :style="{ left: tag.x + 'px', top: tag.y + 'px' }"
+        :class="{ visible: tag.visible }"
+      >
+        <span
+          @click.stop="goTag(tag, index)"
+          class="point zoom"
+          @mouseenter.stop="onMouseEnter(tag, index)"
+          :style="{ 'background-image': 'url(' + getUrl(tag.icon) + ')' }"
+        ></span>
+        <div class="content">
+          <div
+            class="trans"
+            :class="{
+              active:
+                (isFixed && hotData && tag.sid == hotData.sid) ||
+                (showInfo && hotData && tag.sid == hotData.sid),
+            }"
+          >
+            <template v-if="hotData && tag.sid == hotData.sid && !showMsg">
+              <div class="arrow" :id="`arrow_${tag.sid}`">
+                <ui-icon
+                  @click.stop="closeTag"
+                  v-if="getApp().config.mobile"
+                  type="close"
+                ></ui-icon>
+              </div>
+              <ShowTag
+                @click.stop=""
+                v-if="!isEdit && hotData"
+                @open="openInfo"
+              />
+            </template>
+          </div>
+        </div>
+        <TagView
+          @click.stop=""
+          v-if="showMsg && toggleIndex == index"
+          @close="closeInfo"
+        />
+      </div>
+    </template>
+  </teleport>
 </template>
 
 <script setup>
-import { ref, onMounted, computed, watch, watchEffect, onActivated, onDeactivated, getCurrentInstance, nextTick } from 'vue'
-import { getApp, useApp } from '@/app'
-import { useStore } from 'vuex'
-import common from '../../utils/common'
-import TagView from './tag-view.vue'
-import ShowTag from './show-tag.vue'
-import { useRoute } from 'vue-router'
-import { useMusicPlayer } from '@/utils/sound'
-const musicPlayer = useMusicPlayer()
-let init = true
+import {
+  ref,
+  onMounted,
+  computed,
+  watch,
+  watchEffect,
+  onActivated,
+  onDeactivated,
+  getCurrentInstance,
+  nextTick,
+} from "vue";
+import { getApp, useApp } from "@/app";
+import { useStore } from "vuex";
+import common from "../../utils/common";
+import TagView from "./tag-view.vue";
+import ShowTag from "./show-tag.vue";
+import { useRoute } from "vue-router";
+import { useMusicPlayer } from "@/utils/sound";
+const musicPlayer = useMusicPlayer();
+let init = true;
 const hotData = computed(() => {
-    let data = store.getters['tag/hotData']
-    if (!data) {
-        // musicPlayer.play()
-        // musicPlayer.pause(true)
-        // if (!getApp().Scene.isCurrentPanoHasVideo) {
-        //     console.log('resume')
-        //     console.log(init)
-        //     musicPlayer.resume()
-        // }
-    }
-    return data
-})
-const isPlay = computed(() => store.getters['tour/isPlay'])
-const router = computed(() => store.getters['router'])
-const flying = computed(() => store.getters['flying'])
-const leaveId = computed(() => store.getters['tag/leaveId'])
-const isEdit = computed(() => store.getters['tag/isEdit'])
-const isFixed = computed(() => store.getters['tag/isFixed'])
-const enterVisible = computed(() => store.getters['tag/enterVisible'])
-const editPosition = computed(() => store.getters['tag/editPosition'])
-const toggleIndex = computed(() => store.getters['tag/toggleIndex'])
-const isClick = computed(() => store.getters['tag/isClick'])
-const editModule = computed(() => store.getters['editModule'])
-const positionInfo = computed(() => store.getters['tag/positionInfo'])
-const store = useStore()
-const tags$ = ref(null)
+  let data = store.getters["tag/hotData"];
+  if (!data) {
+    // musicPlayer.play()
+    // musicPlayer.pause(true)
+    // if (!getApp().Scene.isCurrentPanoHasVideo) {
+    //     console.log('resume')
+    //     console.log(init)
+    //     musicPlayer.resume()
+    // }
+  }
+  return data;
+});
+const isPlay = computed(() => store.getters["tour/isPlay"]);
+const router = computed(() => store.getters["router"]);
+const flying = computed(() => store.getters["flying"]);
+const leaveId = computed(() => store.getters["tag/leaveId"]);
+const isEdit = computed(() => store.getters["tag/isEdit"]);
+const isFixed = computed(() => store.getters["tag/isFixed"]);
+const enterVisible = computed(() => store.getters["tag/enterVisible"]);
+const editPosition = computed(() => store.getters["tag/editPosition"]);
+const toggleIndex = computed(() => store.getters["tag/toggleIndex"]);
+const isClick = computed(() => store.getters["tag/isClick"]);
+const editModule = computed(() => store.getters["editModule"]);
+const positionInfo = computed(() => store.getters["tag/positionInfo"]);
+const store = useStore();
+const tags$ = ref(null);
 const tags = computed(() => {
-    return store.getters['tag/tags'] || []
-})
+  return store.getters["tag/tags"] || [];
+});
 
 watch(
-    () => router.value.name,
-    (val, old) => {
-        // console.log(val)
-        if (val !== 'tag') {
-            store.commit('tag/setFixed', false)
-        }
+  () => router.value.name,
+  (val, old) => {
+    // console.log(val)
+    if (val !== "tag") {
+      store.commit("tag/setFixed", false);
     }
-)
+  }
+);
 
-const showInfo = ref(false)
-const showMsg = ref(false)
+const showInfo = ref(false);
+const showMsg = ref(false);
 // const toggleIndex = ref(null)
 const openInfo = () => {
-    showMsg.value = true
-    store.commit('tag/setFixed', false)
-    showInfo.value = false
-}
+  showMsg.value = true;
+  store.commit("tag/setFixed", false);
+  showInfo.value = false;
+};
 const closeInfo = () => {
-    showMsg.value = false
-    if (isClick.value) {
-        //只有点击定位的才恢复显示
-        store.commit('tag/show', toggleIndex.value)
-        store.commit('tag/setFixed', true)
-        // showInfo.value = true
-        showInfo.value = false
-    }
-    // store.commit('tag/setClick', false)
-}
+  showMsg.value = false;
+  if (isClick.value) {
+    //只有点击定位的才恢复显示
+    store.commit("tag/show", toggleIndex.value);
+    store.commit("tag/setFixed", true);
+    // showInfo.value = true
+    showInfo.value = false;
+  }
+  // store.commit('tag/setClick', false)
+};
 const closeTag = async () => {
-    const app = getApp()
-    const player = await app.TourManager.player
-    //关闭热点面板时候,继续播放之前暂停的音频
-    if (!app.Scene.isCurrentPanoHasVideo && !player.isPlaying) {
-        if ( hotData.value && (hotData.value.type == 'audio' || hotData.value.type == 'video')) {
-            // console.log('resume')
-            window.parent.postMessage(
-            {
-                source: "qjkankan",
-                event: "toggleBgmStatus",
-                params: {
-                    status: true,
-                },
-            },
-            "*"
-            );
-        }
+  const app = getApp();
+  const player = await app.TourManager.player;
+  //关闭热点面板时候,继续播放之前暂停的音频
+  if (!app.Scene.isCurrentPanoHasVideo && !player.isPlaying) {
+    if (
+      hotData.value &&
+      (hotData.value.type == "audio" || hotData.value.type == "video")
+    ) {
+      // console.log('resume')
+      window.parent.postMessage(
+        {
+          source: "qjkankan",
+          event: "toggleBgmStatus",
+          params: {
+            status: true,
+          },
+        },
+        "*"
+      );
     }
+  }
 
-    store.commit('tag/setFixed', false)
-    store.commit('tag/closeTag')
-    store.commit('tag/setClick', false)
-    showInfo.value = false
-}
+  store.commit("tag/setFixed", false);
+  store.commit("tag/closeTag");
+  store.commit("tag/setClick", false);
+  showInfo.value = false;
+};
 const goTag = async (item, index) => {
-    let player = await getApp().TourManager.player
-    if (isPlay.value) {
-        player.pause()
-        store.commit('tour/setData', { isPlay: false })
-    }
-    if (flying.value) {
-        return
-    }
-    if (isFixed.value && !isEdit.value && hotData.value.sid == item.sid && !positionInfo.value) {
-        closeTag()
+  let player = await getApp().TourManager.player;
+  if (isPlay.value) {
+    player.pause();
+    store.commit("tour/setData", { isPlay: false });
+  }
+  if (flying.value) {
+    return;
+  }
+  if (
+    isFixed.value &&
+    !isEdit.value &&
+    hotData.value.sid == item.sid &&
+    !positionInfo.value
+  ) {
+    closeTag();
+  } else {
+    if (!enterVisible.value && !editPosition.value) {
+      if (!isEdit.value && !positionInfo.value) {
+        store.commit("tag/show", index);
+        store.commit("tag/setFixed", true);
+        showInfo.value = true;
+        store.commit("tag/setToggleIndex", index);
+        store.commit("tag/gotoTag", item);
+      }
+      store.commit("tag/setClick", true);
     } else {
-        if (!enterVisible.value && !editPosition.value) {
-            if (!isEdit.value && !positionInfo.value) {
-                store.commit('tag/show', index)
-                store.commit('tag/setFixed', true)
-                showInfo.value = true
-                store.commit('tag/setToggleIndex', index)
-                store.commit('tag/gotoTag', item)
-            }
-            store.commit('tag/setClick', true)
-        } else {
-            //热点可视操作
-            getApp().TagManager.edit.setTagVisi(item.sid)
-        }
+      //热点可视操作
+      getApp().TagManager.edit.setTagVisi(item.sid);
     }
-}
+  }
+};
 
 onMounted(async () => {
-    const app = await useApp()
-    await app.TagManager.tag()
-    init = false
+  const app = await useApp();
+  await app.TagManager.tag();
+  init = false;
 
-    tags$.value = '[xui_tags]'
-    app.TagManager.updatePosition(tags.value)
-    if (app.config.mobile) {
-        nextTick(() => {
-            // let player = document.querySelector('.player')
-            // player.addEventListener('touchstart', onClickHandler)
-        })
-    } else {
-        window.addEventListener('click', onClickHandler)
-    }
-})
-const getUrl = icon => {
-    let url = icon == '' || !icon ? getApp().resource.getAppURL('images/tag_icon_default.svg') : icon
+  tags$.value = "[xui_tags]";
+  app.TagManager.updatePosition(tags.value);
+  if (app.config.mobile) {
+    nextTick(() => {
+      // let player = document.querySelector('.player')
+      // player.addEventListener('touchstart', onClickHandler)
+    });
+  } else {
+    window.addEventListener("click", onClickHandler);
+  }
+});
+const getUrl = (icon) => {
+  let url =
+    icon == "" || !icon
+      ? getApp().resource.getAppURL("images/tag_icon_default.svg")
+      : icon;
 
-    return common.changeUrl(url)
-}
+  return common.changeUrl(url);
+};
 const onMouseEnter = (tag, index) => {
-    if (!getApp().config.mobile) {
-        if (flying.value || isPlay.value) {
-            return
-        }
-        if (!enterVisible.value && !editPosition.value && !isEdit.value && !positionInfo.value) {
-            // console.log('onMouseEnter')
+  if (!getApp().config.mobile) {
+    if (flying.value || isPlay.value) {
+      return;
+    }
+    if (
+      !enterVisible.value &&
+      !editPosition.value &&
+      !isEdit.value &&
+      !positionInfo.value
+    ) {
+      // console.log('onMouseEnter')
 
-            showInfo.value = true
-            store.commit('tag/show', index)
+      showInfo.value = true;
+      store.commit("tag/show", index);
 
-            store.commit('tag/setToggleIndex', index)
-            if (leaveId.value != tag.sid) {
-                //聚焦后 移到其他热点取消fixed
-                store.commit('tag/setFixed', false)
-            }
-        }
+      store.commit("tag/setToggleIndex", index);
+      if (leaveId.value != tag.sid) {
+        //聚焦后 移到其他热点取消fixed
+        store.commit("tag/setFixed", false);
+      }
     }
-}
+  }
+};
 
 const onMouseLeave = (event, tag) => {
-    if (!getApp().config.mobile) {
-        if (flying.value) {
-            return
-        }
-        if (event.relatedTarget != null) {
-            // if (!isEdit.value) {
-            showInfo.value = false
-            // }
-            store.commit('tag/setLeaveId', tag.sid)
-            if (!enterVisible.value && !isFixed.value && !showMsg.value && !editPosition.value && !positionInfo.value) {
-                closeTag()
-            }
-        }
+  if (!getApp().config.mobile) {
+    if (flying.value) {
+      return;
     }
-}
+    if (event.relatedTarget != null) {
+      // if (!isEdit.value) {
+      showInfo.value = false;
+      // }
+      store.commit("tag/setLeaveId", tag.sid);
+      if (
+        !enterVisible.value &&
+        !isFixed.value &&
+        !showMsg.value &&
+        !editPosition.value &&
+        !positionInfo.value
+      ) {
+        closeTag();
+      }
+    }
+  }
+};
 
 const onClickHandler = () => {
-    // if (flying.value) {
-    //     return
-    // }
+  // if (flying.value) {
+  //     return
+  // }
 
-    if (!isEdit.value && !positionInfo.value && isFixed.value) {
-        closeTag()
-    }
-}
+  if (!isEdit.value && !positionInfo.value && isFixed.value) {
+    closeTag();
+  }
+};
 </script>

+ 702 - 0
packages/qjkankan-kankan-view/src/components/Tags/share/entry.vue

@@ -0,0 +1,702 @@
+<!--  -->
+<template>
+  <teleport to="body">
+    <div class="share-entry" @click="closeShare()">
+      <div v-if="screenUrl" style="opacity: 0">
+        <div v-if="domShow" class="share-card" ref="takeEle">
+          <!-- <div class="bg-pic-box">
+                        <img class="bg-pic" :src="screenUrl" alt="" />
+                    </div> -->
+
+          <div class="card-content">
+            <div class="card-name">
+              <img
+                v-if="getLocale() == 'zh'"
+                crossOrigin="anonymous"
+                :src="
+                  resource.getStaticURL(
+                    `static/images/vr_space.png?t=${new Date().getTime()}`
+                  )
+                "
+                alt=""
+              />
+              <img
+                v-else
+                crossOrigin="anonymous"
+                :src="
+                  resource.getStaticURL(
+                    `static/images/vr_space_en.png?t=${new Date().getTime()}`
+                  )
+                "
+                alt=""
+              />
+            </div>
+            <p class="card-title">{{ hotData.title }}</p>
+            <div class="card-meta">
+              <img
+                v-if="hotData.type == 'image' && hotData.media['image'].length"
+                :style="
+                  imgRatio == 's'
+                    ? 'height:100%;width:auto;'
+                    : imgRatio == 'h'
+                    ? 'width:100%;height:auto;'
+                    : ''
+                "
+                class="meta-user-img"
+                :src="imgUrl"
+                crossOrigin="anonymous"
+                alt=""
+              />
+              <img
+                v-else
+                crossOrigin="anonymous"
+                class="cover-pic"
+                :src="screenUrl"
+                alt=""
+              />
+              <div class="scene-title">
+                <ui-icon :type="iconType[hotData.type]"></ui-icon
+                ><span>{{ metadata.title }}</span>
+              </div>
+            </div>
+            <span
+              v-if="hotData.content"
+              class="card-desc"
+              v-html="hotData.content"
+            ></span>
+          </div>
+          <div class="card-foot">
+            <img class="shadow-bg" src="~@/assets/images/shadow.png" alt="" />
+
+            <div class="foot-content">
+              <img
+                class="msg-pic"
+                :src="
+                  resource.getStaticURL(
+                    `static/images/bg_bottom.png?t=${new Date().getTime()}`
+                  )
+                "
+                alt=""
+              />
+
+              <div class="foot-msg">
+                <div class="qrcode-box">
+                  <canvas id="qrcode-tag"></canvas>
+                </div>
+                <div class="msg-box">
+                  <div class="foot-title">
+                    <span
+                      >{{ $t("share.scanQrCode") }}<br />{{
+                        $t("share.goVrSpace")
+                      }}</span
+                    >
+                  </div>
+                </div>
+              </div>
+
+              <div class="foot-logo">
+                <img
+                  v-if="loadingLogoFile"
+                  crossOrigin="anonymous"
+                  :style="logoSize == 's' ? 'height:100%;width:auto;' : ''"
+                  :src="loadingLogoFile"
+                  alt=""
+                />
+                <i
+                  v-else
+                  class="iconfont"
+                  :class="
+                    getLocale() == 'zh' ? 'icon-swsd__cn' : 'icon-swsd__en'
+                  "
+                ></i>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div v-if="makePicUrl" class="share-img">
+        <div class="img-header">
+          <span class="share-title">{{ $t("share.longTap") }}</span>
+          <ui-icon type="close" @click="closeShare(true)"></ui-icon>
+        </div>
+
+        <div class="img-box">
+          <img :src="makePicUrl" alt="" />
+        </div>
+        <!-- <div class="close-btn" @click="closeShare(true)">
+                    <ui-icon type="close_r"></ui-icon>
+                </div> -->
+      </div>
+      <transition
+        appear
+        name="custom-classes-transition"
+        enter-active-class="animated fadeInUp short faster"
+        leave-active-class="animated fadeOutDown short faster"
+      >
+        <div class="share-type" v-if="domShow">
+          <div class="share-button">
+            <div @click.stop="onShare">
+              <ui-icon type="download"></ui-icon>
+              <span>{{ $t("share.shareCompress") }}</span>
+            </div>
+          </div>
+          <div class="share-button">
+            <div :data-clipboard-text="LinkUrl" ref="copy$">
+              <ui-icon type="copy"></ui-icon>
+              <span>{{ $t("share.copyLink") }}</span>
+            </div>
+          </div>
+        </div>
+      </transition>
+    </div>
+  </teleport>
+</template>
+
+<script setup>
+import {
+  reactive,
+  ref,
+  toRefs,
+  onBeforeMount,
+  onMounted,
+  defineEmits,
+  computed,
+  defineProps,
+  nextTick,
+  watch,
+} from "vue";
+import { getApp } from "@/app";
+import html2canvas from "html2canvas";
+import { base64ToDataURL, blobToDataURL } from "@/utils/file";
+import QRCode from "qrcode";
+import resource from "@/utils/resource";
+import common from "@/utils/common";
+import { Dialog, Loading } from "@kankan/components";
+import ClipboardJS from "clipboard";
+import { useStore } from "vuex";
+import browser from "@/utils/browser";
+import { useI18n, getLocale } from "@/i18n";
+const { t } = useI18n({ useScope: "global" });
+const store = useStore();
+const emits = defineEmits(["closeShare"]);
+const metadata = computed(() => store.getters["scene/metadata"]);
+const loadingLogoFile = computed(() => store.getters["scene/loadingLogoFile"]);
+const screenUrl = ref(null);
+const takeEle = ref(null);
+const domShow = ref(true);
+const makePicUrl = ref(null);
+const props = defineProps({
+  hotData: {
+    type: Object,
+    default: {},
+  },
+});
+const iconType = {
+  image: "b_pic",
+  text: "b_text",
+  audio: "b_music",
+  video: "b_video",
+  link: "b_internet",
+};
+const copy$ = ref(null);
+const closeShare = (close) => {
+  if (!domShow.value && !close) {
+    return;
+  }
+  emits("closeShare");
+};
+const logoSize = ref("h");
+const onScreen = async () => {
+  const camera = getApp().Camera;
+  let thumbs = await camera.screenshot(
+    [
+      {
+        width: document.body.clientWidth,
+        height: document.body.clientHeight,
+        name: "big",
+      },
+    ],
+    false
+  );
+  screenUrl.value = base64ToDataURL(thumbs[0].data);
+  if (loadingLogoFile.value) {
+    let img = new Image();
+    img.onload = () => {
+      if (img.width <= img.height) {
+        logoSize.value = "s";
+      }
+
+      nextTick(() => {
+        initQrcode();
+      });
+    };
+
+    img.src = loadingLogoFile.value;
+  } else {
+    nextTick(() => {
+      initQrcode();
+    });
+  }
+};
+
+const onShare = () => {
+  Loading.show();
+  onScreen();
+};
+
+const LinkUrl = computed(() => {
+  let url;
+  if (browser.hasURLParam("t_id")) {
+    url = browser.changeURLArg(window.location.href, "t_id", props.hotData.sid);
+  } else {
+    url = window.location.href + `&t_id=${props.hotData.sid}`;
+  }
+  return url;
+});
+
+const initQrcode = () => {
+  var canvas = document.getElementById("qrcode-tag");
+  let url = LinkUrl.value;
+  QRCode.toCanvas(canvas, url, function (error) {
+    if (error) {
+      return;
+    }
+    nextTick(() => {
+      composePic();
+      // Loading.hide()
+    });
+  });
+};
+const imgRatio = ref(null);
+
+const imgUrl = ref(null);
+
+const setImgRatio = () => {
+  let type = props.hotData.type;
+
+  let src = null;
+  if (type == "image" && props.hotData.media[type].length) {
+    src = props.hotData.media[type][0];
+    // imgUrl.value = common.changeUrl(props.hotData.media[type][0].src)
+    imgUrl.value =
+      common.changeUrl(props.hotData.media[type][0].src).split("?").shift() +
+      `?t=${new Date().getTime()}`;
+  } else {
+    return;
+  }
+
+  let img = new Image();
+  img.onload = () => {
+    if (img.width > img.height) {
+      imgRatio.value = "h";
+    } else {
+      imgRatio.value = "s";
+    }
+  };
+  img.src = common.changeUrl(props.hotData.media[type][0].src);
+};
+const composePic = () => {
+  const ops = {
+    width: takeEle.value.clientWidth - 1,
+    height: takeEle.value.clientHeight - 1,
+    useCORS: true,
+
+    // allowTaint:true,
+    background: "#ffffff",
+    scale: window.devicePixelRatio, // 处理模糊问题
+    // dpi: 300, // 处理模糊问题
+  };
+
+  html2canvas(takeEle.value, ops).then(function (canvas) {
+    makePicUrl.value = canvas.toDataURL("image/png", 1);
+    domShow.value = false;
+    Loading.hide();
+  });
+};
+onMounted(() => {
+  nextTick(() => {
+    setImgRatio();
+    setTimeout(() => {
+      new ClipboardJS(copy$.value).on("success", function (e) {
+        e.clearSelection();
+        Dialog.toast({ content: t("toast.copySuccess"), type: "success" });
+      });
+    }, 0);
+  });
+});
+</script>
+<style lang="scss" scoped>
+$imgHeight: 2.1867rem;
+.share-img {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  padding: 0 0.5333rem;
+  .img-header {
+    width: 100%;
+    // height:2.1867rem;
+    height: 1.92rem;
+    color: rgba(255, 255, 255, 0.7);
+    font-size: 0.4267rem;
+    text-align: center;
+    position: relative;
+
+    .iconfont {
+      position: absolute;
+      top: 50%;
+      transform: translateY(-50%);
+      right: 0;
+    }
+    .share-title {
+      font-weight: 600;
+
+      line-height: 1.92rem;
+    }
+  }
+  .img-box {
+    width: 100%;
+    height: calc(100% - 1.92rem);
+    padding: 0.2667rem 0.5333rem 0.5333rem;
+    overflow: scroll;
+    position: absolute;
+    top: 1.92rem;
+    left: 0;
+    img {
+      width: 100%;
+      height: auto;
+    }
+  }
+}
+.share-card {
+  width: 89%;
+  min-height: 75%;
+  height: auto;
+  overflow: hidden;
+  position: relative;
+  margin: 0 auto;
+  &::after {
+    content: "";
+    position: absolute;
+    width: 100%;
+    height: 16%;
+    background: linear-gradient(
+      to bottom,
+      rgba(0, 0, 0, 0.5),
+      rgba(0, 0, 0, 0)
+    );
+    z-index: 1;
+  }
+  .card-name {
+    color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 100%;
+    font-size: 0.48rem;
+    margin-bottom: 0.5333rem;
+    img {
+      width: 2.1333rem;
+      height: 0.64rem;
+    }
+    .iconfont {
+      font-size: 0.64rem;
+      margin-right: 0.16rem;
+    }
+  }
+  // overflow: hidden;
+  .close-btn {
+    color: #fff;
+    margin: 0.6667rem auto;
+    width: 1.0667rem;
+    .iconfont {
+      font-size: 1.0667rem;
+    }
+  }
+  .card-foot {
+    width: 100%;
+    height: 1.6rem;
+    background: #2e2e2e;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    // z-index: 2;
+    padding: 0 0.5333rem;
+    .msg-pic {
+      width: 70%;
+      height: 100%;
+      position: absolute;
+      top: 0;
+      left: 0;
+    }
+    .foot-content {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-right: 0.2667rem;
+      color: #fff;
+      .msg-pic {
+        width: 70%;
+        height: 100%;
+        position: absolute;
+        top: 0;
+        left: 0;
+      }
+      .foot-logo {
+        width: 1.6rem;
+        height: 1.0667rem;
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+        img {
+          width: auto;
+          height: 100%;
+        }
+        .iconfont {
+          font-size: 1.6rem;
+        }
+      }
+      .foot-msg {
+        display: flex;
+        align-items: center;
+        justify-content: flex-start;
+        width: 50%;
+        height: 100%;
+        position: relative;
+
+        .qrcode-box {
+          width: 1.0667rem;
+          height: 1.0667rem;
+          background: #fff;
+          position: relative;
+          margin-right: 0.2667rem;
+          canvas {
+            width: 1.0667rem !important;
+            height: 1.0667rem !important;
+          }
+        }
+        .msg-box {
+          display: flex;
+          align-items: center;
+          justify-content: flex-start;
+          flex-flow: column;
+          .foot-title {
+            margin-bottom: 0.2133rem;
+            font-size: 0.2667rem;
+            line-height: 0.4267rem;
+          }
+        }
+      }
+    }
+    .shadow-bg {
+      width: 100%;
+      height: 0.1067rem;
+      position: absolute;
+      left: 0;
+      top: -0.1067rem;
+      z-index: 10;
+    }
+  }
+  .card-content {
+    width: 102%;
+    height: 102%;
+    background: linear-gradient(180deg, #444444 0%, #121212 100%);
+    // border-radius: 0.2667rem 0.2667rem 0px 0px;
+    z-index: 2;
+    margin-left: -1%;
+    margin-top: -1%;
+    // position: absolute;
+    // top: 0;
+    // left: 0;
+    // transform: translateX(-50%);
+    color: #fff;
+    padding: 0.8rem 0.5333rem;
+    margin-bottom: 1.6rem;
+    box-sizing: border-box;
+    display: flex;
+    flex-flow: column;
+    align-items: center;
+    justify-content: center;
+
+    .card-title {
+      font-size: 0.3733rem;
+      margin-bottom: 0.4rem;
+      line-height: 0.56rem;
+      text-align: center;
+      word-break: break-all;
+    }
+    .card-desc {
+      max-height: 20%;
+      font-size: 0.2667rem;
+      margin-bottom: 0.2667rem;
+      line-height: 0.4rem;
+      text-align: justify;
+      word-break: break-all;
+      // display: -webkit-box;
+      // -webkit-box-orient: vertical;
+      // -webkit-line-clamp: 5;
+      // white-space: pre-wrap;
+      // word-break: break-all;
+      overflow: hidden;
+    }
+    .card-meta {
+      width: 7.8667rem;
+      height: 5.8667rem;
+      position: relative;
+      border-radius: 0.0533rem;
+      overflow: hidden;
+      margin-bottom: 0.4rem;
+
+      &.img-tag {
+        background: rgba(255, 255, 255, 0.1);
+        border: 1px solid rgba(255, 255, 255, 0.2);
+      }
+      .scene-title {
+        position: absolute;
+        height: 1.0667rem;
+        bottom: -1px;
+        left: 0;
+        color: #fff;
+        display: flex;
+        align-items: center;
+        justify-content: flex-start;
+        background: linear-gradient(
+          to top,
+          rgba(0, 0, 0, 0.5),
+          rgba(0, 0, 0, 0)
+        );
+        padding: 0 0.2667rem;
+        width: 100%;
+        .iconfont {
+          font-size: 0.4267rem;
+          margin-right: 0.1333rem;
+        }
+        span {
+          font-size: 0.32rem;
+        }
+      }
+      .cover-pic {
+        position: absolute;
+        width: 100%;
+        height: auto;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+      }
+      .meta-user-img {
+        position: absolute;
+        width: 100%;
+        height: 100%;
+        // background-color: red;
+        background-repeat: no-repeat;
+        background-size: contain;
+        background-position: center;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+      }
+
+      // .meta-user-img {
+      //     position: absolute;
+      //     top: 50%;
+      //     left: 50%;
+      //     transform: translate(-50%, -50%);
+      //     width: 100%;
+      //     height: auto;
+
+      // }
+    }
+  }
+  .othor {
+    width: 43.3%;
+    height: auto;
+    background: none;
+    border: none;
+    img {
+      width: 100%;
+    }
+    .other-text {
+      font-size: 0.2667rem;
+      text-align: center;
+      margin-top: 0.2667rem;
+      width: 100%;
+      white-space: nowrap;
+    }
+  }
+  .bg-pic-box {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 1;
+    overflow: hidden;
+    .bg-pic {
+      width: 100%;
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      z-index: 1;
+    }
+  }
+}
+.share-entry {
+  width: 100%;
+  height: 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1000;
+  background: rgba(0, 0, 0, 0.8);
+  backdrop-filter: blur(4px);
+  .share-type {
+    width: 100%;
+    height: 2.6933rem;
+    background: rgba(27, 27, 28, 0.8);
+    box-shadow: inset 0px 0.0533rem 0px 0px rgba(255, 255, 255, 0.1),
+      inset 0px 0.0267rem 0px 0px #000000;
+    opacity: 1;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    border-radius: 0.2667rem;
+    color: #fff;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    &::after {
+      content: "";
+      position: absolute;
+      left: 0.0133rem;
+      right: 0.0133rem;
+      bottom: 0.0133rem;
+      top: 0.0133rem;
+      border: 0.0133rem solid rgba(255, 255, 255, 0.1);
+      border-radius: 0.2667rem;
+      z-index: 0;
+      pointer-events: none;
+    }
+    .share-button {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: 50%;
+      > div {
+        display: flex;
+        flex-flow: column;
+        align-items: center;
+        .iconfont {
+          font-size: 0.6rem;
+        }
+        > span {
+          font-size: 0.32rem;
+          margin-top: 0.2933rem;
+        }
+      }
+    }
+  }
+}
+</style>

+ 491 - 227
packages/qjkankan-kankan-view/src/components/Tags/show-tag.vue

@@ -1,267 +1,531 @@
-<!--  -->
 <template>
-    <div class="show-tag" :id="`tagBox_${hotData.sid}`">
-        <div class="tag-title">
-            <h2>
-                {{ hotData.title }}
-                <ui-audio v-if="hotData.type == 'audio' && audioInfo.length > 0" class="audio" ref="audio"
-                    :src="common.changeUrl(audioInfo[0].src)"></ui-audio>
-            </h2>
-        </div>
-        <div class="desc" v-if="hotData.content != ''">
-            <div class="text" v-html="hotData.content"></div>
-        </div>
-        <div class="tag-metas" @click.stop="open"
-            :class="{ mask: hotData.type == 'link', nocursor: hotData.type == 'video' }"
-            v-if="hotData.media[hotData.type].length > 0 && hotData.type != 'audio'">
-            <metasImage v-if="hotData.type == 'image'" />
-            <metasVideo v-if="hotData.type == 'video'" />
-            <metasWeb v-if="hotData.type == 'link'" />
-        </div>
-        <!-- <div class="edit-btn" v-if="routerName && routerName == 'tag' && !editModule">
-            <span @click="edit()"><ui-icon type="edit"></ui-icon> 修改</span>
-        </div> -->
+
+  <div
+    class="show-tag move-layer"
+    :style="`transform:translateY(${moveDistance}px);`"
+    :id="`tagBox_${hotData.sid}`"
+  >
+    <div class="show-content">
+      <!-- <div
+        class="share-box"
+        v-if="controls.showTagshare && !browser.detectApp()"
+      >
+        <ui-icon
+          type="share"
+          @mousemove="openShare(true)"
+          @mouseleave="openShare(false)"
+        ></ui-icon>
+      </div> -->
+      <div class="tag-title">
+        <h2>
+          <span :style="hotData.type == 'audio' ? '' : 'width:100%;'">
+            {{ hotData.title }}</span
+          >
+          <ui-audio
+            v-if="hotData.type == 'audio' && audioInfo.length > 0"
+            class="audio"
+            ref="audio"
+            :src="common.changeUrl(audioInfo[0].src)"
+          ></ui-audio>
+        </h2>
+      </div>
+      <div class="desc" v-if="hotData.content != ''">
+        <div class="text" v-html="hotData.content"></div>
+      </div>
+      <div
+        class="tag-metas"
+        @click.stop="open"
+        :class="{
+          mask: hotData.type == 'link',
+          nocursor: hotData.type == 'video',
+        }"
+        v-if="hotData.media[hotData.type].length > 0 && hotData.type != 'audio'"
+      >
+        <metasImage v-if="hotData.type == 'image'" />
+        <metasVideo v-if="hotData.type == 'video'" />
+        <metasWeb v-if="hotData.type == 'link'" />
+      </div>
+      <!-- <div class="edit-btn" v-if="routerName && routerName == 'tag' && !editModule">
+          <span @click="edit()"><ui-icon type="edit"></ui-icon> 修改</span>
+      </div> -->
     </div>
+  </div>
+  <!-- <shareTag
+    v-if="showShareEntry"
+    :hotData="hotData"
+    @closeShare="closeShare"
+  ></shareTag> -->
 </template>
 
 <script setup>
-import { reactive, toRefs, onBeforeMount, onMounted, ref, watchEffect, computed, watch, defineEmits } from 'vue'
-import metasImage from './metas/metas-image'
-import metasVideo from './metas/metas-video'
-import metasAudio from './metas/metas-audio'
-import metasWeb from './metas/metas-web'
-import common from '@/utils/common'
-import { useStore } from 'vuex'
-import { useMusicPlayer } from '@/utils/sound'
-const musicPlayer = useMusicPlayer()
-const editModule = computed(() => store.getters['editModule'])
-const store = useStore()
-const emit = defineEmits(['open'])
-const hotData = computed(() => {
-    let data = store.getters['tag/hotData']
-    if (data.type == 'audio' || data.type == 'video') {
-        // musicPlayer.pause(true)
-        // console.log('1qwdq');
-        window.parent.postMessage(
-            {
-                source: "qjkankan",
-                event: "toggleBgmStatus",
-                params: {
-                    status: false,
-                },
-            },
-            "*"
-        );
+import {
+  reactive,
+  toRefs,
+  onBeforeMount,
+  onMounted,
+  nextTick,
+  ref,
+  watchEffect,
+  computed,
+  watch,
+} from "vue";
+import metasImage from "./metas/metas-image";
+import metasVideo from "./metas/metas-video";
+import metasAudio from "./metas/metas-audio";
+import metasWeb from "./metas/metas-web";
+import common from "@/utils/common";
+import { getApp } from "@/app";
+import { useStore } from "vuex";
+import browser from "@/utils/browser";
+import { useMusicPlayer } from "@/utils/sound";
+import QRCode from "qrcode";
+// import shareTag from "./share/entry";
+// import ClipboardJS from "clipboard";
+// import { Dialog } from "@/global_components";
+import { useI18n, getLocale } from "@/i18n";
+const { t } = useI18n({ useScope: "global" });
+const copy$ = ref(null);
+// const musicPlayer = useMusicPlayer();
+// const editModule = computed(() => store.getters["editModule"]);
+const store = useStore();
+const emits = defineEmits(["open"]);
+const shareCode = ref(false);
 
+const controls = computed(() => store.getters["scene/metadata"].controls || {});
+const props = defineProps({
+  moveDistance: {
+    type: Number,
+    default: 0,
+  },
+});
+const hotData = computed(() => {
+  let data = store.getters["tag/hotData"];
+  if (data.type == "audio" || data.type == "video") {
+    // musicPlayer.pause(true)
+    // console.log('1qwdq');
+    window.parent.postMessage(
+      {
+        source: "qjkankan",
+        event: "toggleBgmStatus",
+        params: {
+          status: false,
+        },
+      },
+      "*"
+    );
+  }
+  return data;
+});
+let timer = null;
+const openShare = (status) => {
+  nextTick(() => {
+    if (getApp().config.mobile) {
+      showShareEntry.value = true;
+    } else {
+      if (!status) {
+        timer = setTimeout(() => {
+          shareCode.value = status;
+          clearTimeout(timer);
+          timer = null;
+        }, 0);
+      } else {
+        clearTimeout(timer);
+        timer = null;
+        shareCode.value = status;
+      }
     }
-    return data
-})
-
+  });
+};
+const showShareEntry = ref(false);
+const closeShare = () => {
+  showShareEntry.value = false;
+};
 const audioInfo = computed(() => {
-    return hotData.value.media.audio
-})
-const router = computed(() => store.getters['router'])
+  return hotData.value.media.audio;
+});
+const router = computed(() => store.getters["router"]);
 const routerName = computed(() => {
-    let name = router.value.name || null
-    return name
-})
-const audio = ref(null)
+  let name = router.value.name || null;
+  return name;
+});
+const onClickHandler = () => {
+  shareCode.value = false;
+};
+const audio = ref(null);
 watchEffect(() => {
-    if (audio.value) {
-        audio.value.play()
+  if (audio.value) {
+    audio.value.play();
+  }
+});
+const LinkUrl = computed(() => {
+  let url;
+  if (browser.hasURLParam("t_id")) {
+    url = browser.changeURLArg(window.location.href, "t_id", hotData.value.sid);
+  } else {
+    url = window.location.href + `&t_id=${hotData.value.sid}`;
+  }
+  return url;
+});
+const initQrcode = () => {
+  var canvas = document.getElementById("qrcode-share-tag");
+  let url = LinkUrl.value;
+  QRCode.toCanvas(canvas, url, function (error) {
+    if (error) {
+      return;
     }
-})
+  });
+};
 const open = () => {
-    if (hotData.value.type != 'video') {
-        emit('open')
-        window.parent.postMessage(
-            {
-                source: "qjkankan",
-                event: "toggleFdkkHotspot",
-                params: {
-                    status: 'open',
-                },
-            },
-            "*"
-        );
-        console.log(111111);
-    }
-}
+  if (hotData.value.type != "video") {
+    emits("open");
+    window.parent.postMessage(
+      {
+        source: "qjkankan",
+        event: "toggleFdkkHotspot",
+        params: {
+          status: "open",
+        },
+      },
+      "*"
+    );
+    console.log(111111);
+  }
+};
 // const edit = () => {
 //     store.commit('tag/edit')
 //     store.commit('tag/gotoTag', hotData.value)
 // }
-onMounted(() => { })
+onMounted(() => {
+  nextTick(() => {
+    // initQrcode();
+    if (getApp().config.mobile) {
+        
+    } else {
+      window.addEventListener("click", onClickHandler);
+    }
+    // if (controls.value.showTagshare && !browser.detectApp()) {
+    //   new ClipboardJS(copy$.value).on("success", function (e) {
+    //     e.clearSelection();
+    //     Dialog.toast({ content: t("toast.copySuccess"), type: "success" });
+    //   });
+    // }
+  });
+});
 </script>
 <style lang="scss" scoped>
-.show-tag {
-    pointer-events: auto;
-    background: rgba(27, 27, 28, 0.8);
+.share-code {
+  width: 168px;
+  // height: 194px;
+  height: 241px;
+  background: rgba(27, 27, 28, 0.9);
+  box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25),
+    inset 0px 0px 0px 2px rgba(255, 255, 255, 0.1);
+  border-radius: 4px;
+  opacity: 1;
+  border: 1px solid #000000;
+  position: absolute;
+  z-index: 10;
+  pointer-events: auto;
+  // right: -5px;
+  // top: -180px;
+  right: -137px;
+  top: -72px;
+  padding: 20px;
+  box-sizing: border-box;
+  .hover-box {
+    // position: absolute;
+    // width: 36px;
+    // height: 100%;
+    // z-index: 10;
+    // left: -32px;
+    // top: 0;
+    position: absolute;
+    width: 44px;
+    height: 100%;
+    z-index: 10;
+    left: -38px;
+    top: 0;
+  }
+  &::after {
+    content: "";
+    position: absolute;
+    left: 1px;
+    right: 1px;
+    bottom: 1px;
+    top: 1px;
+    border: 1px solid rgba(255, 255, 255, 0.1);
     border-radius: 4px;
-    // border: 1px solid #000000;
-    // backdrop-filter: blur(4px);
-    min-width: 400px;
-    // min-height: 100px;
-    padding: 30px 20px;
-
-    .edit-btn {
-        margin-top: 20px;
-        text-align: right;
+    z-index: 0;
+    pointer-events: none;
+  }
 
-        span {
-            font-size: 14px;
-            color: rgba(255, 255, 255, 0.6);
-            cursor: pointer;
+  &::before {
+    position: absolute;
+    content: "";
+    // left: 80px;
+    // bottom: -10px;
+    left: -10px;
+    bottom: 117px;
+    width: 0;
+    height: 0;
+    // border-left: 6px solid transparent;
+    // border-right: 6px solid transparent;
+    // border-top: 10px solid rgba(0, 0, 0, 0.8);
 
-            &:hover {
-                color: #fff;
-            }
-        }
+    border-top: 6px solid transparent;
+    border-bottom: 6px solid transparent;
+    border-right: 10px solid rgba(0, 0, 0, 0.8);
+  }
+  canvas {
+    width: 128px !important;
+    height: 128px !important;
+    margin-bottom: 10px;
+  }
+  .share-copyBtn {
+    color: rgba(255, 255, 255, 0.7);
+    font-size: 14px;
+    margin-top: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    > div {
+      cursor: pointer;
+    }
+    &:hover {
+      color: #fff;
+    }
+    .iconfont {
+      margin-right: 5px;
     }
+  }
+  .share-line {
+    width: 128px;
+    height: 1px;
+    background: rgba(255, 255, 255, 0.16);
+  }
+  p.share-titie {
+    font-size: 12px;
+    color: rgba(255, 255, 255, 0.5);
+    text-align: center;
+    width: 120%;
+    margin-left: -10%;
+    margin-bottom: 10px;
+  }
+}
+.show-tag {
+  pointer-events: auto;
+  // background: rgba(27, 27, 28, 0.8);
+  border-radius: 4px;
+  // border: 1px solid #000000;
+  // backdrop-filter: blur(4px);
+  min-width: 420px;
+  // min-height: 100px;
+  // padding: 30px 20px;
+  // padding: 0px 20px 0 0;
+  padding: 30px 0 30px 20px;
+  background: rgba(27, 27, 28, 0.8);
 
-    .tag-metas {
+  position: relative;
+  border-radius: 8px;
+  // &::before {
+  //     content: '';
+  //     position: fixed;
+  //     width: calc(100% - 40px);
+  //     border-radius: 8px;
+  //     height: 100%;
+  //     z-index: 1;
+  //     top: 0;
+  //     left: 0;
+  //     // backdrop-filter: blur(2px);
+  //     background: rgba(27, 27, 28, 0.8);
+  // }
+  .show-content {
+    position: relative;
+    z-index: 2;
+    max-height: 50vh;
+    overflow-y: auto;
+    padding: 0px 20px 0 0;
+  }
+  .share-box {
+    height: 24px;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    margin-bottom: 10px;
+    .iconfont {
+      font-size: 24px;
+      cursor: pointer;
+      color: #999999;
+      &:hover {
+        color: #fff;
+      }
+    }
+  }
+  .edit-btn {
+    margin-top: 20px;
+    text-align: right;
+    span {
+      font-size: 14px;
+      color: rgba(255, 255, 255, 0.6);
+      cursor: pointer;
+      &:hover {
+        color: #fff;
+      }
+    }
+  }
+  .tag-metas {
+    width: 100%;
+    height: 225px;
+    background: rgba(255, 255, 255, 0.1);
+    border-radius: 4px;
+    overflow: hidden;
+    position: relative;
+    cursor: -webkit-zoom-in;
+    margin-top: 20px;
+    &.nocursor {
+      cursor: auto;
+    }
+    &.mask {
+      &::after {
+        content: "";
+        position: absolute;
+        top: 0;
+        left: 0;
         width: 100%;
-        height: 225px;
-        background: rgba(255, 255, 255, 0.1);
-        border-radius: 4px;
-        overflow: hidden;
-        position: relative;
-        cursor: -webkit-zoom-in;
-        margin-top: 20px;
-
-        &.nocursor {
-            cursor: auto;
-        }
-
-        &.mask {
-            &::after {
-                content: '';
-                position: absolute;
-                top: 0;
-                left: 0;
-                width: 100%;
-                height: 100%;
-                z-index: 100;
-            }
-        }
+        height: 100%;
+        z-index: 100;
+      }
     }
-
-    .tag-title {
-        word-break: break-all;
-
-        h2 {
-            font-size: 20px;
-            // margin-bottom: 10px;
-            line-height: 30px;
-            color: #ffffff;
-            position: relative;
-
-            .ui-audio {
-                float: right;
-
-                &.audio {
-                    display: inline-block;
-                    cursor: pointer;
-                }
-            }
+  }
+  .tag-title {
+    word-break: break-all;
+    h2 {
+      font-size: 20px;
+      // margin-bottom: 10px;
+      line-height: 30px;
+      color: #ffffff;
+      position: relative;
+      display: flex;
+      align-items: flex-start;
+      justify-content: space-between;
+      > span {
+        width: 93%;
+        text-align: justify;
+      }
+      .ui-audio {
+        float: right;
+        &.audio {
+          display: inline-block;
+          cursor: pointer;
         }
+      }
     }
-
-    .desc {
-        margin-top: 10px;
-
-        .text {
-            font-size: 14px;
-            color: #999999;
-            line-height: 20px;
-            text-align: justify;
-            word-break: break-all;
-        }
+  }
+  .desc {
+    margin-top: 10px;
+    .text {
+      font-size: 14px;
+      color: #999999;
+      line-height: 20px;
+      text-align: justify;
+      word-break: break-all;
     }
+  }
 }
-
 [is-mobile] {
-    .show-tag {
-        pointer-events: auto;
-        background: rgba(27, 27, 28, 0.8);
-        border-radius: 0.0533rem;
-        // border: 1px solid #000000;
-        // backdrop-filter: blur(0.0533rem);
-        min-width: 7.4667rem;
-        // min-height: 4rem;
-        padding: 0.4rem 0.2667rem;
-
-        .edit-btn {
-            margin-top: 0.2667rem;
-            text-align: right;
-
-            span {
-                font-size: 0.1867rem;
-                color: rgba(255, 255, 255, 0.6);
-                cursor: pointer;
+  .show-tag {
+    pointer-events: auto;
+    border-radius: 0.0533rem;
 
-                &:hover {
-                    color: #fff;
-                }
-            }
+    min-width: 7.4667rem;
+    border-radius: 0.1067rem;
+    // padding: 0px 0.2667rem 0 0;
+    padding: 0.4rem 0 0.4rem 0.2667rem;
+    box-shadow: 0px 0.1067rem 0.1067rem 0px rgba(0, 0, 0, 0.25),
+      inset 0px 0px 0px 0.0533rem rgba(255, 255, 255, 0.1);
+    opacity: 1;
+    // border: 0.0267rem solid #000000;
+    .show-content {
+      padding: 0px 0.2667rem 0 0;
+    }
+    &::before {
+      width: 100%;
+      border-radius: 0.1067rem;
+    }
+    .share-box {
+      height: 0.64rem;
+      display: flex;
+      align-items: center;
+      justify-content: flex-end;
+      margin-bottom: 0.1333rem;
+      .iconfont {
+        font-size: 0.64rem;
+        color: #999999;
+      }
+    }
+    .edit-btn {
+      margin-top: 0.2667rem;
+      text-align: right;
+      span {
+        font-size: 0.1867rem;
+        color: rgba(255, 255, 255, 0.6);
+        cursor: pointer;
+        &:hover {
+          color: #fff;
         }
-
-        .tag-metas {
-            width: 100%;
-            height: 4.2667rem;
-            background: rgba(255, 255, 255, 0.1);
-            border-radius: 0.0533rem;
-            overflow: hidden;
-            position: relative;
-            cursor: -webkit-zoom-in;
-            margin-top: 0.4rem;
-
-            &.mask {
-                &::after {
-                    content: '';
-                    position: absolute;
-                    top: 0;
-                    left: 0;
-                    width: 100%;
-                    height: 100%;
-                    z-index: 100;
-                }
-            }
+      }
+    }
+    .tag-metas {
+      width: 100%;
+      height: 4.2667rem;
+      background: rgba(255, 255, 255, 0.1);
+      border-radius: 0.0533rem;
+      overflow: hidden;
+      position: relative;
+      cursor: -webkit-zoom-in;
+      margin-top: 0.4rem;
+      &.mask {
+        &::after {
+          content: "";
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 100%;
+          height: 100%;
+          z-index: 100;
         }
-
-        .tag-title {
-            h2 {
-                font-size: 0.5333rem;
-                line-height: 0.8rem;
-                color: #ffffff;
-                position: relative;
-
-                .ui-audio {
-                    float: right;
-
-                    &.audio {
-                        display: inline-block;
-                        cursor: pointer;
-                    }
-                }
-            }
+      }
+    }
+    .tag-title {
+      h2 {
+        font-size: 0.5333rem;
+        line-height: 0.8rem;
+        color: #ffffff;
+        position: relative;
+        .ui-audio {
+          float: right;
+          &.audio {
+            display: inline-block;
+            cursor: pointer;
+          }
         }
+      }
+    }
+    .desc {
+      margin-bottom: 0.2933rem;
 
-        .desc {
-            margin-bottom: 0.2933rem;
-
-            .text {
-                font-size: 0.3733rem;
-                color: #999999;
-                line-height: 0.2533rem;
-                text-align: justify;
-                line-height: 0.5333rem;
+      .text {
+        font-size: 0.3733rem;
+        color: #999999;
+        line-height: 0.2533rem;
+        text-align: justify;
+        line-height: 0.5333rem;
 
-                p {
-                    line-height: 0.5333rem;
-                }
-            }
+        p {
+          line-height: 0.5333rem;
         }
+      }
     }
+  }
 }
 </style>

+ 1 - 11
packages/qjkankan-kankan-view/src/components/Tags/tag-view.vue

@@ -29,17 +29,7 @@
 </template>
 
 <script setup>
-import {
-  reactive,
-  defineEmits,
-  onBeforeMount,
-  onMounted,
-  ref,
-  watchEffect,
-  computed,
-  watch,
-  nextTick,
-} from "vue";
+import { onMounted, ref, watchEffect, computed, watch, nextTick } from "vue";
 import { Dialog } from "@/global_components";
 import metasImage from "./metas/metas-image";
 import imageView from "./metas/image-view";

+ 240 - 214
packages/qjkankan-kankan-view/src/components/shared/Guide.vue

@@ -1,246 +1,272 @@
 <template>
-    <div v-if="show && isMobile" class="user-guide-overlay">
-        <div class="user-guide-mobile">
-                <div class="zh">
-                    <div class="btn" @click="onSet"></div>
-                </div>
-        </div>
+  <div v-if="show && isMobile" class="user-guide-overlay">
+    <div class="user-guide-mobile">
+      <div class="en" v-if="lang === 'en'">
+        <ul>
+          <li>
+            <div>
+              <span>Walk</span>
+              <div>Click to move</div>
+            </div>
+          </li>
+          <li>
+            <div>
+              <span>Roam</span>
+              <div>Swipe the screen to roam the screen to roam</div>
+            </div>
+          </li>
+          <li>
+            <div>
+              <span>Zoom</span>
+              <div>Zoom in or out</div>
+            </div>
+          </li>
+        </ul>
+        <div class="btn" @click="onSet">Got it</div>
+      </div>
+      <div class="zh" v-else>
+        <div class="btn" @click="onSet"></div>
+      </div>
     </div>
+  </div>
 </template>
 <script setup>
-import { onMounted, watch, computed, ref, nextTick } from 'vue'
-import { useApp } from '@/app'
+import { onMounted, watch, computed, ref, nextTick } from "vue";
+import { useApp } from "@/app";
 import browser from "@/utils/browser";
 
-const isMobile = browser.isMobile()
+const lang = computed(() => browser.getURLParam("lang"));
 
-const show = ref(false)
+const isMobile = browser.isMobile();
+
+const show = ref(false);
 const onSet = () => {
-    show.value = false
-    localStorage.setItem('user_guide', Date.now())
-}
-const getTips = tips => {
-    let text = tips.split('<br />')
-    return `<span>${text[0]}</span><div>${text[1]}</div>`
-}
-useApp().then(app => {
-    app.Scene.on('loaded', () => {
-        if (!localStorage.getItem('user_guide')) {
-            show.value = true
-        }
-    })
-})
+  show.value = false;
+  localStorage.setItem("user_guide", Date.now());
+};
+const getTips = (tips) => {
+  let text = tips.split("<br />");
+  return `<span>${text[0]}</span><div>${text[1]}</div>`;
+};
+useApp().then((app) => {
+  app.Scene.on("loaded", () => {
+    // show.value = true;
+    if (!localStorage.getItem("user_guide")) {
+      show.value = true;
+    }
+  });
+});
 </script>
 <style lang="scss" scoped>
 .user-guide-overlay {
-    position: fixed;
-    left: 0;
-    top: 0;
-    width: 100%;
-    height: 100%;
-    z-index: 100000;
-    background-color: rgba(0, 0, 0, 0.7);
+  position: fixed;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 100000;
+  background-color: rgba(0, 0, 0, 0.7);
 }
 .user-guide {
-    white-space: normal;
-    position: absolute;
-    top: 50%;
-    left: 1.2rem;
-    right: 1.2rem;
-    border-radius: 0.15rem;
-    color: #fff;
-    transform: translateY(-50%);
-    background-color: rgba(0, 0, 0, 0.7);
-    z-index: 999999;
-    .main {
-        padding: 0.8rem;
-        padding-bottom: 0;
-        h4 {
-            margin: 0;
-            font-size: 0.5rem;
-            text-align: center;
-        }
-        ul,
-        li {
-            list-style: none;
-            padding: 0;
-            margin: 0;
-            width: 100%;
-        }
-        ul {
-            margin: 0.4rem 0;
-        }
-        li {
-            display: flex;
-            align-items: center;
-            padding: 0.6rem 0;
-            i {
-                font-size: 1.2rem;
-            }
-            > div {
-                line-height: 1.6;
-                font-size: 0.4rem;
-                margin-left: 0.35rem;
-            }
-        }
-
-        button {
-            width: 100%;
-            margin-bottom: 0.5rem;
-            background-color: #fff;
-            font-size: 0.4rem;
-            color: #444;
-            height: 1.1rem;
-            border: none;
-            border-radius: 0.15rem;
-            &[type='submit'] {
-                color: #fff;
-                background-color: transparent;
-            }
-        }
+  white-space: normal;
+  position: absolute;
+  top: 50%;
+  left: 1.2rem;
+  right: 1.2rem;
+  border-radius: 0.15rem;
+  color: #fff;
+  transform: translateY(-50%);
+  background-color: rgba(0, 0, 0, 0.7);
+  z-index: 999999;
+  .main {
+    padding: 0.8rem;
+    padding-bottom: 0;
+    h4 {
+      margin: 0;
+      font-size: 0.5rem;
+      text-align: center;
+    }
+    ul,
+    li {
+      list-style: none;
+      padding: 0;
+      margin: 0;
+      width: 100%;
+    }
+    ul {
+      margin: 0.4rem 0;
+    }
+    li {
+      display: flex;
+      align-items: center;
+      padding: 0.6rem 0;
+      i {
+        font-size: 1.2rem;
+      }
+      > div {
+        line-height: 1.6;
+        font-size: 0.4rem;
+        margin-left: 0.35rem;
+      }
     }
 
-    @media (orientation: landscape) {
-        width: 400px;
-        left: 50% !important;
-        right: auto !important;
-        margin-left: -200px;
-        .main {
-            padding: 0.5rem;
-            h4 {
-                font-size: 0.35rem;
-            }
-            ul {
-                margin: 0.3rem 0;
-            }
-            li {
-                padding: 0.1rem 0;
-                i {
-                    font-size: 0.6rem;
-                }
-                > div {
-                    font-size: 0.25rem;
-                }
-            }
+    button {
+      width: 100%;
+      margin-bottom: 0.5rem;
+      background-color: #fff;
+      font-size: 0.4rem;
+      color: #444;
+      height: 1.1rem;
+      border: none;
+      border-radius: 0.15rem;
+      &[type="submit"] {
+        color: #fff;
+        background-color: transparent;
+      }
+    }
+  }
 
-            button {
-                margin-bottom: 0rem;
-                font-size: 0.3rem;
-                height: 0.8rem;
-            }
+  @media (orientation: landscape) {
+    width: 400px;
+    left: 50% !important;
+    right: auto !important;
+    margin-left: -200px;
+    .main {
+      padding: 0.5rem;
+      h4 {
+        font-size: 0.35rem;
+      }
+      ul {
+        margin: 0.3rem 0;
+      }
+      li {
+        padding: 0.1rem 0;
+        i {
+          font-size: 0.6rem;
         }
+        > div {
+          font-size: 0.25rem;
+        }
+      }
+
+      button {
+        margin-bottom: 0rem;
+        font-size: 0.3rem;
+        height: 0.8rem;
+      }
     }
+  }
 }
 .user-guide-mobile {
-    position: absolute;
-    top: 1.55789rem;
-    left: 50%;
-    width: 7.89474rem;
-    transform: translateX(-50%);
-    .zh {
-        width: 100%;
-        height: 7rem;
-        background-image: url(~@/assets/images/guide/novice_guide_text@2x.png);
-        background-size: contain;
-        background-position: center top;
-        background-repeat: no-repeat;
+  position: absolute;
+  top: 1.55789rem;
+  left: 50%;
+  width: 7.89474rem;
+  transform: translateX(-50%);
+  .zh {
+    width: 100%;
+    height: 7rem;
+    background-image: url(~@/assets/images/guide/novice_guide_text@2x.png);
+    background-size: contain;
+    background-position: center top;
+    background-repeat: no-repeat;
+  }
+  .en {
+    width: 100%;
+    color: #fff;
+    ul,
+    li {
+      list-style: none;
+      padding: 0;
+      margin: 0;
+      width: 100%;
     }
-    .en {
-        width: 100%;
-        color: #fff;
-        ul,
-        li {
-            list-style: none;
-            padding: 0;
-            margin: 0;
-            width: 100%;
-        }
-        ul {
-            margin: 0;
-        }
-        li {
-            display: flex;
-            align-items: flex-start;
-            padding: 0.5rem 0;
-            &:first-child {
-                padding-top: 0;
-            }
-            i {
-                font-size: 1.32rem;
-            }
-            > div {
-                font-size: 0.4rem;
-                margin-left: 0.3rem;
-                :deep(span) {
-                    font-size: 0.6rem;
-                    color: #00c2c4;
-                }
-                :deep(div) {
-                    font-size: 0.5rem;
-                    margin-top: 0.1rem;
-                    white-space: pre-line;
-                    line-height: 1.3;
-                }
-            }
+    ul {
+      margin: 0;
+    }
+    li {
+      display: flex;
+      align-items: flex-start;
+      padding: 0.5rem 0;
+      &:first-child {
+        padding-top: 0;
+      }
+      i {
+        font-size: 1.32rem;
+      }
+      > div {
+        font-size: 0.4rem;
+        margin-left: 0.3rem;
+        :deep(span) {
+          font-size: 0.6rem;
+          color: #00c2c4;
         }
-
-        .btn {
-            background-image: none;
-            color: #00c2c4;
-            line-height: 1.2rem;
-            text-align: center;
-            font-size: 0.52632rem;
-            background-image: url(~@/assets/images/guide/novice_guide_button_empty@2x.png);
+        :deep(div) {
+          font-size: 0.5rem;
+          margin-top: 0.1rem;
+          white-space: pre-line;
+          line-height: 1.3;
         }
+      }
     }
+
     .btn {
-        position: absolute;
-        bottom: -3.15789rem;
-        left: 50%;
-        width: 3.5rem;
-        height: 1.31579rem;
-        background-image: url(~@/assets/images/guide/novice_guide_button@2x.png);
-        background-size: contain;
-        background-position: center top;
-        background-repeat: no-repeat;
-        transform: translateX(-50%);
+      background-image: none;
+      color: #00c2c4;
+      line-height: 1.2rem;
+      text-align: center;
+      font-size: 0.52632rem;
+      background-image: url(~@/assets/images/guide/novice_guide_button_empty@2x.png);
     }
+  }
+  .btn {
+    position: absolute;
+    bottom: -3.15789rem;
+    left: 50%;
+    width: 3.5rem;
+    height: 1.31579rem;
+    background-image: url(~@/assets/images/guide/novice_guide_button@2x.png);
+    background-size: contain;
+    background-position: center top;
+    background-repeat: no-repeat;
+    transform: translateX(-50%);
+  }
 
-    @media (orientation: landscape) {
-        top: 0.5rem;
-        .zh {
-            height: 4rem;
-            .btn {
-                width: 2.5rem;
-                height: 0.8rem;
-                bottom: -1.4rem;
-            }
-        }
+  @media (orientation: landscape) {
+    top: 0.5rem;
+    .zh {
+      height: 4rem;
+      .btn {
+        width: 2.5rem;
+        height: 0.8rem;
+        bottom: -1.4rem;
+      }
+    }
 
-        .en {
-            li {
-                padding: 0.15rem 0;
-                i {
-                    font-size: 1rem;
-                }
-                > div {
-                    margin-left: 0.3rem;
-                    :deep(span) {
-                        font-size: 0.3rem;
-                    }
-                    :deep(div) {
-                        font-size: 0.25rem;
-                        margin-top: 0.1rem;
-                    }
-                }
-            }
-            .btn {
-                height: 0.7rem;
-                line-height: 0.63rem;
-                font-size: 0.25rem;
-                bottom: -0.7rem;
-            }
+    .en {
+      li {
+        padding: 0.15rem 0;
+        i {
+          font-size: 1rem;
+        }
+        > div {
+          margin-left: 0.3rem;
+          :deep(span) {
+            font-size: 0.3rem;
+          }
+          :deep(div) {
+            font-size: 0.25rem;
+            margin-top: 0.1rem;
+          }
         }
+      }
+      .btn {
+        height: 0.7rem;
+        line-height: 0.63rem;
+        font-size: 0.25rem;
+        bottom: -0.7rem;
+      }
     }
+  }
 }
 </style>

+ 119 - 69
packages/qjkankan-kankan-view/src/pages/SMG.vue

@@ -12,24 +12,48 @@
           <ui-icon type="show_map_collect"></ui-icon>
         </span>
 
-        <p class="change" v-if="controls.showDollhouse" @click="changeMode('dollhouse')">
+        <p
+          class="change"
+          v-if="controls.showDollhouse"
+          @click.stop="changeMode('dollhouse')"
+        >
           <ui-icon type="show_3d_normal"></ui-icon>
-          {{$t('mode.dollhouseModel')}}
+          {{ $t("mode.dollhouseModel") }}
         </p>
       </teleport>
       <template v-if="refMiniMap">
-        <div :class="{ disabled: flying }" v-show="mode != 'panorama'"
-          v-if="controls.showFloorplan && controls.showDollhouse" class="tab-layer">
+        <div
+          :class="{ disabled: flying }"
+          v-show="mode != 'panorama'"
+          v-if="controls.showFloorplan && controls.showDollhouse"
+          class="tab-layer"
+        >
           <div class="tabs" v-if="controls.showMap">
-            <span :class="{ active: mode === 'floorplan' }" ref="floorplan_ref"
-              @click="changeMode('floorplan', $event)">
-              <ui-icon :type="mode == 'floorplan' ? 'show_plane_selected' : 'show_plane_normal'"></ui-icon>
-              {{$t('mode.floorplan')}}
+            <span
+              :class="{ active: mode === 'floorplan' }"
+              ref="floorplan_ref"
+              @click="changeMode('floorplan', $event)"
+            >
+              <ui-icon
+                :type="
+                  mode == 'floorplan'
+                    ? 'show_plane_selected'
+                    : 'show_plane_normal'
+                "
+              ></ui-icon>
+              {{ $t("mode.floorplan") }}
             </span>
-            <span :class="{ active: mode === 'dollhouse' }" ref="dollhouse_ref"
-              @click="changeMode('dollhouse', $event)">
-              <ui-icon :type="mode == 'dollhouse' ? 'show_3d_selected' : 'show_3d_normal'"></ui-icon>
-              {{$t('mode.dollhouse')}}
+            <span
+              :class="{ active: mode === 'dollhouse' }"
+              ref="dollhouse_ref"
+              @click="changeMode('dollhouse', $event)"
+            >
+              <ui-icon
+                :type="
+                  mode == 'dollhouse' ? 'show_3d_selected' : 'show_3d_normal'
+                "
+              ></ui-icon>
+              {{ $t("mode.dollhouse") }}
             </span>
             <div class="background" ref="background"></div>
           </div>
@@ -39,13 +63,12 @@
     <UiTags />
   </div>
 </template>
-  
-<script setup>
 
+<script setup>
 import UiTags from "@/components/Tags";
 
-import { listenMessage } from '@/utils/messageHandler'
-import {Dialog} from '@/global_components'
+import { listenMessage } from "@/utils/messageHandler";
+import { Dialog } from "@/global_components";
 
 import Information from "@/components/Information";
 import Control from "@/components/Controls/Control.Mobile.vue";
@@ -55,37 +78,37 @@ import Guide from "@/components/shared/Guide.vue";
 import Password from "@/components/shared/Password.vue";
 
 import { createApp } from "@/app";
-import { ref, onMounted, computed, nextTick, watch } from "vue";
+import { ref, onMounted, computed, nextTick, watch, unref } from "vue";
 import { useStore } from "vuex";
 import browser from "@/utils/browser";
 import { useApp, getApp } from "@/app";
-import { useI18n, getLocale } from '@/i18n'
+import { useI18n, getLocale } from "@/i18n";
 import { useAppHeight } from "@/utils/globalViewHeight";
-const { t } = useI18n({ useScope: 'global' })
+const { t } = useI18n({ useScope: "global" });
 useAppHeight();
 let app = null;
 
-const autoPlayMedia = player => {
-    function onclick() {
-        window.parent.postMessage(
-            {
-                source: "qjkankan",
-                event: "autoPlayBgm",
-                params: {
-                    status: true,
-                },
-            },
-            "*"
-        );
-        $player.removeEventListener('click', onclick)
-        $player.removeEventListener('touchstart', onclick)
-    }
-    const $player = document.querySelector('.player')
-    $player.addEventListener('click', onclick)
-    $player.addEventListener('touchstart', onclick)
-}
+const autoPlayMedia = (player) => {
+  function onclick() {
+    window.parent.postMessage(
+      {
+        source: "qjkankan",
+        event: "autoPlayBgm",
+        params: {
+          status: true,
+        },
+      },
+      "*"
+    );
+    $player.removeEventListener("click", onclick);
+    $player.removeEventListener("touchstart", onclick);
+  }
+  const $player = document.querySelector(".player");
+  $player.addEventListener("click", onclick);
+  $player.addEventListener("touchstart", onclick);
+};
 
-listenMessage()
+listenMessage();
 
 const closetagtype = () => {
   store.commit("tag/setTagClickType", {
@@ -113,10 +136,14 @@ const refMiniMap = ref(null);
 const isCollapse = ref(false);
 const background = ref(null);
 const resize = () => {
-  if (this.$refs.background && (this.mode == "floorplan" || this.mode == "dollhouse")) {
+  if (
+    this.$refs.background &&
+    (this.mode == "floorplan" || this.mode == "dollhouse")
+  ) {
     this.$nextTick(() => {
       let $active = $(this.$el).find(".tabs .active");
-      background.value.style.width = $active[0].getBoundingClientRect().width + "px";
+      background.value.style.width =
+        $active[0].getBoundingClientRect().width + "px";
       background.value.style.left = $active.position().left + "px";
     });
   }
@@ -160,17 +187,19 @@ watch(
 watch(
   () => mode.value,
   (val, old) => {
-    console.log(val);
+    console.error("mode", unref(val));
     let timer = setTimeout(() => {
       clearTimeout(timer);
-      if (val == "floorplan") {
+      if (unref(val) == "floorplan") {
         if (floorplan_ref.value && floorplan_ref.value) {
-          background.value.style.width = floorplan_ref.value.getBoundingClientRect().width + "px";
+          background.value.style.width =
+            floorplan_ref.value.getBoundingClientRect().width + "px";
           background.value.style.left = floorplan_ref.value.offsetLeft + "px";
         }
-      } else if (val == "dollhouse") {
+      } else if (unref(val) == "dollhouse") {
         if (dollhouse_ref.value && dollhouse_ref.value) {
-          background.value.style.width = dollhouse_ref.value.getBoundingClientRect().width + "px";
+          background.value.style.width =
+            dollhouse_ref.value.getBoundingClientRect().width + "px";
           background.value.style.left = dollhouse_ref.value.offsetLeft + "px";
         }
       }
@@ -198,6 +227,7 @@ const changeMode = (name, e) => {
     // }, 0)
   }
 };
+
 // console.dir(document.querySelector(".tabs>span:last-of-type"));
 const toggleMap = () => {
   isCollapse.value = !isCollapse.value;
@@ -223,6 +253,8 @@ const onClickTagInfo = (el) => {
 };
 
 onMounted(() => {
+  window.changeMode = changeMode;
+
   const app = createApp({
     num: browser.getURLParam("m"),
     dom: scene$.value,
@@ -238,25 +270,36 @@ onMounted(() => {
   app.Scene.on("error", (data) => {
     switch (data.code) {
       case 5033:
-        window.location.replace(`/5033.html?m=` + browser.getURLParam("m"));
+        window.location.replace(
+          `/5033.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`
+        );
         break;
       case 5034:
-        window.location.replace(`/5034.html?m=` + browser.getURLParam("m"));
+        window.location.replace( `/5034.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`);
         break;
       case 5009:
-        window.location.replace(`/5034.html?m=` + browser.getURLParam("m"));
+        window.location.replace( `/5034.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`);
         break;
       case 5005:
-        Dialog.toast({
-            content: t('guide.no_scene'),
-            type: 'error',
-        })
+        // Dialog.toast({
+        //     content: t('guide.no_scene'),
+        //     type: 'error',
+        // })
+        window.location.replace( `/5033.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`);
         break;
     }
   });
   app.Scene.on("loaded", (pano) => {
     refMiniMap.value = "[xui_min_map]";
-    let music = store.getters['scene/musicURL']
+    let music = store.getters["scene/musicURL"];
 
     window.parent.postMessage(
       {
@@ -268,7 +311,7 @@ onMounted(() => {
       },
       "*"
     );
-    autoPlayMedia()
+    autoPlayMedia();
   });
   app.Scene.on("panorama.videorenderer.resumerender", () => {
     window.parent.postMessage(
@@ -346,19 +389,19 @@ onMounted(() => {
     store.commit("setFlying", false);
     store.commit("setPanoId", targetPano.id);
   });
-  app.TourManager.on('loaded', async (tour) => {
+  app.TourManager.on("loaded", async (tour) => {
     let tours = JSON.parse(
       JSON.stringify(app.TourManager.tours, (key, val) => {
-        if (key === 'audio') {
-          return null
+        if (key === "audio") {
+          return null;
         } else {
-          return val
+          return val;
         }
       })
-    )
-    store.commit('tour/setData', {
+    );
+    store.commit("tour/setData", {
       tours: tours,
-    })
+    });
 
     window.parent.postMessage(
       {
@@ -383,12 +426,16 @@ onMounted(() => {
       ),
     });
   });
-  app.store.on("floorcad", (floor) => store.commit("scene/loadFloorData", floor));
-  app.store.on('flooruser', floor => store.commit('scene/loadFloorData', floor)) //4.7以后新楼层方式
+  app.store.on("floorcad", (floor) =>
+    store.commit("scene/loadFloorData", floor)
+  );
+  app.store.on("flooruser", (floor) =>
+    store.commit("scene/loadFloorData", floor)
+  ); //4.7以后新楼层方式
   app.render();
 });
 </script>
-  
+
 <style lang="scss">
 .tab-layer {
   width: 100%;
@@ -485,7 +532,11 @@ onMounted(() => {
         width: 2px;
         height: 28px;
         bottom: -30px;
-        background: linear-gradient(145deg, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
+        background: linear-gradient(
+          145deg,
+          rgba(255, 255, 255, 0.8),
+          rgba(255, 255, 255, 0)
+        );
         position: absolute;
       }
 
@@ -503,7 +554,7 @@ onMounted(() => {
         pointer-events: none;
       }
 
-      >p {
+      > p {
         color: #131d34;
         font-size: 16px;
         pointer-events: none;
@@ -582,7 +633,7 @@ onMounted(() => {
     .tabs {
       height: 0.7rem;
 
-      >span {
+      > span {
         height: 0.7rem;
         font-size: 0.25rem;
       }
@@ -590,4 +641,3 @@ onMounted(() => {
   }
 }
 </style>
-  

+ 18 - 10
packages/qjkankan-kankan-view/src/pages/SPG.vue

@@ -33,8 +33,6 @@ import browser from "@/utils/browser";
 import { useI18n, getLocale } from "@/i18n";
 const { t } = useI18n({ useScope: "global" });
 
-
-
 const autoPlayMedia = (player) => {
   function onclick() {
     window.parent.postMessage(
@@ -83,22 +81,32 @@ onMounted(() => {
     show.value = true;
   });
   app.Scene.on("error", (data) => {
-    console.error(data);
     switch (data.code) {
       case 5033:
-        window.location.replace(`/5033.html?m=` + browser.getURLParam("m"));
+        window.location.replace(
+          `/5033.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`
+        );
         break;
       case 5034:
-        window.location.replace(`/5034.html?m=` + browser.getURLParam("m"));
+        window.location.replace( `/5034.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`);
         break;
       case 5009:
-        window.location.replace(`/5034.html?m=` + browser.getURLParam("m"));
+        window.location.replace( `/5034.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`);
         break;
       case 5005:
-        Dialog.toast({
-          content: t("guide.no_scene"),
-          type: "error",
-        });
+        // Dialog.toast({
+        //     content: t('guide.no_scene'),
+        //     type: 'error',
+        // })
+        window.location.replace( `/5033.html?m=${browser.getURLParam("m")}&lang=${browser.getURLParam(
+            "lang"
+          )}`);
         break;
     }
   });

+ 2 - 1
packages/qjkankan-view/.env.eurprod

@@ -2,6 +2,7 @@ NODE_ENV=production
 VUE_APP_STATIC_DIR=showviewer
 VUE_APP_CDN=https://eurs3.4dkankan.com
 VUE_APP_PROXY_URL_ROOT='https://eur.4dkankan.com'
+VUE_APP_RESOURCE_URL='https://eur.4dkankan.com/panorama/'
 VUE_APP_PROXY_URL='https://eur.4dkankan.com/qjkankan/'
 VUE_APP_URL_FILL=/qjkankan
-VUE_APP_DEBBUG_FLAG=0529-01
+VUE_APP_DEBBUG_FLAG=0824-01

+ 1 - 0
packages/qjkankan-view/.env.eurtestdev

@@ -1,6 +1,7 @@
 VUE_APP_STATIC_DIR=showviewer
 VUE_APP_CDN=https://testeurs3.4dkankan.com
 VUE_APP_PROXY_URL_ROOT='https://testeur.4dkankan.com'
+VUE_APP_RESOURCE_URL='https://testeur.4dkankan.com/panorama/'
 VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
 VUE_APP_URL_FILL=
 

+ 2 - 1
packages/qjkankan-view/.env.eurtestprod

@@ -2,8 +2,9 @@ NODE_ENV=production
 VUE_APP_STATIC_DIR=showviewer
 VUE_APP_CDN=https://testeurs3.4dkankan.com
 VUE_APP_PROXY_URL_ROOT='https://testeur.4dkankan.com'
+VUE_APP_RESOURCE_URL='https://testeur.4dkankan.com/panorama/'
 VUE_APP_PROXY_URL='https://testeur.4dkankan.com/qjkankan/'
 VUE_APP_URL_FILL=/qjkankan
 # 接口请求地址
 VUE_APP_APIS_URL=https://testeur.4dkankan.com/
-VUE_APP_DEBBUG_FLAG=0523-01
+VUE_APP_DEBBUG_FLAG=0628-01

+ 1 - 1
packages/qjkankan-view/.env.prod

@@ -8,4 +8,4 @@ VUE_APP_URL_FILL=/qjkankan
 
 # 接口请求地址
 VUE_APP_APIS_URL=https://www.4dkankan.com/
-VUE_APP_DEBBUG_FLAG=0627-01
+VUE_APP_DEBBUG_FLAG=0807-01

+ 1 - 1
packages/qjkankan-view/.env.testdev

@@ -10,4 +10,4 @@ VUE_APP_APIS_URL=https://test.4dkankan.com/
 VUE_APP_DEBBUG_FLAG=0516-03
 VUE_APP_DEBBUG_NOTIFY=0
 VUE_APP_DEBBUG_V4=1
-VUE_APP_DEBBUG_V4_URL="http://192.168.0.186:8081"
+VUE_APP_DEBBUG_V4_URL="http://192.168.0.20:8081"

+ 1 - 1
packages/qjkankan-view/.env.testprod

@@ -7,7 +7,7 @@ VUE_APP_PROXY_URL='https://test.4dkankan.com/qjkankan/'
 VUE_APP_URL_FILL=/qjkankan
 # 接口请求地址
 VUE_APP_APIS_URL=https://test.4dkankan.com/
-VUE_APP_DEBBUG_FLAG=0621-01
+VUE_APP_DEBBUG_FLAG=0807-01
 VUE_APP_DEBBUG_NOTIFY=0
 VUE_APP_DEBBUG_V4=0
 VUE_APP_DEBBUG_V4_URL="http://192.168.0.186:8081"

+ 1 - 0
packages/qjkankan-view/package.json

@@ -26,6 +26,7 @@
     "tiny-emitter": "^2.1.0",
     "vue": "^3.2.13",
     "vue-i18n": "^9.1.10",
+    "vue-marquee-text-component": "^2.0.1",
     "vue-toastification": "^2.0.0-rc.5",
     "vue3-lazyload": "^0.3.6",
     "vuex": "^4.0.0"

+ 5 - 4
packages/qjkankan-view/public/showMobile.html

@@ -47,6 +47,10 @@
     <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
     <link rel="icon" href="./favicon.png" />
     <title>-</title>
+    <!-- <script src="https://4dkk.4dage.com/v4-test/www/viewer/static/lib/vconsole.js"></script>
+    <script>
+      var vConsole = new window.VConsole();
+    </script> -->
   </head>
   <body>
     <div id="app"></div>
@@ -56,9 +60,6 @@
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/howler/howler.min.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper-bundle.min.js"></script>
     <!-- <script src="<%= VUE_APP_STATIC_DIR %>/lib/jssor/jssor.slider-28.1.0.min.js"></script> -->
-    <!-- <script src="https://4dkk.4dage.com/v4-test/www/viewer/static/lib/vconsole.js"></script>
-    <script>
-      var vConsole = new window.VConsole();
-    </script> -->
+ 
   </body>
 </html>

+ 20 - 7
packages/qjkankan-view/src/components/Fdkk/index.vue

@@ -7,9 +7,7 @@
         :key="currentScene.sceneCode"
         v-if="!isMobile"
         id="fdkkifr"
-        :src="`/spc.html?m=${
-          currentScene.sceneCode
-        }&lang=${lang}`"
+        :src="`/spc.html?m=${currentScene.sceneCode}&lang=${lang}`"
         frameborder="0"
       ></iframe>
       <!-- <iframe :key="currentScene.sceneCode" v-if="!isMobile" id="fdkkifr" :src="`https://test.4dkankan.com/spc.html?m=${currentScene.sceneCode}`" -->
@@ -63,6 +61,7 @@ const isHasV4BGM = computed(() => store.getters["audio/isHasV4BGM"]);
 const fdkkCurrentVersion = computed(
   () => store.getters["scene/fdkkCurrentVersion"]
 );
+const isPlayTours = computed(() => store.getters["fdkk/isPlayTours"]);
 
 const somedatainfo = ref({});
 
@@ -78,11 +77,11 @@ const V4IframeUrl = computed(() => {
   if (process.env.VUE_APP_DEBBUG_V4 == 1) {
     return `${v4Mi}/${unref(isMobile) ? "smg" : "spg"}.html?m=${
       unref(currentScene).sceneCode
-    }&lang=${unref(lang)}&rnd=${Math.floor(Math.random()*100000)}`;
+    }&lang=${unref(lang)}&rnd=${Math.floor(Math.random() * 100000)}`;
   } else {
     return `${unref(isMobile) ? "smg" : "spg"}.html?m=${
       unref(currentScene).sceneCode
-    }&lang=${unref(lang)}&rnd=${Math.floor(Math.random()*100000)}`;
+    }&lang=${unref(lang)}&rnd=${Math.floor(Math.random() * 100000)}`;
   }
 });
 
@@ -141,9 +140,23 @@ const handleMessage = (res) => {
     //
     if (event == "toggleBgmStatus") {
       console.error("toggleBgmStatus", params);
-      // debugger;
-      if (params.status) {
+      if (!params.status) {
+        store.dispatch("audio/pauseBGM");
       } else {
+        setTimeout(() => {
+          if (!isPlayTours.value) {
+            console.error("toggleBgmStatus-恢复");
+            if (store.getters["audio/isHasV4BGM"]) {
+              if (!store.getters["audio/isPauseByControl"]) {
+                store.dispatch("audio/playBGM", 2);
+              }
+            } else {
+              if (!store.getters["audio/isPauseByControl"]) {
+                store.dispatch("audio/playBGM", 0);
+              }
+            }
+          }
+        }, 500);
       }
     }
 

+ 2 - 0
packages/qjkankan-view/src/components/Pano/index.vue

@@ -99,7 +99,9 @@ watch(
           let flag =
             data.data.bgMusic &&
             data.data.bgMusic != "0" &&
+            data.data.bgMusic != "Cheerful" &&
             data.data.bgMusic != "noMusic";
+   
           console.error("是否有V3--BGM", flag);
           store.commit("fdkk/setV3FdkkBGM", flag);
           store.dispatch("audio/initV3BGM", flag);

+ 2 - 2
packages/qjkankan-view/src/components/UIGather/control.vue

@@ -191,7 +191,7 @@ const onIsBGM = () => {
     if (!unref(isCurrentPlaying)) {
       store.dispatch("audio/playBGM", 2);
     } else {
-      store.dispatch("audio/pauseBGM");
+      store.dispatch("audio/pauseBGM", 0);
     }
   } else {
     if (!unref(isPlayNormalBGM)) {
@@ -201,7 +201,7 @@ const onIsBGM = () => {
       if (!unref(isCurrentPlaying)) {
         store.dispatch("audio/playBGM", 0);
       } else {
-        store.dispatch("audio/pauseBGM");
+        store.dispatch("audio/pauseBGM", 0);
       }
     }
   }

+ 209 - 69
packages/qjkankan-view/src/components/UIGather/list.vue

@@ -12,17 +12,10 @@
     "
     :class="{ barshow: isShowScenesList }"
   >
-    <div
-      class="top-con"
-      :style="`width:${
-        Math.max(scenesListW, secondaryW) > 1150
-          ? '100%'
-          : Math.max(scenesListW, secondaryW) + 120 + 'px'
-      }`"
-    >
+    <div class="top-con">
       <div
-        class="swiper-container"
-        :style="`width:${scenesListW > 1150 ? '100%' : scenesListW + 'px'}`"
+        class="swiper-container swiper1"
+        :style="`width:calc(100% - 20px)`"
         id="swScenes"
         v-if="currentScenesList.length > 0"
       >
@@ -32,9 +25,9 @@
             class="swiper-slide"
             :class="{
               active: currentScene.sceneCode == item.sceneCode,
-              loopspan:
-                item.sceneTitle.length > spanlength &&
-                currentScene.id == item.id,
+              // loopspan:
+              //   item.sceneTitle.length > spanlength &&
+              //   currentScene.id == item.id,
             }"
             :style="{ backgroundImage: `url(${item.icon})` }"
             v-for="(item, i) in currentScenesList"
@@ -46,47 +39,70 @@
                 item.type == '4dkk' ? 'icon-editor_3d' : 'icon-editor_panoramic'
               "
             ></i>
-            <div>
-              <span v-if="currentScene.id == item.id">{{
-                item.sceneTitle
-              }}</span>
-              <span v-else>{{
-                item.sceneTitle.length > spanlength
-                  ? item.sceneTitle.slice(0, spanlength)
-                  : item.sceneTitle
-              }}</span>
+            <div class="marquee">
+              <marquee-text
+                :repeat="1"
+                :duration="Math.ceil(item.sceneTitle.length / 10) * 5"
+                :key="item.id"
+                v-if="
+                  item.sceneTitle.length > spanlength &&
+                  currentScene.id == item.id
+                "
+              >
+                {{ item.sceneTitle }}
+              </marquee-text>
+              <span v-else>
+                {{ item.sceneTitle }}
+              </span>
             </div>
           </li>
         </ul>
       </div>
 
       <div
-        class="swiper-container"
+        class="swiper-container swiper2"
         id="swSecondary"
-        :style="`width:${secondaryW}px`"
+        :style="`width:${clamp(secondaryW, 0, 1150)}px`"
         v-if="secondaryList.length > 1"
       >
+        <!-- {{ clamp(secondaryW, 0, 1150) }} -->
         <ul class="swiper-wrapper">
           <li
             class="swiper-slide"
-            @click="tabSecondary(item)"
+            @click="tabSecondary(item, i)"
             :class="{
               active: currentSecondary.id == item.id,
-              loopspan:
-                fixTitle(item.name).length > spanlength &&
-                currentSecondary.id == item.id,
+              // loopspan:
+              //   fixTitle(item.name).length > spanlength &&
+              //   currentSecondary.id == item.id,
             }"
             v-for="(item, i) in secondaryList"
             :key="i"
           >
-            <span v-if="currentSecondary.id == item.id">{{
+            <!-- {{ Math.ceil(fixTitle(item.name).length / 10) }} -->
+
+            <marquee-text
+              :duration="Math.ceil(fixTitle(item.name).length / 10) * 5"
+              :key="item.id"
+              :repeat="1"
+              v-if="
+                fixTitle(item.name).length > spanlength &&
+                currentSecondary.id == item.id
+              "
+            >
+              {{ fixTitle(item.name) }}
+            </marquee-text>
+            <span v-else>
+              {{ fixTitle(item.name) }}
+            </span>
+            <!-- <span v-if="currentSecondary.id == item.id">{{
               fixTitle(item.name)
             }}</span>
             <span v-else>{{
               fixTitle(item.name).length > spanlength
                 ? fixTitle(item.name).slice(0, spanlength)
                 : fixTitle(item.name)
-            }}</span>
+            }}</span> -->
           </li>
         </ul>
       </div>
@@ -103,22 +119,37 @@
           class="swiper-slide"
           :class="{
             active: currentCatalogRoot.id == item.id,
-            loopspan:
-              fixTitle(item.name).length > spanlength &&
-              currentCatalogRoot.id == item.id,
+            // loopspan:
+            //   fixTitle(item.name).length > spanlength &&
+            //   currentCatalogRoot.id == item.id,
           }"
           @click="tabRoot(item)"
           v-for="(item, i) in metadata.catalogRoot"
           :key="i"
         >
-          <span v-if="currentCatalogRoot.id == item.id">{{
+          <!-- <span v-if="currentCatalogRoot.id == item.id">{{
             fixTitle(item.name)
           }}</span>
           <span v-else>{{
             fixTitle(item.name).length > spanlength
               ? fixTitle(item.name).slice(0, spanlength)
               : fixTitle(item.name)
-          }}</span>
+          }}</span> -->
+
+          <marquee-text
+            :duration="Math.ceil(fixTitle(item.name).length / 10) * 5"
+            :key="item.id"
+            :repeat="1"
+            v-if="
+              fixTitle(item.name).length > spanlength &&
+              currentCatalogRoot.id == item.id
+            "
+          >
+            {{ fixTitle(item.name) }}
+          </marquee-text>
+          <span v-else>
+            {{ fixTitle(item.name) }}
+          </span>
         </li>
       </ul>
     </div>
@@ -126,10 +157,18 @@
 </template>
 
 <script setup>
-import { ref, watch, computed, onMounted, nextTick } from "vue";
+import {
+  ref,
+  watch,
+  computed,
+  onMounted,
+  nextTick,
+  unref,
+  watchEffect,
+} from "vue";
 import { useStore } from "vuex";
 import { useApp } from "@/app";
-
+import MarqueeText from "vue-marquee-text-component";
 import { useI18n, getLocale } from "@/i18n";
 const { t } = useI18n({ useScope: "global" });
 
@@ -141,6 +180,10 @@ const metadata = computed(() => store.getters["scene/metadata"]);
 const scenes = computed(() => store.getters["scene/list"]);
 const currentScene = computed(() => store.getters["scene/currentScene"]);
 
+const clamp = computed(
+  () => (num, min, max) => Math.min(Math.max(num, min), max)
+);
+
 const currentCatalogRoot = computed(
   () => store.getters["scene/currentCatalogRoot"]
 );
@@ -183,13 +226,16 @@ const tabCurrentScene = (data) => {
   console.log("tabCurrentScene", data.id, currentScene.value.id);
   if (data.id !== currentScene.value.id) {
     store.commit("scene/setCurrentScene", data);
+    setTimeout(() => {
+      scenesSwiperFocus();
+    }, 300);
   } else {
     console.log("重复点击当前导航");
     // window.alert("alert-test-->重复点击当前导航");
   }
 };
 
-const tabSecondary = (data) => {
+const tabSecondary = (data, index) => {
   store.commit("scene/setCurrentSecondary", data);
 };
 
@@ -207,42 +253,124 @@ const fixTitle = (name) => {
   }
   return name;
 };
+const swiperOptions = {
+  slidesPerView: "auto",
+  centeredSlides: true,
+  spaceBetween: 10,
+  centerInsufficientSlides: true,
+  centeredSlidesBounds: true,
+  freeMode: {
+    enabled: true,
+    sticky: false,
+    momentumBounce: false,
+    // momentumVelocityRatio: 0.5,
+  },
+};
+
+// const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
 
-const loadList = () => {
+const initMainSwiper = () => {
   nextTick(() => {
-    let t = setTimeout(() => {
-      clearTimeout(t);
-      ["#swcatalogRoot", "#swSecondary", "#swScenes"].forEach((item) => {
-        new Swiper(item, {
-          slidesPerView: "auto",
-          centeredSlides: true,
-          spaceBetween: 10,
-          centerInsufficientSlides: true,
-          centeredSlidesBounds: true,
-          freeMode: true,
-          touchMoveStopPropagation: true,
-          touchStartPreventDefault : true,
-          // slidesPerView : 6,
-          // slidesPerGroup: 10,
-          // resistanceRatio: 0,
-        });
+    if (window.mainNatSwiper) {
+      // window.mainNatSwiper = null;
+      window.mainNatSwiper.update();
+      window.sencordNatSwiper.slideReset();
+    }
+    window.mainNatSwiper = new Swiper("#swcatalogRoot", swiperOptions);
+  });
+};
+const initsencordNatSwiper = () => {
+  nextTick(() => {
+    console.warn("initsencordNatSwiper");
+    if (window.sencordNatSwiper) {
+      window.sencordNatSwiper.update();
+      window.sencordNatSwiper.slideReset();
+    }
+    window.sencordNatSwiper = new Swiper("#swSecondary", swiperOptions);
+  });
+};
+const initScenesSwiper = () => {
+  console.warn("initScenesSwiper");
+  nextTick(() => {
+    if (window.scenesNatSwiper) {
+      window.scenesNatSwiper.update();
+      window.scenesNatSwiper.slideReset();
+      // window.scenesNatSwiper = null;
+    } else {
+      window.scenesNatSwiper = new Swiper("#swScenes", {
+        ...swiperOptions,
       });
-    }, 100);
+    }
+    scenesSwiperFocus();
   });
 };
 
-watch(currentSecondary, () => {
-  loadList();
-});
+const scenesSwiperFocus = () => {
+  const sceneIndex = Array.from(currentScenesList.value).findIndex(
+    (item) => item.id === currentScene.value.id
+  );
+  if (window.scenesNatSwiper && window.scenesNatSwiper.slides.length > 0) {
+    const index = sceneIndex < 0 ? 0 : sceneIndex;
+    console.warn("scenesSwiperFocus", index);
+    window.scenesNatSwiper.slideTo(index);
+  }
+};
 
-watch(currentScenesList, () => {
-  loadList();
-});
+const sencordNatSwiperFocus = () => {
+  nextTick(() => {
+    const current = Array.from(secondaryList.value).findIndex(
+      (item) => item.id === currentSecondary.value.id
+    );
+    if (window.sencordNatSwiper) {
+      const index = current < 0 ? 0 : current;
+      console.warn("sencordNatSwiperFocus", index);
+      // window.sencordNatSwiper.slideTo(current);
+      window.sencordNatSwiper.slideTo(current);
+    }
+  });
+};
 
 onMounted(() => {
   useApp().then(async (app) => {
     show.value = true;
-    loadList();
+  });
+  watchEffect(() => {
+    if (
+      metadata.value.catalogRoot &&
+      unref(metadata.value.catalogRoot).length > 0
+    ) {
+      initMainSwiper();
+    }
+  });
+
+  watch([currentSecondary, secondaryList], () => {
+    if (unref(secondaryList).length > 1) {
+      initsencordNatSwiper();
+      sencordNatSwiperFocus();
+    } else {
+      if (window.sencordNatSwiper) {
+        console.warn("destroy-sencordNatSwiper");
+        window.sencordNatSwiper.update();
+        window.sencordNatSwiper.slideReset();
+      }
+    }
+  });
+
+  watch(currentScenesList, () => {
+    initScenesSwiper();
+  });
+  watch(currentCatalogRoot, (val) => {
+    if (Array.from(unref(val).children).includes(currentScene.value.category)) {
+      //当前场景在一类的children
+      const activeSecond = Array.from(unref(secondaryList)).find(
+        (i) => i.id === currentScene.value.category
+      );
+      console.log("activeSecond", activeSecond);
+      store.commit("scene/setCurrentSecondary", activeSecond);
+      if (window.sencordNatSwiper) {
+        window.sencordNatSwiper.update();
+      }
+    }
   });
 });
 </script>
@@ -281,7 +409,7 @@ $width: 1150px;
         &.loopspan {
           > span,
           > div > span {
-            animation: 5s wordsLoop linear infinite normal;
+            animation: 10s wordsLoop linear infinite normal;
           }
         }
 
@@ -407,10 +535,12 @@ $width: 1150px;
           width: 100%;
           overflow: hidden;
 
-          > span {
-            width: 100%;
+          > span,
+          div {
+            // width: 100%;
             line-height: 20px;
             word-break: keep-all;
+            white-space: normal;
           }
         }
 
@@ -436,10 +566,20 @@ $width: 1150px;
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
+  }
+}
+.marquee {
+  .marquee-text-wrap {
+    height: 20px;
+    line-height: 20px;
   }
 }
 </style>
+<style>
+.marquee-text-text {
+  padding: 0 5px;
+}
+</style>

+ 2 - 2
packages/qjkankan-view/src/components/UIGather/logo.vue

@@ -12,8 +12,8 @@
 
 <script setup>
 import { useStore } from "vuex";
-import { ref, onMounted, computed, watch, nextTick } from "vue";
-import { useI18n, getLocale } from "@/i18n";
+import { computed } from "vue";
+import { getLocale } from "@/i18n";
 
 const store = useStore();
 const metadata = computed(() => store.getters["scene/metadata"]);

+ 151 - 67
packages/qjkankan-view/src/components/UIGather/menu.vue

@@ -1,121 +1,199 @@
 <template>
   <ul class="menu">
-    <li @click="onIsShowList"
+    <li
+      @click="onIsShowList"
       v-tooltip="$t('menu.guide')"
-      v-if="!((metadata.catalogRoot && metadata.catalogRoot.length == 1) && scenes.length == 1 && secondaryList.length == 1)">
-      <img :src="require(`@/assets/images/icon/${isShowScenesList ? 'function_off@2x.png' : 'function_on@2x.png'}`)"
-        alt="" />
+      v-if="
+        !(
+          metadata.catalogRoot &&
+          metadata.catalogRoot.length == 1 &&
+          scenes.length == 1 &&
+          secondaryList.length == 1
+        )
+      "
+    >
+      <img
+        :src="
+          require(`@/assets/images/icon/${
+            isShowScenesList ? 'function_off@2x.png' : 'function_on@2x.png'
+          }`)
+        "
+        alt=""
+      />
     </li>
 
-
-    <div class="v-link"
+    <div
+      class="v-link"
       v-if="
-      (!((metadata.catalogRoot && metadata.catalogRoot.length == 1) && scenes.length == 1 && secondaryList.length == 1)) &&
-      currentScene.type == '4dkk' && fdkkmetadata && (fdkkmetadata.controls.showPanorama || fdkkmetadata.controls.showFloorplan || fdkkmetadata.controls.showDollhouse)">
-    </div>
+        !(
+          metadata.catalogRoot &&
+          metadata.catalogRoot.length == 1 &&
+          scenes.length == 1 &&
+          secondaryList.length == 1
+        ) &&
+        currentScene.type == '4dkk' &&
+        fdkkmetadata &&
+        (fdkkmetadata.controls.showPanorama ||
+          fdkkmetadata.controls.showFloorplan ||
+          fdkkmetadata.controls.showDollhouse)
+      "
+    ></div>
 
     <template v-if="currentScene.type == '4dkk'">
-
       <li
-      v-tooltip="$t('menu.panorama')"
-       v-if="fdkkmetadata && fdkkmetadata.controls.showPanorama" :class="{ disabled: isPlayTours || flying }"
-        @click="onModeChange('panorama')">
-        <img :src="require(`@/assets/images/icon/${mode == 'panorama' ? 'roaming_selected' : 'roaming_normal'}@2x.png`)"
-          alt="" />
+        v-tooltip="$t('menu.panorama')"
+        v-if="fdkkmetadata && fdkkmetadata.controls.showPanorama"
+        :class="{ disabled: isPlayTours || flying }"
+        @click="onModeChange('panorama')"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              mode == 'panorama' ? 'roaming_selected' : 'roaming_normal'
+            }@2x.png`)
+          "
+          alt=""
+        />
       </li>
 
       <li
-      v-tooltip="$t('menu.floorplan')"
-      v-if="fdkkmetadata && fdkkmetadata.controls.showFloorplan" :class="{ disabled: isPlayTours || flying }"
-        @click="onModeChange('floorplan')">
-        <img :src="require(`@/assets/images/icon/${mode == 'floorplan' ? 'plane_selected' : 'plane_normal'}@2x.png`)"
-          alt="" />
+        v-tooltip="$t('menu.floorplan')"
+        v-if="fdkkmetadata && fdkkmetadata.controls.showFloorplan"
+        :class="{ disabled: isPlayTours || flying }"
+        @click="onModeChange('floorplan')"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              mode == 'floorplan' ? 'plane_selected' : 'plane_normal'
+            }@2x.png`)
+          "
+          alt=""
+        />
       </li>
 
       <li
-      v-tooltip="$t('menu.dollhouse')"
-       v-if="fdkkmetadata && fdkkmetadata.controls.showDollhouse" :class="{ disabled: isPlayTours || flying }"
-        @click="onModeChange('dollhouse')">
-        <img :src="require(`@/assets/images/icon/${mode == 'dollhouse' ? '3d_selected' : '3d_normal'}@2x.png`)"
-          alt="" />
+        v-tooltip="$t('menu.dollhouse')"
+        v-if="fdkkmetadata && fdkkmetadata.controls.showDollhouse"
+        :class="{ disabled: isPlayTours || flying }"
+        @click="onModeChange('dollhouse')"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              mode == 'dollhouse' ? '3d_selected' : '3d_normal'
+            }@2x.png`)
+          "
+          alt=""
+        />
       </li>
 
-      <div class="v-link"
-        v-if="toursList.length > 0 && fdkkmetadata && (fdkkmetadata.controls.showPanorama || fdkkmetadata.controls.showFloorplan || fdkkmetadata.controls.showDollhouse)">
-      </div>
+      <div
+        class="v-link"
+        v-if="
+          toursList.length > 0 &&
+          fdkkmetadata &&
+          (fdkkmetadata.controls.showPanorama ||
+            fdkkmetadata.controls.showFloorplan ||
+            fdkkmetadata.controls.showDollhouse)
+        "
+      ></div>
 
       <li
-      v-tooltip="$t('menu.tour')"
-       class="daolan" @click.stop="playTour" v-if="toursList.length > 0">
-        <img :src="require(`@/assets/images/icon/${isPlayTours ? 'pause01' : 'playing01'}@2x.png`)" alt="" />
-        <span>{{$t('menu.tour')}}</span>
-        <img @click.stop="openTours" :class="{ active: showTours }" class="jiantou"
-          :src="require(`@/assets/images/icon/expand_arrows@2x.png`)" alt="" />
+        v-tooltip="$t('menu.tour')"
+        class="daolan"
+        @click.stop="playTour"
+        v-if="toursList.length > 0"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              isPlayTours ? 'pause01' : 'playing01'
+            }@2x.png`)
+          "
+          alt=""
+        />
+        <span>{{ $t("menu.tour") }}</span>
+        <img
+          @click.stop="openTours"
+          :class="{ active: showTours }"
+          class="jiantou"
+          :src="require(`@/assets/images/icon/expand_arrows@2x.png`)"
+          alt=""
+        />
       </li>
-
     </template>
-
   </ul>
 </template>
 
 <script setup>
-import { ref, watch, computed, onMounted, nextTick } from "vue";
+import { ref, watch, computed, onMounted, nextTick, watchEffect } from "vue";
 import { useStore } from "vuex";
 const store = useStore();
 const toursList = computed(() => store.getters["fdkk/toursList"]);
 
-const isShowScenesList = computed(() => store.getters["functions/isShowScenesList"]);
+const isShowScenesList = computed(
+  () => store.getters["functions/isShowScenesList"]
+);
 const toursStatus = computed(() => store.getters["fdkk/toursStatus"]);
 const isPlayTours = computed(() => store.getters["fdkk/isPlayTours"]);
 const flying = computed(() => store.getters["fdkk/isFlying"]);
 const mode = computed(() => store.getters["fdkk/mode"]);
 
-
 const showTours = computed(() => store.getters["fdkk/isShowToursList"]);
 
-
 const currentScene = computed(() => store.getters["scene/currentScene"]);
 const metadata = computed(() => store.getters["scene/metadata"]);
 const scenes = computed(() => store.getters["scene/list"]);
 const secondaryList = computed(() => store.getters["scene/secondaryList"]);
 const fdkkmetadata = computed(() => store.getters["fdkk/metadata"]);
 
-
 const openTours = () => {
   if (isShowScenesList.value) {
     store.commit("functions/setShowScenesList", false);
   }
-
-  store.commit('fdkk/setShowToursList', !showTours.value)
-}
+  // debugger;
+  store.commit("fdkk/setShowToursList", !showTours.value);
+};
 
 const playTour = () => {
-  store.commit('fdkk/setToursStatus', !toursStatus.value)
-}
+  store.commit("fdkk/setToursStatus", !toursStatus.value);
+};
 
 const onIsShowList = (data) => {
   if (showTours.value) {
-    store.commit('fdkk/setShowToursList', false)
+    store.commit("fdkk/setShowToursList", false);
   }
   store.commit("functions/setShowScenesList", !isShowScenesList.value);
 };
 
-const onModeChange = name => {
-  document.querySelector('#fdkkifr') && document.querySelector('#fdkkifr').contentWindow.postMessage(
-    {
-      source: "qjkankan",
-      event: "setMode",
-      params: {
-        name: name
-      }
-    },
-    "*"
-  );
-}
-
+const onModeChange = (name) => {
+  document.querySelector("#fdkkifr") &&
+    document.querySelector("#fdkkifr").contentWindow.postMessage(
+      {
+        source: "qjkankan",
+        event: "setMode",
+        params: {
+          name: name,
+        },
+      },
+      "*"
+    );
+};
 
 onMounted(() => {
-})
+  watchEffect(() => {
+    if (isPlayTours.value) {
+      store.commit("functions/setShowScenesList", false);
+    } else {
+      setTimeout(() => {
+        console.log("tours-关闭");
+        store.commit("fdkk/setShowToursList", false);
+        store.commit("functions/setShowScenesList", true);
+      }, 100);
+    }
+  });
+});
 </script>
 
 <style lang="scss" scoped>
@@ -126,13 +204,13 @@ onMounted(() => {
   display: flex;
   z-index: 9;
 
-  >li {
+  > li {
     margin: 0 10px;
     cursor: pointer;
     display: flex;
     justify-content: center;
     align-items: center;
-    >img {
+    > img {
       width: 26px;
       height: 26px;
     }
@@ -141,7 +219,12 @@ onMounted(() => {
   .v-link {
     width: 1px;
     height: 26px;
-    background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 49%, rgba(255, 255, 255, 0) 100%);
+    background: linear-gradient(
+      180deg,
+      rgba(255, 255, 255, 0) 0%,
+      #ffffff 49%,
+      rgba(255, 255, 255, 0) 100%
+    );
   }
 
   .daolan {
@@ -149,7 +232,7 @@ onMounted(() => {
     width: auto;
     align-items: center;
 
-    >img {
+    > img {
       width: 26px;
       height: 26px;
     }
@@ -157,14 +240,15 @@ onMounted(() => {
     .jiantou {
       margin-left: -4px;
       transform: rotate(180deg);
-      transition: .3s ease transform;
+      transition: 0.3s ease transform;
 
       &.active {
         transform: none;
       }
     }
 
-    >span {}
+    > span {
+    }
   }
 }
 </style>

+ 4 - 4
packages/qjkankan-view/src/components/UIGather/mobile/control.fdkk.vue

@@ -131,7 +131,7 @@
 
     <li @click="onIsBGM" v-if="isHasNormalBGM || isHasV4BGM || isHasV3BGM">
       <img
-        v-if="isHasV3BGM"
+        v-if="isHasV3BGM && fdkkCurrentVersion==='V3'"
         :src="
           require(`@/assets/images/icon/${
             isPlayV3BGM ? 'music@2x.png' : 'music_disabled@2x.png'
@@ -233,16 +233,16 @@ const onLink = () => {
 };
 
 const onIsBGM = () => {
-  console.log("fdkk----onIsBGM");
+  console.log("fdkk----onIsBGM", fdkkCurrentVersion.value);
 
-  if (unref(isHasV3BGM)) {
+  if (unref(isHasV3BGM) && fdkkCurrentVersion.value === "V3") {
     const v3playToggle = !unref(isPlayV3BGM);
     console.log("v3playToggle", v3playToggle);
     toggleV3BGM(v3playToggle);
     return;
   }
 
-  if (unref(isHasV4BGM)) {
+  if (unref(isHasV4BGM) && fdkkCurrentVersion.value === "V4") {
     if (!unref(isCurrentPlaying)) {
       store.dispatch("audio/playBGM", 2);
     } else {

+ 162 - 61
packages/qjkankan-view/src/components/UIGather/mobile/list.vue

@@ -40,15 +40,21 @@
                 item.type == '4dkk' ? 'icon-editor_3d' : 'icon-editor_panoramic'
               "
             ></i>
-            <div>
-              <span v-if="currentScene.id == item.id">{{
-                item.sceneTitle
-              }}</span>
-              <span v-else>{{
-                item.sceneTitle.length > spanlength
-                  ? item.sceneTitle.slice(0, spanlength)
-                  : item.sceneTitle
-              }}</span>
+            <div class="marquee">
+              <marquee-text
+                :repeat="1"
+                :duration="Math.ceil(item.sceneTitle.length / 10) * 5"
+                :key="item.id"
+                v-if="
+                  item.sceneTitle.length > spanlength &&
+                  currentScene.id == item.id
+                "
+              >
+                {{ item.sceneTitle }}
+              </marquee-text>
+              <span v-else>
+                {{ item.sceneTitle }}
+              </span>
             </div>
           </li>
         </ul>
@@ -74,14 +80,20 @@
             v-for="(item, i) in secondaryList"
             :key="i"
           >
-            <span v-if="currentSecondary.id == item.id">{{
-              fixTitle(item.name)
-            }}</span>
-            <span v-else>{{
-              fixTitle(item.name).length > spanlength
-                ? fixTitle(item.name).slice(0, spanlength)
-                : fixTitle(item.name)
-            }}</span>
+            <marquee-text
+              :duration="Math.ceil(fixTitle(item.name).length / 10) * 5"
+              :key="item.id"
+              :repeat="1"
+              v-if="
+                fixTitle(item.name).length > spanlength &&
+                currentSecondary.id == item.id
+              "
+            >
+              {{ fixTitle(item.name) }}
+            </marquee-text>
+            <span v-else>
+              {{ fixTitle(item.name) }}
+            </span>
           </li>
         </ul>
       </div>
@@ -107,14 +119,20 @@
           v-for="(item, i) in metadata.catalogRoot"
           :key="i"
         >
-          <span v-if="currentCatalogRoot.id == item.id">{{
-            fixTitle(item.name)
-          }}</span>
-          <span v-else>{{
-            fixTitle(item.name).length > spanlength
-              ? fixTitle(item.name).slice(0, spanlength)
-              : fixTitle(item.name)
-          }}</span>
+          <marquee-text
+            :duration="Math.ceil(fixTitle(item.name).length / 10) * 5"
+            :key="item.id"
+            :repeat="1"
+            v-if="
+              fixTitle(item.name).length > spanlength &&
+              currentCatalogRoot.id == item.id
+            "
+          >
+            {{ fixTitle(item.name) }}
+          </marquee-text>
+          <span v-else>
+            {{ fixTitle(item.name) }}
+          </span>
         </li>
       </ul>
     </div>
@@ -122,11 +140,20 @@
 </template>
 
 <script setup>
-import { ref, watch, computed, onMounted, nextTick } from "vue";
+import {
+  ref,
+  unref,
+  watch,
+  watchEffect,
+  computed,
+  onMounted,
+  nextTick,
+} from "vue";
 import { useStore } from "vuex";
 import { useApp } from "@/app";
 import { useI18n, getLocale } from "@/i18n";
 const { t } = useI18n({ useScope: "global" });
+import MarqueeText from "vue-marquee-text-component";
 
 const store = useStore();
 
@@ -179,6 +206,9 @@ const tabCurrentScene = (data) => {
   console.log("tabCurrentScene", data.id, currentScene.value.id);
   if (data.id !== currentScene.value.id) {
     store.commit("scene/setCurrentScene", data);
+    setTimeout(() => {
+      scenesSwiperFocus();
+    }, 300);
   } else {
     console.log("重复点击当前导航");
     // window.alert("alert-test-->重复点击当前导航");
@@ -204,48 +234,108 @@ const fixTitle = (name) => {
   return name;
 };
 
-const loadList = () => {
-  nextTick(() => {
-    let t = setTimeout(() => {
-      clearTimeout(t);
-      ["#swcatalogRoot", "#swSecondary", "#swScenes"].forEach((item) => {
-        let tmp = new Swiper(item, {
-          slidesPerView: "auto",
-          centeredSlides: true,
-          spaceBetween: 10,
-          centerInsufficientSlides: true,
-          centeredSlidesBounds: true,
-          freeMode: true,
-          observer: true,
-          observeParents: true,
-        });
-        if (item == "#swScenes") {
-          setTimeout(() => {
-            if (tmp && "slideTo" in tmp) {
-              // tmp.slideTo(0, 80, false);
-            }
-          }, 0);
-        }
+const swiperOptions = {
+  slidesPerView: "auto",
+  centeredSlides: true,
+  spaceBetween: 10,
+  centerInsufficientSlides: true,
+  centeredSlidesBounds: true,
+  freeMode: {
+    enabled: true,
+    sticky: false,
+  },
+};
+
+// const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
 
-        // console.log(tmp.slideTo);
+const initMainSwiper = () => {
+  nextTick(() => {
+    if (window.mainNatSwiper) {
+      window.mainNatSwiper.update();
+      window.sencordNatSwiper.slideReset();
+    }
+    window.mainNatSwiper = new Swiper("#swcatalogRoot", swiperOptions);
+  });
+};
+const initsencordNatSwiper = () => {
+  nextTick(() => {
+    if (window.sencordNatSwiper) {
+      window.sencordNatSwiper.update();
+      window.sencordNatSwiper.slideReset();
+    }
+    window.sencordNatSwiper = new Swiper("#swSecondary", swiperOptions);
+  });
+};
+const initScenesSwiper = () => {
+  console.warn("initScenesSwiper");
+  nextTick(() => {
+    if (window.scenesNatSwiper) {
+      window.scenesNatSwiper.update();
+      window.scenesNatSwiper.slideReset();
+      // window.scenesNatSwiper = null;
+    } else {
+      window.scenesNatSwiper = new Swiper("#swScenes", {
+        ...swiperOptions,
       });
-    }, 100);
+    }
+    scenesSwiperFocus();
   });
 };
 
-watch(currentSecondary, () => {
-  loadList();
-});
+const scenesSwiperFocus = () => {
+  const sceneIndex = Array.from(currentScenesList.value).findIndex(
+    (item) => item.id === currentScene.value.id
+  );
+  if (window.scenesNatSwiper && window.scenesNatSwiper.slides.length > 0) {
+    const index = sceneIndex < 0 ? 0 : sceneIndex;
+    console.warn("scenesSwiperFocus", index);
+    window.scenesNatSwiper.slideTo(index);
+  }
+};
 
-watch(currentScenesList, () => {
-  loadList();
-});
+const sencordNatSwiperFocus = () => {
+  nextTick(() => {
+    const current = Array.from(secondaryList.value).findIndex(
+      (item) => item.id === currentSecondary.value.id
+    );
+    if (window.sencordNatSwiper && window.sencordNatSwiper.slides.length > 0) {
+      console.warn("current-sencordNatSwiper-index", current);
+      window.sencordNatSwiper.slideTo(current);
+    }
+  });
+};
 
 onMounted(() => {
   useApp().then(async (app) => {
     show.value = true;
-    loadList();
   });
+  watchEffect(() => {
+    if (
+      metadata.value.catalogRoot &&
+      unref(metadata.value.catalogRoot).length > 0
+    ) {
+      initMainSwiper();
+    }
+  });
+
+  watch(currentSecondary, () => {
+    if (unref(secondaryList).length > 1) {
+      initsencordNatSwiper();
+      sencordNatSwiperFocus();
+    } else {
+      if (window.sencordNatSwiper) {
+        console.warn("destroy-sencordNatSwiper");
+        window.sencordNatSwiper.update();
+        window.sencordNatSwiper.slideReset();
+      }
+    }
+  });
+
+  watch(currentScenesList, () => {
+    initScenesSwiper();
+  });
+
+
 });
 </script>
 
@@ -406,7 +496,8 @@ onMounted(() => {
           width: 100%;
           overflow: hidden;
 
-          > span {
+          > span,
+          div {
             width: 100%;
             line-height: 20px;
             word-break: keep-all;
@@ -435,10 +526,20 @@ onMounted(() => {
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
+  }
+}
+.marquee {
+  .marquee-text-wrap {
+    height: 20px;
+    line-height: 20px;
   }
 }
 </style>
+<style>
+.marquee-text-text {
+  padding: 0 5px;
+}
+</style>

+ 100 - 54
packages/qjkankan-view/src/components/UIGather/mobile/menu.vue

@@ -1,86 +1,131 @@
 <template>
-  <ul class="menu" >
+  <ul class="menu">
     <li @click="onIsShowList">
-      <img :src="require(`@/assets/images/icon/${isShowScenesList ? 'function_off.svg' : 'function_on.svg'}`)" alt="" />
+      <img
+        :src="
+          require(`@/assets/images/icon/${
+            isShowScenesList ? 'function_off.svg' : 'function_on.svg'
+          }`)
+        "
+        alt=""
+      />
     </li>
-   <template v-if="currentScene.type == '4dkk'">
-    <li :class="{ disabled: isPlayTours || flying }"  @click="onModeChange('panorama')">
-      <img :src="require(`@/assets/images/icon/${mode=='panorama'?'roaming_selected':'roaming_normal'}.svg`)" alt="" />
-    </li>
-
-    <li :class="{ disabled: isPlayTours || flying }"  @click="onModeChange('floorplan')">
-      <img :src="require(`@/assets/images/icon/${mode=='floorplan'?'plane_selected':'plane_normal'}.svg`)" alt="" />
-    </li>
-
-    <li :class="{ disabled: isPlayTours || flying }"  @click="onModeChange('dollhouse')">
-      <img :src="require(`@/assets/images/icon/${mode=='dollhouse'?'3d_selected':'3d_normal'}.svg`)" alt="" />
-    </li>
-
-    <li class="daolan" @click.stop="playTour" v-if="toursList.length>0">
-      <img :src="require(`@/assets/images/icon/${isPlayTours?'pause01':'playing01'}.svg`)" alt="" />
-      <span>{{$t('menu.tour')}}</span>
-      <img @click.stop="openTours" :class="{active:showTours}" class="jiantou"
-        :src="require(`@/assets/images/icon/expand_arrows@2x.png`)" alt="" />
-    </li>
-
-   </template>
+    <template v-if="currentScene.type == '4dkk'">
+      <li
+        :class="{ disabled: isPlayTours || flying }"
+        @click="onModeChange('panorama')"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              mode == 'panorama' ? 'roaming_selected' : 'roaming_normal'
+            }.svg`)
+          "
+          alt=""
+        />
+      </li>
+
+      <li
+        :class="{ disabled: isPlayTours || flying }"
+        @click="onModeChange('floorplan')"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              mode == 'floorplan' ? 'plane_selected' : 'plane_normal'
+            }.svg`)
+          "
+          alt=""
+        />
+      </li>
+
+      <li
+        :class="{ disabled: isPlayTours || flying }"
+        @click="onModeChange('dollhouse')"
+      >
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              mode == 'dollhouse' ? '3d_selected' : '3d_normal'
+            }.svg`)
+          "
+          alt=""
+        />
+      </li>
+
+      <li class="daolan" @click.stop="playTour" v-if="toursList.length > 0">
+        <img
+          :src="
+            require(`@/assets/images/icon/${
+              isPlayTours ? 'pause01' : 'playing01'
+            }.svg`)
+          "
+          alt=""
+        />
+        <span>{{ $t("menu.tour") }}</span>
+        <img
+          @click.stop="openTours"
+          :class="{ active: showTours }"
+          class="jiantou"
+          :src="require(`@/assets/images/icon/expand_arrows@2x.png`)"
+          alt=""
+        />
+      </li>
+    </template>
   </ul>
 </template>
 
 <script setup>
-import { ref, watch, computed, onMounted, nextTick } from "vue";
+import { ref, watch, computed, onMounted, nextTick, watchEffect } from "vue";
 import { useStore } from "vuex";
 const store = useStore();
 const toursList = computed(() => store.getters["fdkk/toursList"]);
 
-const isShowScenesList = computed(() => store.getters["functions/isShowScenesList"]);
+const isShowScenesList = computed(
+  () => store.getters["functions/isShowScenesList"]
+);
 const toursStatus = computed(() => store.getters["fdkk/toursStatus"]);
 const isPlayTours = computed(() => store.getters["fdkk/isPlayTours"]);
 const flying = computed(() => store.getters["fdkk/isFlying"]);
 const mode = computed(() => store.getters["fdkk/mode"]);
 
-
 const showTours = computed(() => store.getters["fdkk/isShowToursList"]);
 
-
 const currentScene = computed(() => store.getters["scene/currentScene"]);
 
-
 const openTours = () => {
   if (isShowScenesList.value) {
     store.commit("functions/setShowScenesList", false);
   }
-  
-  store.commit('fdkk/setShowToursList', !showTours.value)
-}
+
+  store.commit("fdkk/setShowToursList", !showTours.value);
+};
 
 const playTour = () => {
-  store.commit('fdkk/setToursStatus', !toursStatus.value)
-}
+  store.commit("fdkk/setToursStatus", !toursStatus.value);
+};
 
 const onIsShowList = (data) => {
   if (showTours.value) {
-    store.commit('fdkk/setShowToursList', false)
+    store.commit("fdkk/setShowToursList", false);
   }
   store.commit("functions/setShowScenesList", !isShowScenesList.value);
 };
 
-const onModeChange = name => {
-  document.querySelector('#fdkkifr') && document.querySelector('#fdkkifr').contentWindow.postMessage(
-    {
-      source: "qjkankan",
-      event: "setMode",
-      params:{
-        name:name
-      }
-    },
-    "*"
-  );    
-}
-
+const onModeChange = (name) => {
+  document.querySelector("#fdkkifr") &&
+    document.querySelector("#fdkkifr").contentWindow.postMessage(
+      {
+        source: "qjkankan",
+        event: "setMode",
+        params: {
+          name: name,
+        },
+      },
+      "*"
+    );
+};
 
-onMounted(() => {
-})
 </script>
 
 <style lang="scss" scoped>
@@ -91,13 +136,13 @@ onMounted(() => {
   display: flex;
   z-index: 9;
 
-  >li {
+  > li {
     width: 36px;
     height: 36px;
     margin: 0 10px;
     cursor: pointer;
 
-    >img {
+    > img {
       width: 100%;
       height: 100%;
     }
@@ -108,7 +153,7 @@ onMounted(() => {
     width: auto;
     align-items: center;
 
-    >img {
+    > img {
       width: 36px;
       height: 36px;
     }
@@ -116,14 +161,15 @@ onMounted(() => {
     .jiantou {
       margin-left: -4px;
       transform: rotate(180deg);
-      transition: .3s ease transform;
+      transition: 0.3s ease transform;
 
       &.active {
         transform: none;
       }
     }
 
-    >span {}
+    > span {
+    }
   }
 }
 </style>

+ 4 - 4
packages/qjkankan-view/src/components/UIGather/mobile/tips.vue

@@ -15,20 +15,20 @@ import { useApp } from "@/app";
 import { useStore } from "vuex";
 const store = useStore();
 const metadata = computed(() => store.getters["scene/metadata"]);
-
+const currentScene = computed(() => store.getters["scene/currentScene"]);
 const show = ref(false);
+const isPano = computed(() => currentScene.value.type === "pano");
 
 useApp().then((app) => {
   app.Scene.on("sceneReady", () => {
     console.log(metadata.value.isRemind);
     let locoR = "localRemind" + metadata.value.id;
-    if (metadata.value.isRemind) {
+    if (metadata.value.isRemind && isPano.value) {
       show.value =
         localStorage.getItem(locoR) == 1 ? false : !!metadata.value.remindTime;
       localStorage.setItem(locoR, 1);
     } else {
-      console.log(metadata.value.remindTime);
-      if (metadata.value.remindTime) {
+      if (metadata.value.remindTime && isPano.value) {
         show.value = true;
       }
       localStorage.setItem(locoR, 0);

+ 2 - 3
packages/qjkankan-view/src/components/UIGather/mobile/tours.vue

@@ -179,10 +179,9 @@ $width: 1150px;
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
   100% {
-    transform: translateX(-100%);
-    -webkit-transform: translateX(-100%);
+    transform: translateX(-180%);
+    -webkit-transform: translateX(-180%);
   }
 }
 </style>

+ 17 - 8
packages/qjkankan-view/src/components/UIGather/tips.vue

@@ -1,27 +1,36 @@
 <template>
   <div v-if="show" class="user-tips-overlay">
-    <img :src="metadata.pcIcon || require('@/assets/images/default/show/img_tipspc_default.png')" alt="" />
+    <img
+      :src="
+        metadata.pcIcon ||
+        require('@/assets/images/default/show/img_tipspc_default.png')
+      "
+      alt=""
+    />
   </div>
 </template>
 <script setup>
-import { onMounted, watch, computed, ref, nextTick } from "vue";
+import { onMounted, watch, computed, ref, nextTick, unref } from "vue";
 import { useApp } from "@/app";
 import { useStore } from "vuex";
 const store = useStore();
 const metadata = computed(() => store.getters["scene/metadata"]);
-
+const currentScene = computed(() => store.getters["scene/currentScene"]);
 const show = ref(false);
+const isPano = computed(() => currentScene.value.type === "pano");
 
 useApp().then((app) => {
   app.Scene.on("sceneReady", () => {
-    console.log(metadata.value.isRemind);
     let locoR = "localRemind" + metadata.value.id;
-    if (metadata.value.isRemind) {
-      show.value = localStorage.getItem(locoR) == 1 ? false : !!metadata.value.remindTime;
+    console.error("localRemind状态", metadata.value.isRemind && isPano.value);
+
+    if (metadata.value.isRemind && isPano.value) {
+      show.value =
+        localStorage.getItem(locoR) == 1 ? false : !!metadata.value.remindTime;
       localStorage.setItem(locoR, 1);
     } else {
-      console.log(metadata.value.remindTime);
-      if (metadata.value.remindTime) {
+      console.error("remindTime", metadata.value.remindTime);
+      if (metadata.value.remindTime && isPano.value) {
         show.value = true;
       }
       localStorage.setItem(locoR, 0);

+ 10 - 2
packages/qjkankan-view/src/components/UIGather/tours.vue

@@ -195,10 +195,18 @@ $width: 1150px;
     transform: translateX(100%);
     -webkit-transform: translateX(100%);
   }
-
-  100% {
+  50% {
+    transform: translateX(-80%);
+    -webkit-transform: translateX(-80%);
+  }
+  80% {
     transform: translateX(-100%);
     -webkit-transform: translateX(-100%);
   }
+
+  100% {
+    transform: translateX(-110%);
+    -webkit-transform: translateX(-110%);
+  }
 }
 </style>

+ 1 - 1
packages/qjkankan-view/src/components/assembly/Share.vue

@@ -3,7 +3,7 @@
     <div>
       <div class="tips">
         <h4>{{ $t("share.shareLink") }}</h4>
-        <i class="iconfont icon-bs_close" @click="onNo"></i>
+        <i class="iconfont icon-close" @click="onNo"></i>
       </div>
       <div class="url">{{ copyLink }}</div>
       <div class="btns">

+ 16 - 2
packages/qjkankan-view/src/hooks/useAudio.js

@@ -14,8 +14,10 @@ const currentAudioTemp = ref("");
 const isDoneforCover = computed(() => store.getters["scene/isDoneforCover"]);
 const currentScene = computed(() => store.getters["scene/currentScene"]);
 const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
-const isShowCover = computed(
-  () => store.getters["scene/metadata"].coverInfo.isShowCover === 1 || false
+const isShowCover = computed(() =>
+  "isShowCover" in store.getters["scene/metadata"].coverInfo
+    ? store.getters["scene/metadata"].coverInfo.isShowCover === 1
+    : false
 );
 
 async function initDefaultAudio() {
@@ -35,6 +37,7 @@ async function initDefaultAudio() {
       }
       watchUpdateCurrentScenEexplanation(unref(val3));
       watchResetV4BGM(unref(val3));
+      watchSWitchNormalBGM(unref(val3));
     },
     {
       deep: true,
@@ -63,6 +66,9 @@ async function initDefaultAudio() {
             unref(currentPlayer).resume();
           }
         }
+      } else {
+        console.log("为空暂时");
+        unref(currentPlayer) && unref(currentPlayer).stop();
       }
     },
     {
@@ -119,6 +125,14 @@ function watchResetV4BGM(data) {
     store.dispatch("audio/initV4BGM", "");
   }
 }
+function watchSWitchNormalBGM(data) {
+  if (data.type === "pano") {
+    console.log("watchSWitchNormalBGM");
+    if (store.getters["audio/isHasNormalBGM"]) {
+      store.dispatch("audio/playBGM", 0);
+    }
+  }
+}
 
 function createAudioPlayer(url, autoplay, loop = true) {
   const player = new AudioPlayer({

+ 1 - 1
packages/qjkankan-view/src/hooks/useWxshared.js

@@ -4,7 +4,7 @@ import { onMounted } from "vue";
 const initWxShare = async () => {
   // onMounted(async () => {
   try {
-    await new Promise((r) => setTimeout(r, 1000));
+    // await new Promise((r) => setTimeout(r, 1000));
     const title = document.title;
     const link = window.location.href;
     // const desc = '测试微信分享'

+ 0 - 63
packages/qjkankan-view/src/locales/zh copy.json

@@ -1,63 +0,0 @@
-{
-  "common": {
-    "none": "无",
-    "confirm": "确定",
-    "cancel": "取消",
-    "tips": "提示",
-    "hide": "隐藏",
-    "show": "显示",
-    "review": "预览",
-    "open": "开",
-    "close": "关",
-    "pauseTour": "暂停导览",
-    "playTour": "播放导览",
-    "passwordTips": "请输入浏览密码",
-    "passwordError": "密码错误",
-    "tour": "导览",
-    "support": "四维时代提供技术支持",
-    "all": "全部",
-    "model": "三维模式"
-  },
-  "limit": {
-    "viewInVr": "请在手机展示页面观看VR效果"
-  },
-  "share": {
-    "wechat": "微信",
-    "friends": "朋友圈",
-    "qq": "QQ",
-    "facebook": "Facebook",
-    "whatsApp": "WhatsApp",
-    "copyLink": "复制链接",
-    "shareLink": "分享链接",
-    "shareLinkTips": "分享作品",
-    "vrMode": "VR模式",
-    "fastCopy": "复制链接"
-  },
-  "toast": {
-    "copySuccess": "复制成功",
-    "inputPassword": "请输入密码",
-    "checkBrowser": "无法打开页面,请升级或更换浏览器后重新打开",
-    "changeBrowser": "建议使用以下浏览器"
-  },
-  "mode": {
-    "panorama": "漫游",
-    "floorplan": "平面",
-    "dollhouse": "三维",
-    "dollhouseModel": "三维模型",
-    "vr": "VR功能",
-    "music": "音乐",
-    "fullScene": "全屏",
-    "exitFullScene": "退出全屏"
-  },
-  "code": "操作失败,请稍后再试",
-  "model": {
-    "enter": "入户门"
-  },
-  "guide": {
-    "title": "操作提示",
-    "pano": "行走<br />点击任意方向移动",
-    "rotate": "旋转视角<br />左右滑动屏幕,旋转视觉",
-    "zoom": "缩放<br />双指滑动放大或缩小视图",
-    "set": "我知道了"
-  }
-}

+ 5 - 1
packages/qjkankan-view/src/pages/show.vue

@@ -112,7 +112,11 @@ onMounted(async () => {
     // 所有audio入口
 
     const currentSceneData = firstScene || data.scenes[0];
-    store.dispatch("audio/initNormalBGM", data.backgroundMusic.ossPath || "");
+    
+    store.dispatch(
+      "audio/initNormalBGM",
+      data.backgroundMusic ? data.backgroundMusic.ossPath : ""
+    );
     store.commit("scene/setCurrentScene", currentSceneData);
 
     // 过滤空分组

+ 5 - 2
packages/qjkankan-view/src/pages/showMobile.vue

@@ -97,7 +97,7 @@ onMounted(async () => {
       hasPasswordLock.value = true;
     }
     store.commit("scene/setMetaData", data);
-    
+
     // document.title = data.name || t("common.no_title");
 
     let firstScene = "";
@@ -117,7 +117,10 @@ onMounted(async () => {
 
     const currentSceneData = firstScene || data.scenes[0];
     // debugger;
-    store.dispatch("audio/initNormalBGM", data.backgroundMusic.ossPath || "");
+    store.dispatch(
+      "audio/initNormalBGM",
+      data.backgroundMusic ? data.backgroundMusic.ossPath : ""
+    );
     store.commit("scene/setCurrentScene", currentSceneData);
 
     // 过滤空分组

+ 9 - 1
packages/qjkankan-view/src/store/modules/audio.js

@@ -43,6 +43,7 @@ export default {
         repeat: false,
       }, //解说音乐
       currentPlaying: false,
+      pauseByControl: false,
     };
   },
   getters: {
@@ -88,6 +89,9 @@ export default {
     isPlayExplanationBGM: (_, getters) => {
       return getters.currentAudio.type === 3;
     },
+    isPauseByControl: (state) => {
+      return state.pauseByControl;
+    },
   },
   mutations: {
     setNormalBGM(state, payload) {
@@ -151,6 +155,7 @@ export default {
       const index = getters["currentAudio"].order;
       const order = index + 1;
       const target = getters["bgmList"].find((i) => i.type === type);
+      state.pauseByControl = false;
       if (target.url.length > 0) {
         switch (type) {
           case 0:
@@ -174,11 +179,14 @@ export default {
         }
       }
     },
-    pauseBGM() {
+    pauseBGM({ commit, getters, state, dispatch }, from) {
       const { currentPlayer } = useAudio();
       if (unref(currentPlayer)) {
         currentPlayer.value.pause();
       }
+      if (from === 0) {
+        state.pauseByControl = true;
+      }
     },
     resumeBGM() {
       const { currentPlayer } = useAudio();

+ 1 - 1
packages/qjkankan-view/src/utils/debuggerHelper.js

@@ -2,7 +2,7 @@
 import { useToast } from "vue-toastification";
 
 export const debuggerHelper = (show = true) => {
-  const version = "1.4.0--" + process.env.VUE_APP_DEBBUG_FLAG;
+  const version = "1.5.0--" + process.env.VUE_APP_DEBBUG_FLAG;
   if (show) {
     // log.setColors({
     var css = "background: #28b561; color:#fff;font-size:14px;padding:5px;";

+ 19 - 19
packages/qjkankan-view/src/utils/wxshare.js

@@ -6,12 +6,13 @@ export function toConfigure() {
       url: "//www.4dage.com/wechat/jssdk/share",
       type: "get",
       data: {
-        uri: location.href.split("#")[0],
+        uri: window.location.href.split("#")[0],
         name: "厦门四维时代微信公众号",
       },
       dataType: "jsonp",
       //jsonpCallback: "success_jsonp",
       success: function (data, textStatus) {
+        console.log("微信签名", data);
         wx.config({
           debug: false,
           appId: data.appId,
@@ -22,8 +23,8 @@ export function toConfigure() {
             "checkJsApi",
             "updateAppMessageShareData",
             "updateTimelineShareData",
-            "onMenuShareAppMessage",
-            "onMenuShareTimeline",
+            // "onMenuShareAppMessage",
+            // "onMenuShareTimeline",
             "onMenuShareQQ",
             "onMenuShareWeibo",
             // "hideMenuItems",
@@ -100,24 +101,20 @@ function setup({ title, link, imgUrl, desc }) {
 
   wx.ready(function () {
     // 微信朋友圈
-    data.open = "wx_friends";
+    // data.open = "wx_friends";
     // wx.onMenuShareTimeline({ title, link: path + jsonToStr(data), imgUrl, desc });
-    wx.updateTimelineShareData({
-      title,
-      link: path + jsonToStr(data),
-      imgUrl,
-      desc,
-    });
+
+    const shareData = {
+      title: title,
+      desc: desc,
+      link: window.location.href,
+      imgUrl: imgUrl,
+    };
+    wx.updateAppMessageShareData(shareData);
+    wx.updateTimelineShareData(shareData);
+    console.log("shareData", shareData);
     // 微信好友
-    data.open = "wx_friend";
-    wx.updateAppMessageShareData({
-      title,
-      desc,
-      link: path + jsonToStr(data),
-      imgUrl,
-      type: defaultChar,
-      dataUrl: defaultChar,
-    });
+
     // 微博
     data.open = "weibo";
     wx.onMenuShareWeibo({
@@ -150,6 +147,9 @@ function setup({ title, link, imgUrl, desc }) {
     });
     wx.error(function (e) {});
   });
+  wx.error(function (res) {
+    console.log("微信分享错误信息", res);
+  });
 }
 
 export default async (args) => {

Plik diff jest za duży
+ 4336 - 4246
yarn.lock