gemercheung 2 år sedan
förälder
incheckning
a4aa98161a

+ 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.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/
 
 
 

+ 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"

+ 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>

+ 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";

+ 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=0801-01
+VUE_APP_DEBBUG_FLAG=0801-02
 VUE_APP_DEBBUG_NOTIFY=0
 VUE_APP_DEBBUG_V4=0
 VUE_APP_DEBBUG_V4_URL="http://192.168.0.186:8081"

+ 50 - 0
yarn.lock

@@ -7308,6 +7308,11 @@ diffie-hellman@^5.0.0:
     miller-rabin "^4.0.0"
     randombytes "^2.0.0"
 
+dijkstrajs@^1.0.1:
+  version "1.0.3"
+  resolved "https://mirrors.cloud.tencent.com/npm/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23"
+  integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==
+
 dir-glob@^2.0.0, dir-glob@^2.2.2:
   version "2.2.2"
   resolved "http://192.168.0.47:4873/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4"
@@ -7580,6 +7585,11 @@ emojis-list@^3.0.0:
   resolved "http://192.168.0.47:4873/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
   integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
 
+encode-utf8@^1.0.3:
+  version "1.0.3"
+  resolved "https://mirrors.cloud.tencent.com/npm/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda"
+  integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
+
 encodeurl@~1.0.2:
   version "1.0.2"
   resolved "http://192.168.0.47:4873/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@@ -13202,6 +13212,11 @@ please-upgrade-node@^3.2.0:
   dependencies:
     semver-compare "^1.0.0"
 
+pngjs@^5.0.0:
+  version "5.0.0"
+  resolved "https://mirrors.cloud.tencent.com/npm/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
+  integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
+
 pnp-webpack-plugin@^1.6.4:
   version "1.7.0"
   resolved "http://192.168.0.47:4873/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz#65741384f6d8056f36e2255a8d67ffc20866f5c9"
@@ -14322,6 +14337,16 @@ q@^1.1.2, q@^1.5.1:
   resolved "http://192.168.0.47:4873/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
   integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
 
+qrcode@^1.5.3:
+  version "1.5.3"
+  resolved "https://mirrors.cloud.tencent.com/npm/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170"
+  integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==
+  dependencies:
+    dijkstrajs "^1.0.1"
+    encode-utf8 "^1.0.3"
+    pngjs "^5.0.0"
+    yargs "^15.3.1"
+
 qs@6.11.0:
   version "6.11.0"
   resolved "http://192.168.0.47:4873/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
@@ -17980,6 +18005,14 @@ yargs-parser@^13.1.2:
     camelcase "^5.0.0"
     decamelize "^1.2.0"
 
+yargs-parser@^18.1.2:
+  version "18.1.3"
+  resolved "https://mirrors.cloud.tencent.com/npm/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
+  integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
+  dependencies:
+    camelcase "^5.0.0"
+    decamelize "^1.2.0"
+
 yargs-parser@^20.2.2, yargs-parser@^20.2.3:
   version "20.2.9"
   resolved "http://192.168.0.47:4873/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
@@ -18034,6 +18067,23 @@ yargs@^13.3.2:
     y18n "^4.0.0"
     yargs-parser "^13.1.2"
 
+yargs@^15.3.1:
+  version "15.4.1"
+  resolved "https://mirrors.cloud.tencent.com/npm/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
+  integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
+  dependencies:
+    cliui "^6.0.0"
+    decamelize "^1.2.0"
+    find-up "^4.1.0"
+    get-caller-file "^2.0.1"
+    require-directory "^2.1.1"
+    require-main-filename "^2.0.0"
+    set-blocking "^2.0.0"
+    string-width "^4.2.0"
+    which-module "^2.0.0"
+    y18n "^4.0.0"
+    yargs-parser "^18.1.2"
+
 yargs@^16.0.0, yargs@^16.2.0:
   version "16.2.0"
   resolved "http://192.168.0.47:4873/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"