gemercheung пре 2 година
родитељ
комит
31db23e68f

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

@@ -58,9 +58,9 @@
             <span class="name ellipsis" v-title="item.sceneTitle">{{item.sceneTitle}}</span>
           </span>
         </div>
-        <div class="no-more-data">
+        <!-- <div class="no-more-data">
           - {{$i18n.t('gather.no_more_data')}} -
-        </div>
+        </div> -->
       </div>
       <!-- 无数据时的提示 -->
       <div v-show="!(panoList.length !== 0)" class="no-data">
@@ -104,9 +104,9 @@
             <span class="name ellipsis" v-title="item.sceneTitle">{{item.sceneTitle}}</span>
           </span>
         </div>
-        <div class="no-more-data">
+        <!-- <div class="no-more-data">
           - {{$i18n.t('gather.no_more_data')}} -
-        </div>
+        </div> -->
       </div>
       <!-- 无数据时的提示 -->
       <div v-show="!(scene3DList.length !== 0)" class="no-data">

+ 1 - 1
packages/qjkankan-editor/src/views/hotspot/hotspotIconType/personalized_tag.vue

@@ -71,7 +71,7 @@
       />
     </div>
 
-    <div class="remark">{{ $i18n.t("hotspot.text_direction") }}</div>
+    <!-- <div class="remark">{{ $i18n.t("hotspot.text_direction") }}</div> -->
     <!-- <TabbarSwitcherIcon
       class="text-direction-switcher"
       :tabList="[

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

@@ -18,11 +18,12 @@
     "clipboard": "^2.0.11",
     "core-js": "^3.8.3",
     "photoswipe": "^5.2.2",
+    "swiper": "^9.2.3",
     "tiny-emitter": "^2.1.0",
     "vue": "^3.2.13",
     "vue-i18n": "^9.1.10",
-    "vuex": "^4.0.0",
-    "vue3-lazyload":"^0.3.6"
+    "vue3-lazyload": "^0.3.6",
+    "vuex": "^4.0.0"
   },
   "devDependencies": {
     "@babel/core": "^7.12.16",

+ 2 - 2
packages/qjkankan-view/src/components/assembly/MobileTags/index.vue

@@ -3,7 +3,7 @@
     <div class="tag-layer" @click.stop>
       <div class="tag-header">
         <span>{{currentTag.hotspotTitle}}</span>
-        <ui-icon  v-if="currentTag.hotspotType != 'image'" class="close" @click.stop="close" type="player_close"></ui-icon>
+        <ui-icon  v-if="!['image'].includes(currentTag.hotspotType) " class="close" @click.stop="close" type="player_close"></ui-icon>
       </div>
       <metasImage @close="close" v-if="currentTag.hotspotType == 'image'" />
       <metasWeb v-if="currentTag.hotspotType == 'link'" />
@@ -12,7 +12,7 @@
       <metasText v-if="currentTag.hotspotType == 'textarea'" />
       <metasPdf v-if="currentTag.hotspotType == 'pdf'" />
       <metasArticle v-if="currentTag.hotspotType == 'article'" />
-      <metasImageText v-if="currentTag.hotspotType == 'imageText'" />
+      <metasImageText @close="close" v-if="currentTag.hotspotType == 'imageText'" />
     </div>
   </teleport>
 </template>

+ 2 - 12
packages/qjkankan-view/src/components/assembly/MobileTags/metas/metas-article.vue

@@ -5,24 +5,14 @@
 </template>
 
 <script setup>
-import {
-  reactive,
-  defineEmits,
-  onBeforeMount,
-  onMounted,
-  ref,
-  watchEffect,
-  computed,
-  watch,
-  nextTick,
-} from "vue";
+import { computed } from "vue";
 import { useStore } from "vuex";
 const store = useStore();
 
 const currentTag = computed(() => store.getters["tags/currentTag"]);
 </script>
 
-<style lang="scss" >
+<style lang="scss">
 .txtcon {
   display: flex;
   align-items: flex-start;

+ 222 - 42
packages/qjkankan-view/src/components/assembly/MobileTags/metas/metas-imagetext.vue

@@ -1,61 +1,241 @@
 <template>
-  <div class="txtcon">
-    <div class="title">
-      <i class="iconfont icon-material_text" />
-      {{ currentTag.hotspotTitle }}
+  <div class="imagetext-container">
+    <div class="metas-imagetext">
+      <div class="image-content">
+        <Swiper
+          :pagination="{
+            type: 'fraction',
+          }"
+          :zoom="true"
+          class="mySwiper"
+          :modules="modules"
+          :slides-per-view="1"
+          :free-mode="true"
+        >
+          <swiper-slide
+            v-for="(item, index) in currentTag.imageTextInfo.imageList"
+            :key="index"
+          >
+            <img :src="item.ossPath" />
+          </swiper-slide>
+        </Swiper>
+        <div class="audio-control" v-if="hasAudio">
+          <ui-icon
+            @click="pauseAudio"
+            type="player_pause"
+            v-if="isPlaying"
+          ></ui-icon>
+          <ui-icon @click="playAudio" type="player_playback" v-else></ui-icon>
+          <span class="timeline">{{ time }} / {{ audioAllTime }}</span>
+          <audio
+            id="audioTag"
+            class="noshow"
+            autoplay
+            :src="currentTag.imageTextInfo.audio.ossPath"
+          ></audio>
+        </div>
+      </div>
+      <div class="text-content">
+        <div v-html="currentTag.imageTextInfo.text"></div>
+      </div>
     </div>
-
-    <div class="txtbody" v-html="currentTag.articleInfo.html"></div>
   </div>
 </template>
-
 <script setup>
-import { computed, onMounted } from "vue";
+import {
+  reactive,
+  nextTick,
+  onMounted,
+  ref,
+  computed,
+  onUnmounted,
+  unref,
+} from "vue";
 import { useStore } from "vuex";
+import { useI18n, getLocale } from "@/i18n";
+import { Swiper, SwiperSlide } from "swiper/vue";
+import { Pagination, Navigation } from "swiper";
+// Import Swiper styles
+import "swiper/css";
+// import "swiper/swiper.scss";
+// swiper-bundle.min.css 决定了小圆点和左右翻页标签,如果不需要可以不引用
+
 const store = useStore();
+const { t } = useI18n({ useScope: "global" });
 
 const currentTag = computed(() => store.getters["tags/currentTag"]);
 
+const modules = ref([Pagination, Navigation]);
+const hasAudio = computed(
+  () => currentTag.value.imageTextInfo.audio.ossPath.length > 0
+);
+const time = ref("00:00");
+const audioAllTime = ref("");
+const isPlaying = ref(false);
+
+function transTime(time) {
+  var duration = parseInt(time);
+  var minute = parseInt(duration / 60);
+  var sec = (duration % 60) + "";
+  var isM0 = ":";
+  if (minute == 0) {
+    minute = "00";
+  } else if (minute < 10) {
+    minute = "0" + minute;
+  }
+  if (sec.length == 1) {
+    sec = "0" + sec;
+  }
+  return minute + isM0 + sec;
+}
+onMounted(() => {
+  const audio = document.querySelector("#audioTag");
+  nextTick(() => {
+    if (unref(hasAudio)) {
+      audio.addEventListener("loadedmetadata", (e) => {
+        audioAllTime.value = transTime(e.currentTarget.duration);
+        console.log("e", unref(audioAllTime));
+        isPlaying.value = true;
+      });
+
+      console.log("audio", audio);
+      audio.addEventListener(
+        "playing",
+        function (e) {
+          isPlaying.value = true;
+        },
+        false
+      );
+      audio.addEventListener(
+        "pause",
+        function (e) {
+          isPlaying.value = false;
+        },
+        false
+      );
+      audio.addEventListener(
+        "timeupdate",
+        function (event) {
+          time.value = transTime(event.target.currentTime);
+        },
+        false
+      );
+    }
+  });
+});
+
+const playAudio = () => {
+  const audio = document.querySelector("#audioTag");
+  audio && audio.play();
+};
+const pauseAudio = () => {
+  const audio = document.querySelector("#audioTag");
+  audio && audio.pause();
+};
+onUnmounted(() => {
+  pauseAudio();
+});
 </script>
 
-<style lang="scss" scoped>
-.txtcon {
-  display: flex;
-  align-items: flex-start;
-  justify-content: center;
-  height: 100%;
+<style lang="scss">
+.imagetext-container {
+  overflow-y: scroll;
+  height: calc(100vh - 50px);
   width: 100%;
-  padding-top: 70px;
-
-  .txtbody {
-    width: 744px;
-    background: rgba(0, 0, 0, 0.6);
-    border-radius: 10px;
-    font-size: 14px;
-    color: #fff;
-    padding: 30px;
-    max-height: calc(100vh - 100px);
-    overflow-y: auto;
-    line-height: 1.5;
-    :deep(p) {
-      line-height: 24px;
+  overflow-x: hidden;
+}
+.metas-imagetext {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  min-height: 180%;
+  .image-content {
+    height: 80vh;
+    width: 100%;
+    position: relative;
+    overflow: hidden;
+    .mySwiper {
+      width: 100%;
+      height: 100%;
+    }
+    .swiper-slide {
+      text-align: center;
+      font-size: 18px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .swiper-slide img {
+      display: block;
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+
+    .audio-control {
+      position: absolute;
+      bottom: 50px;
+      border-radius: 8px;
+      background: rgba(0, 0, 0, 0.6);
+      width: 122px;
+      height: 32px;
+      background: rgba(0, 0, 0, 0.4);
+      opacity: 1;
+      border: 1px solid rgba(255, 255, 255, 0.2);
+      left:70%;
+      transform: translateX(-70%);
+      line-height: 32px;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      .iconfont {
+        margin-left: 0;
+        color: #fff;
+        margin-right: 2px;
+      }
+      .timeline {
+        color: #fff;
+      }
     }
   }
-  .title {
-    position: absolute;
-    left: 20px;
-    top: 20px;
-    height: 36px;
-    line-height: 36px;
-    padding: 0 16px;
-    background: rgba(0, 0, 0, 0.6);
-    border-radius: 20px;
-    color: #fff;
-    font-size: 14px;
-    z-index: 999;
-    > i {
-      margin-right: 4px;
+  .text-content {
+    background-color: #fff;
+    box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
+    min-height: 90vh;
+    padding: 30px 20px 25px;
+    word-wrap: break-word;
+    border-top-left-radius: 10px;
+    border-top-right-radius: 10px;
+    position: relative;
+    &::before {
+      content: "";
+      width: 35px;
+      height: 4px;
+      background: #444444;
+      border-radius: 13px 13px 13px 13px;
+      opacity: 1;
+      position: absolute;
+      top: 14px;
+      left: 50%;
+      transform: translateX(-50%);
     }
   }
 }
+.swiper-pagination {
+  width: 56px;
+  height: 32px;
+  line-height: 30px;
+  background: rgba(0, 0, 0, 0.4);
+  opacity: 1;
+  border: 1px solid rgba(255, 255, 255, 0.2);
+  color: #fff;
+  border-radius: 15px;
+  left: 20%;
+  transform: translateX(-20%);
+  bottom: 50px;
+  .swiper-pagination-total {
+    color: #858586;
+  }
+}
 </style>

+ 18 - 12
packages/qjkankan-view/src/components/assembly/Tags/metas/metas-imagetext.vue

@@ -35,7 +35,9 @@
                 v-if="currentTag.imageTextInfo.imageList.length > 1"
                 class="iconfont icon-material_preview_next1 hover-tips append-splitter"
                 :class="{
-                  disabled: currentIndex === currentTag.imageTextInfo.imageList.length - 1,
+                  disabled:
+                    currentIndex ===
+                    currentTag.imageTextInfo.imageList.length - 1,
                 }"
                 @click="onClickNext()"
               >
@@ -86,17 +88,21 @@
               </i>
             </div>
           </div>
-          <div class="audio-control">
-            <ui-icon @click="pauseAudio" type="player_pause" v-if="isPlaying"></ui-icon>
-            <ui-icon @click="playAudio"  type="player_playback" v-else></ui-icon>
+          <div class="audio-control" v-if="hasAudio">
+            <ui-icon
+              @click="pauseAudio"
+              type="player_pause"
+              v-if="isPlaying"
+            ></ui-icon>
+            <ui-icon @click="playAudio" type="player_playback" v-else></ui-icon>
             <span class="timeline">{{ time }} / {{ audioAllTime }}</span>
+            <audio
+              id="audioTag"
+              class="noshow"
+              autoplay
+              :src="currentTag.imageTextInfo.audio.ossPath"
+            ></audio>
           </div>
-          <audio
-            id="audioTag"
-            class="noshow"
-            autoplay
-            :src="currentTag.imageTextInfo.audio.ossPath"
-          ></audio>
         </div>
       </div>
       <!-- 文字 -->
@@ -244,9 +250,9 @@ const pauseAudio = () => {
   const audio = document.querySelector("#audioTag");
   audio && audio.pause();
 };
-onUnmounted(()=>{
+onUnmounted(() => {
   pauseAudio();
-})
+});
 </script>
 
 <style lang="scss" scoped>

+ 17 - 0
yarn.lock

@@ -15402,6 +15402,11 @@ ssr-window@^3.0.0-alpha.1:
   resolved "https://mirrors.cloud.tencent.com/npm/ssr-window/-/ssr-window-3.0.0.tgz#fd5b82801638943e0cc704c4691801435af7ac37"
   integrity sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==
 
+ssr-window@^4.0.2:
+  version "4.0.2"
+  resolved "https://mirrors.cloud.tencent.com/npm/ssr-window/-/ssr-window-4.0.2.tgz#dc6b3ee37be86ac0e3ddc60030f7b3bc9b8553be"
+  integrity sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==
+
 ssri@^6.0.1:
   version "6.0.2"
   resolved "https://mirrors.cloud.tencent.com/npm/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
@@ -15810,6 +15815,13 @@ swiper@^5.3.8:
     dom7 "^2.1.5"
     ssr-window "^2.0.0"
 
+swiper@^9.2.3:
+  version "9.2.3"
+  resolved "https://mirrors.cloud.tencent.com/npm/swiper/-/swiper-9.2.3.tgz#557b5872f711de0e9a80c8cb2901c645f7937b19"
+  integrity sha512-hxqcjIsYPP1fv+KIXPqGywl6ik8RBp0y0i9+TOIh55ca6SpZ5FrgNJ4QXPhsl6mlSBMEYPmh5zOKtZpI8zpWeQ==
+  dependencies:
+    ssr-window "^4.0.2"
+
 table@^5.2.3:
   version "5.4.6"
   resolved "https://mirrors.cloud.tencent.com/npm/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e"
@@ -16660,6 +16672,11 @@ vue-awesome-swiper@^4.1.1:
   resolved "https://mirrors.cloud.tencent.com/npm/vue-awesome-swiper/-/vue-awesome-swiper-4.1.1.tgz#8f7ab221ad003021d756b86aa618f429924900fe"
   integrity sha512-50um10t6N+lJaORkpwSi1wWuMmBI1sgFc9Znsi5oUykw2cO5DzLaBHcO2JNX21R+Ue4TGoIJDhhxjBHtkFrTEQ==
 
+vue-awesome-swiper@^5.0.1:
+  version "5.0.1"
+  resolved "https://mirrors.cloud.tencent.com/npm/vue-awesome-swiper/-/vue-awesome-swiper-5.0.1.tgz#ba0d20ec9ca4dff2b7b4e99592cf59308335dfcc"
+  integrity sha512-mWjFJzUqA4lG+DmsmibvMpoiBnl+IH2SSeiiQ3i5M0t1y9FknTxnGT0DsMb2YdJLgjYMEK3sYOWzqgLnZMH8Lg==
+
 vue-cropper@^1.0.2:
   version "1.0.7"
   resolved "https://mirrors.cloud.tencent.com/npm/vue-cropper/-/vue-cropper-1.0.7.tgz#be8f22bcaa012a93917ad4dc2aab1e0e8e138e1d"