gemercheung 2 лет назад
Родитель
Сommit
10ae138520

Разница между файлами не показана из-за своего большого размера
+ 14 - 0
packages/qjkankan-editor/public/static/lib/krpano/js/tour copy.js


Разница между файлами не показана из-за своего большого размера
+ 6 - 8
packages/qjkankan-editor/public/static/lib/krpano/js/tour.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
packages/qjkankan-editor/public/static/template/skin/vtourskin copy.xml


Разница между файлами не показана из-за своего большого размера
+ 1432 - 1
packages/qjkankan-editor/public/static/template/skin/vtourskin.xml


+ 155 - 111
packages/qjkankan-editor/src/Store/index.js

@@ -1,28 +1,28 @@
-import Vue from 'vue'
-import Vuex from 'vuex'
+import Vue from "vue";
+import Vuex from "vuex";
 
-import browser from "@/utils/browser"
+import browser from "@/utils/browser";
 import { deepClone, isSameObject } from "@/utils/other.js";
-import modules from './modules/'
+import modules from "./modules/";
 
-Vue.use(Vuex)
+Vue.use(Vuex);
 
 const store = new Vuex.Store({
   state: {
-    userAvatar: '',
-    userNickName: '',
+    userAvatar: "",
+    userNickName: "",
 
-    info: '',
-    infoSnapshotAtSave: '',
-    showInfo: '',
-    hotspot: '', // 当前在新增或编辑的热点的信息
-    backupHotSpot: '',
-    initScene: '',
+    info: "",
+    infoSnapshotAtSave: "",
+    showInfo: "",
+    hotspot: "", // 当前在新增或编辑的热点的信息
+    backupHotSpot: "",
+    initScene: "",
     tablist: [],
     temptablist: [],
     vrlist: [],
     allVrlist: [],
-    activeItem: '',
+    activeItem: "",
     isEditing: false,
     isShow: false, // 是否正常显示编辑器页面。如果发现作品不属于当前用户,就不能正常显示。
 
@@ -33,195 +33,239 @@ const store = new Vuex.Store({
 
     // 编辑器-导航-场景导航中,拖拽时要用到
     editorNavDragInfo: {
-      type: '', // 'topologyGroupLevel1': 拓扑结构中一级分组;'topologyGroupLevel2': 拓扑结构中二级分组;'scene': 场景(全景图和三维场景)
+      type: "", // 'topologyGroupLevel1': 拓扑结构中一级分组;'topologyGroupLevel2': 拓扑结构中二级分组;'scene': 场景(全景图和三维场景)
       node: {},
-    }
+    },
   },
   getters: {
-    userAvatar: state => state.userAvatar,
-    userNickName: state => state.userNickName,
+    userAvatar: (state) => state.userAvatar,
+    userNickName: (state) => state.userNickName,
 
-    isEditing: state => state.isEditing,
-    info: state => state.info,
+    isEditing: (state) => state.isEditing,
+    info: (state) => state.info,
     catalogTopology: (state) => {
       if (!state.info || !state.info.catalogRoot || !state.info.catalogs) {
-        return
+        return;
       }
       //四层:root,level1(一级分类),level2(二级分类或直属于一级分类的场景), level3(场景)
-      let root = deepClone(state.info.catalogRoot)
+      let root = deepClone(state.info.catalogRoot);
       // 对于每个一级分类
       for (const itemLevel1 of root) {
         // 指定每个一级分类的下级
-        itemLevel1.childrenTemp = []
+        itemLevel1.childrenTemp = [];
         for (const itemLevel2Id of itemLevel1.children) {
           for (const catalogsItem of state.info.catalogs) {
             if (itemLevel2Id === catalogsItem.id) {
-              const itemLevel2 = deepClone(catalogsItem)
-              itemLevel2.parentId = itemLevel1.id // 看起来,vuex getter中的数据如果存在循环引用,在通过mutation转而再存储到vuex中时,会导致调用栈溢出,原因难道是vuex mutation在深拷贝时没有考虑循环引用的情况?所以这里不进行循环引用,只记录parent的id。
-              itemLevel2.children = []
-              itemLevel1.childrenTemp.push(itemLevel2)
+              const itemLevel2 = deepClone(catalogsItem);
+              itemLevel2.parentId = itemLevel1.id; // 看起来,vuex getter中的数据如果存在循环引用,在通过mutation转而再存储到vuex中时,会导致调用栈溢出,原因难道是vuex mutation在深拷贝时没有考虑循环引用的情况?所以这里不进行循环引用,只记录parent的id。
+              itemLevel2.children = [];
+              itemLevel1.childrenTemp.push(itemLevel2);
               // 对于每个三级元素
               for (const sceneItem of state.info.scenes) {
                 // 如果属于上述二级分类
                 if (itemLevel2.id === sceneItem.category /* 注意拼写!!! */) {
-                  const itemLevel3 = deepClone(sceneItem)
-                  itemLevel3.parentId = itemLevel2.id  // 看起来,vuex getter中的数据如果存在循环引用,在通过mutation转而再存储到vuex中时,会导致调用栈溢出,原因难道是vuex mutation在深拷贝时没有考虑循环引用的情况?所以这里不进行循环引用,只记录parent的id。
-                  itemLevel2.children.push(itemLevel3)
+                  const itemLevel3 = deepClone(sceneItem);
+                  itemLevel3.parentId = itemLevel2.id; // 看起来,vuex getter中的数据如果存在循环引用,在通过mutation转而再存储到vuex中时,会导致调用栈溢出,原因难道是vuex mutation在深拷贝时没有考虑循环引用的情况?所以这里不进行循环引用,只记录parent的id。
+                  itemLevel2.children.push(itemLevel3);
                 }
               }
               // 按weight排序
               itemLevel2.children.sort((a, b) => {
                 if (a.weight === undefined && b.weight === undefined) {
-                  return 0
+                  return 0;
                 } else if (a.weight !== undefined && b.weight === undefined) {
-                  return -1
+                  return -1;
                 } else if (a.weight === undefined && b.weight !== undefined) {
-                  return 1
+                  return 1;
                 } else {
-                  return a.weight - b.weight
+                  return a.weight - b.weight;
                 }
-              })
-              break
+              });
+              break;
             }
           }
         }
-        itemLevel1.children = itemLevel1.childrenTemp
-        delete itemLevel1.childrenTemp
+        itemLevel1.children = itemLevel1.childrenTemp;
+        delete itemLevel1.childrenTemp;
       }
-      return root
-    },
-    isInfoChangedSinceSave: state => {
-      return !isSameObject(state.info, state.infoSnapshotAtSave)
-    },
-    showInfo: state => state.showInfo,
-    hotspot: state => state.hotspot,
-    backupHotSpot: state => state.backupHotSpot,
-    initScene: state => state.initScene,
-    activeItem: state => state.activeItem,
-    vrlist: state => state.vrlist,
-    tablist: state => state.tablist,
-    temptablist: state => state.temptablist,
-    isShow: state => state.isShow,
-    allVrlist: state => state.allVrlist,
+      return root;
+    },
+    isInfoChangedSinceSave: (state) => {
+      return !isSameObject(state.info, state.infoSnapshotAtSave);
+    },
+    showInfo: (state) => state.showInfo,
+    hotspot: (state) => state.hotspot,
+    backupHotSpot: (state) => state.backupHotSpot,
+    initScene: (state) => state.initScene,
+    activeItem: (state) => state.activeItem,
+    vrlist: (state) => state.vrlist,
+    tablist: (state) => state.tablist,
+    temptablist: (state) => state.temptablist,
+    isShow: (state) => state.isShow,
+    allVrlist: (state) => state.allVrlist,
+
+    uploadStatusListAudio: (state) => state.uploadStatusListAudio,
+    uploadStatusListImage: (state) => state.uploadStatusListImage,
+    uploadStatusListPano: (state) => state.uploadStatusListPano,
+    uploadStatusListVideo: (state) => state.uploadStatusListVideo,
 
-    uploadStatusListAudio: state => state.uploadStatusListAudio,
-    uploadStatusListImage: state => state.uploadStatusListImage,
-    uploadStatusListPano: state => state.uploadStatusListPano,
-    uploadStatusListVideo: state => state.uploadStatusListVideo,
+    editorNavDragInfo: (state) => state.editorNavDragInfo,
 
-    editorNavDragInfo: state => state.editorNavDragInfo,
+    // 1.3.0 新增层级后所有热点类型不同汇总显示的ICON
+    hotspotIcon: (state) => {
+      const category =
+        state.hotspot && state.hotspot.hotspotIconType
+          ? state.hotspot.hotspotIconType
+          : "";
+      switch (category) {
+        case "system_icon":
+          return {
+            img: state.hotspot.img,
+            type: "system_icon",
+          };
+        case "custom_image":
+          return {
+            ...state.hotspot.customIconInfo,
+            type: "custom_image",
+          };
+        case "serial_frame":
+          return {
+            ...state.hotspot.serialFrameInfo,
+            img: state.hotspot.serialFrameInfo.url,
+            type: "serial_frame",
+          };
+        case "personalized_tag":
+          return {
+            ...state.hotspot.personalizedTagInfo,
+            img: "",
+            type: "personalized_tag",
+          };
+        default:
+          return {
+            img: "",
+          };
+      }
+    },
   },
   mutations: {
     SetUserAvatar(state, avatar) {
-      if (typeof avatar === 'string') {
-        state.userAvatar = avatar
+      if (typeof avatar === "string") {
+        state.userAvatar = avatar;
       }
     },
     SetUserNickName(state, nickName) {
-      if (typeof nickName === 'string') {
-        state.userNickName = nickName
+      if (typeof nickName === "string") {
+        state.userNickName = nickName;
       }
     },
 
     SetTabList(state, list) {
-      state.tablist = list
+      state.tablist = list;
     },
     SetTempTabList(state, list) {
-      state.temptablist = list
+      state.temptablist = list;
     },
     SetVrList(state, list) {
-      state.vrlist = list
+      state.vrlist = list;
     },
     UpdateIsShowState(state, isShow) {
-      state.isShow = isShow
+      state.isShow = isShow;
     },
     UpdateIsEditingState(state, isShow) {
-      state.isEditing = isShow
+      state.isEditing = isShow;
     },
     SetAllVrlist(state, list) {
-      state.allVrlist = list
+      state.allVrlist = list;
     },
     SetInitScene(state, scene) {
-      state.initScene = scene
+      state.initScene = scene;
     },
     SetActiveItem(state, scene) {
-      state.activeItem = scene
+      state.activeItem = scene;
     },
     SetShowInfo(state, data) {
-      state.showInfo = data
+      state.showInfo = data;
     },
     SetInfo(state, data) {
-      state.info = data
-      this.commit('scene/setMetaData', data)
+      state.info = data;
+      this.commit("scene/setMetaData", data);
     },
     TakeInfoSnapShotAtSave(state) {
-      state.infoSnapshotAtSave = deepClone(state.info)
+      state.infoSnapshotAtSave = deepClone(state.info);
     },
     SetHotspot(state, data) {
-      state.hotspot = data
-      this.commit("BackupHotSpot", browser.CloneObject(data))
+      state.hotspot = data;
+      this.commit("BackupHotSpot", browser.CloneObject(data));
     },
     BackupHotSpot(state, data) {
-      state.backupHotSpot = data
+      state.backupHotSpot = data;
     },
 
     setUploadStatusListImage(state, data) {
-      state.uploadStatusListImage = data
+      state.uploadStatusListImage = data;
     },
     setUploadStatusListPano(state, data) {
-      state.uploadStatusListPano = data
+      state.uploadStatusListPano = data;
     },
     setUploadStatusListAudio(state, data) {
-      state.uploadStatusListAudio = data
+      state.uploadStatusListAudio = data;
     },
     setUploadStatusListVideo(state, data) {
-      state.uploadStatusListVideo = data
+      state.uploadStatusListVideo = data;
     },
     clearUploadStatusLists(state) {
-      state.uploadStatusListImage = state.uploadStatusListImage.filter((item) => {
-        return item.status !== 'SUCCESS'
-      })
+      state.uploadStatusListImage = state.uploadStatusListImage.filter(
+        (item) => {
+          return item.status !== "SUCCESS";
+        }
+      );
       state.uploadStatusListPano = state.uploadStatusListPano.filter((item) => {
-        return item.status !== 'SUCCESS'
-      })
-      state.uploadStatusListAudio = state.uploadStatusListAudio.filter((item) => {
-        return item.status !== 'SUCCESS'
-      })
-      state.uploadStatusListVideo = state.uploadStatusListVideo.filter((item) => {
-        return item.status !== 'SUCCESS'
-      })
-    },
-    
+        return item.status !== "SUCCESS";
+      });
+      state.uploadStatusListAudio = state.uploadStatusListAudio.filter(
+        (item) => {
+          return item.status !== "SUCCESS";
+        }
+      );
+      state.uploadStatusListVideo = state.uploadStatusListVideo.filter(
+        (item) => {
+          return item.status !== "SUCCESS";
+        }
+      );
+    },
+
     setEditorNavDragType(state, data) {
-      if (!['topologyGroupLevel1', 'topologyGroupLevel2', 'scene'].includes(data)) {
-        throw("拖拽类型必须是'topologyGroupLevel1', 'topologyGroupLevel2', 'scene'之一!")
+      if (
+        !["topologyGroupLevel1", "topologyGroupLevel2", "scene"].includes(data)
+      ) {
+        throw "拖拽类型必须是'topologyGroupLevel1', 'topologyGroupLevel2', 'scene'之一!";
       }
-      state.editorNavDragInfo.type = data
+      state.editorNavDragInfo.type = data;
     },
     setEditorNavDragNode(state, data) {
-      state.editorNavDragInfo.node = data
+      state.editorNavDragInfo.node = data;
     },
     clearEditorNavDragInfo(state) {
-      state.editorNavDragInfo.type = ''
-      state.editorNavDragInfo.node = {}
-    }
+      state.editorNavDragInfo.type = "";
+      state.editorNavDragInfo.node = {};
+    },
   },
   actions: {
     refreshUserInfo(context) {
       try {
-        const userInfo = JSON.parse(localStorage.getItem('info'))
-        context.commit('SetUserAvatar', userInfo.head)
-        context.commit('SetUserNickName', userInfo.nickName)
+        const userInfo = JSON.parse(localStorage.getItem("info"));
+        context.commit("SetUserAvatar", userInfo.head);
+        context.commit("SetUserNickName", userInfo.nickName);
       } catch (error) {
-        console.log('从storage没有读取到有意义的info,store里用户信息置空。')
-        context.commit('SetUserAvatar', '')
-        context.commit('SetUserNickName', '')
+        console.log("从storage没有读取到有意义的info,store里用户信息置空。");
+        context.commit("SetUserAvatar", "");
+        context.commit("SetUserNickName", "");
       }
     },
   },
   modules: {
-    ...modules
-  }
-})
+    ...modules,
+  },
+});
 
-export default store
+export default store;

+ 2 - 0
packages/qjkankan-editor/src/core/utils.js

@@ -85,6 +85,7 @@ export default class Utils {
     krpano.call("screentosphere(curscreen_x, curscreen_y, curscreen_ath, curscreen_atv);");
     let ath = krpano.get("curscreen_ath");
     let atv = krpano.get("curscreen_atv");
+
     krpano.call(`addImgTextHotSpot(
       ${param.img},
       ${param.name},
@@ -201,6 +202,7 @@ export default class Utils {
     if (typeof someData == 'string') {
       mysd = JSON.parse(someData)
     }
+  
     mysd.hotspots.forEach(item => {
       this.addhotspot(krpano, item, type)
     });

+ 100 - 89
packages/qjkankan-editor/src/directives/vTooltipInEditor.js

@@ -1,104 +1,115 @@
-import Vue from 'vue'
-import {computePosition, offset, flip, shift, arrow} from '@floating-ui/dom';
+import Vue from "vue";
+import { computePosition, offset, flip, shift, arrow } from "@floating-ui/dom";
 
-let tooltipNode = null
-let intervalId = null
+let tooltipNode = null;
+let intervalId = null;
 
 function removeTooltip() {
   try {
-    clearInterval(intervalId)
-    document.body.removeChild(tooltipNode)
-  } catch(e) {
-    console.log('尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:', e);
+    intervalId && clearInterval(intervalId);
+    tooltipNode && document.body.removeChild(tooltipNode);
+  } catch (e) {
+    // console.log(
+    //   "尝试从DOM上移除tooltip元素失败,通常是因为已经在其他回调中被移除了,不需处理:",
+    //   e
+    // );
   }
 }
 
-Vue.directive('tooltip', {
+Vue.directive("tooltip", {
   bind: function (el, binding) {
     if (!binding.value) {
-      return
+      return;
     }
-    el.addEventListener('mouseenter', function(e) {
-      tooltipNode = document.createElement('div')
-      tooltipNode.style.position = 'fixed'
-      tooltipNode.style.zIndex = 100
-      tooltipNode.style.backgroundColor = '#191A1C'
-      tooltipNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
-      tooltipNode.style.borderRadius = '3px'
-      tooltipNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
-      tooltipNode.style.boxShadow = '0px 2px 12px 0px rgba(0, 0, 0, 0.06)'
-      tooltipNode.style.padding = '8px 8px'
-      tooltipNode.style.fontSize = '12px'
-      tooltipNode.style.cursor = 'default'
-      tooltipNode.style.pointerEvents = 'none'
-      tooltipNode.style.wordBreak = 'keep-all'
-      tooltipNode.style.whiteSpace = 'pre'
-      tooltipNode.style.fontSize = '12px'
-      tooltipNode.style.lineHeight = '17px'
-      tooltipNode.style.color = 'rgba(255, 255, 255, 0.6)'
-      tooltipNode.innerText = binding.value
+    el.addEventListener(
+      "mouseenter",
+      function (e) {
+        tooltipNode = document.createElement("div");
+        tooltipNode.style.position = "fixed";
+        tooltipNode.style.zIndex = 100;
+        tooltipNode.style.backgroundColor = "#191A1C";
+        tooltipNode.style.border = "1px solid rgba(151, 151, 151, 0.2)";
+        tooltipNode.style.borderRadius = "3px";
+        tooltipNode.style.border = "1px solid rgba(151, 151, 151, 0.2)";
+        tooltipNode.style.boxShadow = "0px 2px 12px 0px rgba(0, 0, 0, 0.06)";
+        tooltipNode.style.padding = "8px 8px";
+        tooltipNode.style.fontSize = "12px";
+        tooltipNode.style.cursor = "default";
+        tooltipNode.style.pointerEvents = "none";
+        tooltipNode.style.wordBreak = "keep-all";
+        tooltipNode.style.whiteSpace = "pre";
+        tooltipNode.style.fontSize = "12px";
+        tooltipNode.style.lineHeight = "17px";
+        tooltipNode.style.color = "rgba(255, 255, 255, 0.6)";
+        tooltipNode.innerText = binding.value;
 
-      const arrowNode = document.createElement('div')
-      arrowNode.style.position = 'absolute'
-      arrowNode.style.backgroundColor = 'inherit'
-      arrowNode.style.boxSizing = 'border-box'
-      arrowNode.style.width = '12px'
-      arrowNode.style.height = '12px'
-      arrowNode.style.border = '1px solid transparent'
-      arrowNode.style.borderRight = 'inherit'
-      arrowNode.style.borderBottom = 'inherit'
-      arrowNode.style.transform = 'rotate(45deg)'
-      
-      tooltipNode.appendChild(arrowNode)
-      document.body.appendChild(tooltipNode)
+        const arrowNode = document.createElement("div");
+        arrowNode.style.position = "absolute";
+        arrowNode.style.backgroundColor = "inherit";
+        arrowNode.style.boxSizing = "border-box";
+        arrowNode.style.width = "12px";
+        arrowNode.style.height = "12px";
+        arrowNode.style.border = "1px solid transparent";
+        arrowNode.style.borderRight = "inherit";
+        arrowNode.style.borderBottom = "inherit";
+        arrowNode.style.transform = "rotate(45deg)";
 
-      computePosition(el, tooltipNode, {
-        placement: 'top',
-        middleware: [
-          offset(13),
-          flip(),
-          shift({padding: 12}),
-          arrow({
-            element: arrowNode,
-            padding: 3,
-          }),
-        ],
-      }).then(({x, y, placement, middlewareData}) => {
-        Object.assign(tooltipNode.style, {
-          left: `${x}px`,
-          top: `${y}px`,
-        });
+        tooltipNode.appendChild(arrowNode);
+        document.body.appendChild(tooltipNode);
 
-        const {x: arrowX, y: arrowY} = middlewareData.arrow;
-        const staticSide = {
-          top: 'bottom',
-          right: 'left',
-          bottom: 'top',
-          left: 'right',
-        }[placement.split('-')[0]];
-       
-        Object.assign(arrowNode.style, {
-          left: arrowX != null ? `${arrowX}px` : '',
-          [staticSide]: '-6px',
-        });
-      }).catch((err) => {
-        console.log('计算tooltip位置时出现异常,可能因为目标元素已经被卸载。')
-      });
+        computePosition(el, tooltipNode, {
+          placement: "top",
+          middleware: [
+            offset(13),
+            flip(),
+            shift({ padding: 12 }),
+            arrow({
+              element: arrowNode,
+              padding: 3,
+            }),
+          ],
+        })
+          .then(({ x, y, placement, middlewareData }) => {
+            Object.assign(tooltipNode.style, {
+              left: `${x}px`,
+              top: `${y}px`,
+            });
 
-      intervalId = setInterval(() => {
-        if (!document.contains(el)) {
-          removeTooltip()
-        }
-      }, 300);
-    }, {
-      passive: false,
-    })
-    el.addEventListener('mouseleave', removeTooltip)
-    el.addEventListener('mousedown', removeTooltip)
-    el.addEventListener('keydown', removeTooltip)
-    el.addEventListener('scroll', removeTooltip)
-    el.addEventListener('dragstart', removeTooltip)
-    el.addEventListener('dragstart', removeTooltip)
-    el.addEventListener('dragleave', removeTooltip)
+            const { x: arrowX, y: arrowY } = middlewareData.arrow;
+            const staticSide = {
+              top: "bottom",
+              right: "left",
+              bottom: "top",
+              left: "right",
+            }[placement.split("-")[0]];
+
+            Object.assign(arrowNode.style, {
+              left: arrowX != null ? `${arrowX}px` : "",
+              [staticSide]: "-6px",
+            });
+          })
+          .catch((err) => {
+            console.log(
+              "计算tooltip位置时出现异常,可能因为目标元素已经被卸载。"
+            );
+          });
+
+        intervalId = setInterval(() => {
+          if (!document.contains(el)) {
+            removeTooltip();
+          }
+        }, 300);
+      },
+      {
+        passive: false,
+      }
+    );
+    el.addEventListener("mouseleave", removeTooltip);
+    el.addEventListener("mousedown", removeTooltip);
+    el.addEventListener("keydown", removeTooltip);
+    el.addEventListener("scroll", removeTooltip);
+    el.addEventListener("dragstart", removeTooltip);
+    el.addEventListener("dragstart", removeTooltip);
+    el.addEventListener("dragleave", removeTooltip);
   },
-})
+});

+ 78 - 73
packages/qjkankan-editor/src/framework/core/index.vue

@@ -3,9 +3,11 @@
     <div class="none-center" v-show="!activeItem">请先上传或添加场景素材</div>
 
     <div v-show="activeItem" id="pano"></div>
-    <template v-if="showSnapshot&&activeItem">
+    <template v-if="showSnapshot && activeItem">
       <snapshot :showFlash="showFlash"></snapshot>
-      <button class="ui-button submit" @click="onClick">将当前视角设为初始画面</button>
+      <button class="ui-button submit" @click="onClick">
+        将当前视角设为初始画面
+      </button>
     </template>
   </div>
 </template>
@@ -13,7 +15,7 @@
 <script>
 import * as krfn from "@/core/index.js";
 import { uploadCover } from "@/api";
-import { $waiting } from '@/components/shared/loading'
+import { $waiting } from "@/components/shared/loading";
 import { mapGetters } from "vuex";
 
 import Snapshot from "@/components/Snapshot";
@@ -24,9 +26,9 @@ export default {
   components: { Snapshot },
   data() {
     return {
-      activeItem:'',
-      showFlash:false,
-      someData:''
+      activeItem: "",
+      showFlash: false,
+      someData: "",
     };
   },
   computed: {
@@ -41,109 +43,112 @@ export default {
     },
   },
   methods: {
-    updateInfo(){
-      let iidx = this.info.scenes.findIndex(item=>this.activeItem.sceneCode == item.sceneCode)
-      if (iidx>-1) {
+    updateInfo() {
+      let iidx = this.info.scenes.findIndex(
+        (item) => this.activeItem.sceneCode == item.sceneCode
+      );
+      if (iidx > -1) {
         this.info.scenes[iidx] = {
-          ...this.activeItem
-        }
+          ...this.activeItem,
+        };
       }
       this.$store.commit("SetInfo", this.info);
     },
     onClick() {
-      this.$bus.emit('toggleFlash',true)
+      this.$bus.emit("toggleFlash", true);
       let canvas = $("#krpanoSWFObject canvas")[0];
-      let krpano = document.getElementById('krpanoSWFObject');
+      let krpano = document.getElementById("krpanoSWFObject");
       let data = __krfn.utils.setInitView(krpano, canvas);
 
       console.log(data.url);
 
-      uploadCover(
-        { file: data.url, filename: "initCover.jpg" },
-        res => {
-          if (res.code==0) {
-            this.activeItem.icon = res.data
-            this.activeItem.initVisual= {
-              hlookat: data.hlookat,
-              vlookat: data.vlookat
-            }
-            this.$bus.emit('toggleFlash',false)
-            this.$bus.emit("initView", res.data);
-            this.updateInfo()
-            this.$msg.success(this.$i18n.t("gather.setting_success"))
-            this.$store.commit("SetInfo", this.info);
-          }
-        });
+      uploadCover({ file: data.url, filename: "initCover.jpg" }, (res) => {
+        if (res.code == 0) {
+          this.activeItem.icon = res.data;
+          this.activeItem.initVisual = {
+            hlookat: data.hlookat,
+            vlookat: data.vlookat,
+          };
+          this.$bus.emit("toggleFlash", false);
+          this.$bus.emit("initView", res.data);
+          this.updateInfo();
+          this.$msg.success(this.$i18n.t("gather.setting_success"));
+          this.$store.commit("SetInfo", this.info);
+        }
+      });
     },
     addhotspot(param) {
-      let krpano = document.getElementById('krpanoSWFObject');
+      let krpano = document.getElementById("krpanoSWFObject");
       __krfn.utils.addhotspot(krpano, param, true);
-    }
-    
+    },
   },
-  watch:{
-    '$route.name':function(newVal){
-        let krpano = document.getElementById('krpanoSWFObject');
-        __krfn.utils.toggleHotspot(krpano,newVal!='screen');
+  watch: {
+    "$route.name": function (newVal) {
+      let krpano = document.getElementById("krpanoSWFObject");
+      __krfn.utils.toggleHotspot(krpano, newVal != "screen");
     },
-    activeItem:{
+    activeItem: {
       handler(newVal) {
         if (newVal) {
-          this.$nextTick(()=>{
+          this.$nextTick(() => {
             this.$bus.emit("initView", newVal.icon);
-          })
-        }
-        $('#pano').empty();
-        window.vrInitFn = ()=>{
-            $waiting.hide()
-              var krpano = document.getElementById('krpanoSWFObject');
-            __krfn.utils.initHotspot(krpano,newVal&&newVal.someData,true);
-            __krfn.utils.toggleHotspot(krpano,this.$route.name!='screen');
+          });
         }
-        window.vrViewFn = ()=>{
+        $("#pano").empty();
+        window.vrInitFn = () => {
+          $waiting.hide();
+          var krpano = document.getElementById("krpanoSWFObject");
+          __krfn.utils.initHotspot(krpano, newVal && newVal.someData, true);
+          __krfn.utils.toggleHotspot(krpano, this.$route.name != "screen");
+        };
+        window.vrViewFn = () => {
           try {
-            let tmp = newVal.initVisual
-            var krpano = document.getElementById('krpanoSWFObject');
-            krpano.set('view.vlookat',tmp.vlookat);
-            krpano.set('view.hlookat',tmp.hlookat);
+            let tmp = newVal.initVisual;
+            var krpano = document.getElementById("krpanoSWFObject");
+            krpano.set("view.vlookat", tmp.vlookat);
+            krpano.set("view.hlookat", tmp.hlookat);
           } catch (error) {
-            error
+            error;
           }
-        }
-               
+        };
+
         var settings = {
-          'events[skin_events].onxmlcomplete':'js(window.vrViewFn());',
-          'events[skin_events].onloadcomplete': 'js(window.vrInitFn());'
+          "events[skin_events].onxmlcomplete": "js(window.vrViewFn());",
+          "events[skin_events].onloadcomplete": "js(window.vrInitFn());",
         };
-        if(newVal){
-            removepano('#pano')
-            $waiting.show()
-            embedpano({
+        if (newVal) {
+          removepano("#pano");
+          $waiting.show();
+  
+          embedpano({
             // http://ossxiaoan.4dage.com/720yun_fd_manage/fd720_Va0LrkXW3/vtour/tour.xml
             // xml: "%HTMLPATH%/static/template/tour.xml",
             xml: `${this.$cdn}/720yun_fd_manage/${newVal.sceneCode}/vtour/tour.xml`,
-            swf: "%HTMLPATH%/static/template/tour.swf",
+            // swf: "%HTMLPATH%/static/template/tour.swf",
             target: "pano",
             html5: "auto",
             mobilescale: 1,
-            vars:settings,
+            vars: settings,
             webglsettings: { preserveDrawingBuffer: true },
             passQueryParameters: true,
+            onerror: (error) => {
+              console.error("error", error);
+            },
           });
           // $waiting.hide()
         }
       },
-      immediate: true
-    }
+      immediate: true,
+    },
   },
   mounted() {
     window.__krfn = __krfn;
-   
-    this.$bus.on('currentPcode',data=>{
-      this.activeItem = data
-    })
-    
-    this.$bus.on("addhotspot", data => {
+
+    this.$bus.on("currentPcode", (data) => {
+      this.activeItem = data;
+    });
+
+    this.$bus.on("addhotspot", (data) => {
       this.addhotspot(data);
     });
   },
@@ -156,11 +161,11 @@ export default {
   width: 100%;
   position: relative;
   height: 100%;
-  .none-center{
+  .none-center {
     position: absolute;
     top: 50%;
     left: 50%;
-    transform: translate(-50%,-50%);
+    transform: translate(-50%, -50%);
   }
   #pano {
     width: 100%;
@@ -182,4 +187,4 @@ export default {
     z-index: 99;
   }
 }
-</style>
+</style>

+ 114 - 86
packages/qjkankan-editor/src/framework/play/pano/index.vue

@@ -1,25 +1,44 @@
 <template>
-  <div class="panocon">
-    <div v-show="currentScene.type !== '4dkk'" id="pano">
-    </div>
+  <div class="panocon" :class="[routerName]">
+    <div v-show="currentScene.type !== '4dkk'" id="pano"></div>
     <iframe
       id="iframe-4dkk"
       width=""
       v-if="currentScene.type === '4dkk'"
-      :src="`${locationOrigin}/sp${currentScene.version === 'V3' ? 'c' : currentScene.version === 'V4' ? 'g' : ''}.html?m=${currentScene.sceneCode}&lang=${lang}`"
+      :src="`${locationOrigin}/sp${
+        currentScene.version === 'V3'
+          ? 'c'
+          : currentScene.version === 'V4'
+          ? 'g'
+          : ''
+      }.html?m=${currentScene.sceneCode}&lang=${lang}`"
       frameborder="0"
     />
 
-    <div class="showexplanation" v-if="showExplanation&&currentScene.explanation && currentScene.explanation.audioId">
-      <img :src="require(`@/assets/images/commentary@2x.png`)" alt="">
+    <div
+      class="showexplanation"
+      v-if="
+        showExplanation &&
+        currentScene.explanation &&
+        currentScene.explanation.audioId
+      "
+    >
+      <img :src="require(`@/assets/images/commentary@2x.png`)" alt="" />
     </div>
     <list></list>
 
-    <template v-if="showSnapshot && currentScene&&currentScene.type !=='4dkk'">
+    <template
+      v-if="showSnapshot && currentScene && currentScene.type !== '4dkk'"
+    >
       <snapshot :showFlash="showFlash"></snapshot>
-      <button class="ui-button submit set-initial-view" :class="{disable: currentScene.type === '4dkk',}" @click="onClick">{{$i18n.t('screen.setting_screen')}}</button>
+      <button
+        class="ui-button submit set-initial-view"
+        :class="{ disable: currentScene.type === '4dkk' }"
+        @click="onClick"
+      >
+        {{ $i18n.t("screen.setting_screen") }}
+      </button>
     </template>
-
   </div>
 </template>
 
@@ -29,11 +48,8 @@ import { mapGetters } from "vuex";
 import * as krfn from "@/core/index.js";
 import { $waiting } from "@/components/shared/loading";
 import Snapshot from "@/components/Snapshot";
-import {
-  uploadCover,
-  searchInAll3DScenes,
-} from "@/api";
-import config from '@/config'
+import { uploadCover, searchInAll3DScenes } from "@/api";
+import config from "@/config";
 
 let __krfn = krfn.default;
 
@@ -43,11 +59,14 @@ export default {
     return {
       showFlash: false,
       inter: null,
-      lang: config.lang || 'zh',
+      lang: config.lang || "zh",
       locationOrigin: process.env.VUE_APP_PROXY_URL_ROOT,
-    }
+    };
   },
   computed: {
+    routerName() {
+      return this.$route.name;
+    },
     ...mapGetters({
       currentScene: "scene/currentScene",
       info: "info",
@@ -62,34 +81,45 @@ export default {
     },
   },
   watch: {
-    '$route.name': function (newVal) {
-      __krfn.utils.toggleHotspot(this.$getKrpano(), newVal == 'hotspot');
+    "$route.name": function (newVal) {
+      __krfn.utils.toggleHotspot(this.$getKrpano(), newVal == "hotspot");
     },
     currentScene(newVal) {
       if (newVal) {
         this.$nextTick(() => {
           this.$bus.emit("initView", newVal.icon);
-        })
+        });
       }
-      if (newVal.type == '4dkk') {
+      if (newVal.type == "4dkk") {
         $("#pano").empty();
-        if (!newVal.version) { // v1.3之前在作品中新增的三维场景,没有version这个值,需要查询。
-          searchInAll3DScenes({
-            searchKey: newVal.sceneTitle,
-          }, (res) => {
-            const originItem = res.data.list.find((item) => {
-              return item.num === newVal.sceneCode
-            })
-            newVal.version = originItem.buildType
-          })
+        if (!newVal.version) {
+          // v1.3之前在作品中新增的三维场景,没有version这个值,需要查询。
+          searchInAll3DScenes(
+            {
+              searchKey: newVal.sceneTitle,
+            },
+            (res) => {
+              const originItem = res.data.list.find((item) => {
+                return item.num === newVal.sceneCode;
+              });
+              newVal.version = originItem.buildType;
+            }
+          );
         }
-        return
+        return;
       } else {
         $("#pano").empty();
         window.vrInitFn = () => {
-          $waiting.hide()
-          __krfn.utils.initHotspot(this.$getKrpano(), newVal && newVal.someData, true);
-          __krfn.utils.toggleHotspot(this.$getKrpano(), this.$route.name == "hotspot");
+          $waiting.hide();
+          __krfn.utils.initHotspot(
+            this.$getKrpano(),
+            newVal && newVal.someData,
+            true
+          );
+          __krfn.utils.toggleHotspot(
+            this.$getKrpano(),
+            this.$route.name == "hotspot"
+          );
         };
         window.vrViewFn = () => {
           try {
@@ -124,72 +154,71 @@ export default {
         }
       }
 
-      var settings = {
-        "events[skin_events].onxmlcomplete": "js(window.vrViewFn());",
-        "events[skin_events].onloadcomplete": "js(window.vrInitFn());",
-      };
+      // var settings = {
+      //   "events[skin_events].onxmlcomplete": "js(window.vrViewFn());",
+      //   "events[skin_events].onloadcomplete": "js(window.vrInitFn());",
+      // };
 
-      if (newVal) {
-        removepano("#pano");
-        $waiting.show();
-        embedpano({
-          // http://ossxiaoan.4dage.com/720yun_fd_manage/fd720_Va0LrkXW3/vtour/tour.xml
-          // xml: "%HTMLPATH%/static/template/tour.xml",
-          xml: `${this.$cdn}/720yun_fd_manage/${newVal.sceneCode}/vtour/tour.xml`,
-          swf: "%HTMLPATH%/static/template/tour.swf",
-          target: "pano",
-          html5: "auto",
-          mobilescale: 1,
-          vars: settings,
-          webglsettings: { preserveDrawingBuffer: true },
-          passQueryParameters: true,
-        });
-      }
+      // if (newVal) {
+      //   removepano("#pano");
+      //   $waiting.show();
+      //   embedpano({
+      //     // http://ossxiaoan.4dage.com/720yun_fd_manage/fd720_Va0LrkXW3/vtour/tour.xml
+      //     // xml: "%HTMLPATH%/static/template/tour.xml",
+      //     xml: `${this.$cdn}/720yun_fd_manage/${newVal.sceneCode}/vtour/tour.xml`,
+      //     swf: "%HTMLPATH%/static/template/tour.swf",
+      //     target: "pano",
+      //     html5: "auto",
+      //     mobilescale: 1,
+      //     vars: settings,
+      //     webglsettings: { preserveDrawingBuffer: true },
+      //     passQueryParameters: true,
+      //   });
+      // }
     },
     isConfirmingPosi(newVal) {
-      this.inter && clearInterval(this.inter)
-      this.inter = null
-      console.log(newVal,'isConfirmingPosiisConfirmingPosi');
+      this.inter && clearInterval(this.inter);
+      this.inter = null;
+      console.log(newVal, "isConfirmingPosiisConfirmingPosi");
       if (newVal) {
         this.inter = setInterval(() => {
-          __krfn.utils.getCurrentMousePosition(this.$getKrpano(), newVal)
+          __krfn.utils.getCurrentMousePosition(this.$getKrpano(), newVal);
         }, 20);
       } else {
-        this.$bus.emit('resethotspotTitle', '')
+        this.$bus.emit("resethotspotTitle", "");
       }
-    }
-
+    },
   },
   methods: {
     updateInfo() {
-      let iidx = this.info.scenes.findIndex(item => this.currentScene.sceneCode == item.sceneCode)
+      let iidx = this.info.scenes.findIndex(
+        (item) => this.currentScene.sceneCode == item.sceneCode
+      );
       if (iidx > -1) {
         this.info.scenes[iidx] = {
-          ...this.currentScene
-        }
+          ...this.currentScene,
+        };
       }
       this.$store.commit("SetInfo", this.info);
     },
     onClick() {
-      this.$bus.emit('toggleFlash', true)
+      this.$bus.emit("toggleFlash", true);
       let canvas = $("#krpanoSWFObject canvas")[0];
       let data = __krfn.utils.setInitView(this.$getKrpano(), canvas);
-      uploadCover(
-        { file: data.url, filename: "initCover.jpg" },
-        res => {
-          if (res.code == 0) {
-            this.currentScene.icon = res.data
-            this.currentScene.initVisual = {
-              hlookat: data.hlookat,
-              vlookat: data.vlookat
-            }
-            this.$bus.emit('toggleFlash', false)
-            this.$bus.emit("initView", res.data);
-            this.updateInfo()
-            this.$msg.success(this.$i18n.t("gather.setting_success"))
-            this.$store.commit("SetInfo", this.info);
-          }
-        });
+      uploadCover({ file: data.url, filename: "initCover.jpg" }, (res) => {
+        if (res.code == 0) {
+          this.currentScene.icon = res.data;
+          this.currentScene.initVisual = {
+            hlookat: data.hlookat,
+            vlookat: data.vlookat,
+          };
+          this.$bus.emit("toggleFlash", false);
+          this.$bus.emit("initView", res.data);
+          this.updateInfo();
+          this.$msg.success(this.$i18n.t("gather.setting_success"));
+          this.$store.commit("SetInfo", this.info);
+        }
+      });
     },
     addhotspot(param) {
       __krfn.utils.addhotspot(this.$getKrpano(), param, true);
@@ -199,7 +228,8 @@ export default {
   mounted() {
     window.__krfn = __krfn;
 
-    this.$bus.on("addhotspot", data => {
+    this.$bus.on("addhotspot", (data) => {
+      // debugger
       this.addhotspot(data);
     });
 
@@ -207,7 +237,7 @@ export default {
       if (this.isConfirmingPosi) {
         this.$store.commit("tags/setIsConfirmingPosi", false);
       }
-    })
+    });
   },
 };
 </script>
@@ -218,7 +248,6 @@ export default {
   height: 100%;
   position: relative;
   overflow: hidden;
-
   #pano {
     width: 100%;
     height: 100%;
@@ -228,7 +257,7 @@ export default {
     width: 100%;
     height: 100%;
   }
-  
+
   .showexplanation {
     position: absolute;
     top: 20px;
@@ -241,7 +270,7 @@ export default {
     border: 1px solid rgba(255, 255, 255, 0.2);
     backdrop-filter: blur(6px);
 
-    >img {
+    > img {
       width: 100%;
       height: 100%;
     }
@@ -255,6 +284,5 @@ export default {
     transform: translateX(-50%);
     z-index: 99;
   }
-
 }
 </style>

+ 29 - 1
packages/qjkankan-editor/src/views/hotspot/EditPanel.vue

@@ -239,10 +239,37 @@ export default {
     };
   },
   watch: {
+    hotspot: {
+      handler(val) {
+        console.error("this.hotspot", val);
+      },
+      deep: true,
+    },
+    hotspotIcon: {
+      handler(val) {
+        console.error("this.hotspotIcon", val);
+        val.img.length > 0 &&
+          this.$getKrpano().set(`hotspot[${this.hotspot.name}].url`, val.img);
+      },
+      deep: true,
+    },
+    // "hotspot.img": function () {
+    //   console.log("this.hotspot.img", this.hotspot.img);
+    //   this.$getKrpano().set(
+    //     `hotspot[${this.hotspot.name}].url`,
+    //     this.hotspot.img
+    //   );
+    // },
+    "hotspot.titlePosition": function (val) {
+      console.log("111", val);
+      if (val === "bottom") {
+        this.$getKrpano().set("layer[tooltip_" + this.hotspot.name + "].css");
+      }
+    },
     "hotspot.hotspotTitle": function () {
       this.$getKrpano().set(
         "layer[tooltip_" + this.hotspot.name + "].html",
-        this.hotspot.hotspotTitle
+        `<span style="color:white">${this.hotspot.hotspotTitle}</span>`
       );
     },
     // 'hotspot.visible': function () {
@@ -289,6 +316,7 @@ export default {
     ...mapGetters({
       hotspot: "hotspot",
       backupHotSpot: "backupHotSpot",
+      hotspotIcon: "hotspotIcon",
     }),
     iconTypeComponent() {
       let tmp = this.hotspot.hotspotIconType;

+ 234 - 180
packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue

@@ -1,8 +1,11 @@
 <template>
   <div class="hot-spot-list" app-border dir-left>
     <div class="title">
-      {{$i18n.t('hotspot.add_hotspot')}}
-      <i class="iconfont icon-material_prompt tool-tip-for-editor" v-tooltip="$i18n.t('hotspot.hotspot_tips')" />
+      {{ $i18n.t("hotspot.add_hotspot") }}
+      <i
+        class="iconfont icon-material_prompt tool-tip-for-editor"
+        v-tooltip="$i18n.t('hotspot.hotspot_tips')"
+      />
     </div>
 
     <template v-if="currentScene.type !== '4dkk'">
@@ -11,60 +14,80 @@
           class="hotspot-type-item"
           v-for="(item, index) in hotspotTypeList"
           :key="index"
-          @click="open({
-            isAdd: true,
-            hotspotType: item.id,
-            idxInSystemIconList: item.idxInSystemIconList
-          })"
+          @click="
+            open({
+              isAdd: true,
+              hotspotType: item.id,
+              idxInSystemIconList: item.idxInSystemIconList,
+            })
+          "
         >
-          <img class="icon" :src="item.icon" alt="" draggable="false">
-          <div class="type-name">{{item.name}}</div>
+          <img class="icon" :src="item.icon" alt="" draggable="false" />
+          <div class="type-name">{{ item.name }}</div>
           <img
             v-if="item.isExperience"
             class="exp-tag"
             src="@/assets/img/experience.png"
             alt=""
             draggable="false"
-          >
+          />
         </li>
       </ul>
 
-      <div class="total-count">{{$i18n.t('hotspot.current_hotspots')}}
+      <div class="total-count">
+        {{ $i18n.t("hotspot.current_hotspots") }}
         <span class="number">({{ someData.hotspots.length }})</span>
       </div>
       <div class="hots">
         <ul v-if="someData.hotspots.length > 0">
-          <li v-for="(item, key) in someData.hotspots" :key="key" @click="open(item)">
-            <img class="hot-spot-thumb" :src="item.img" alt="">
-            <span class="hot-spot-title" v-title="item.hotspotTitle">{{ item.hotspotTitle }}</span>
+          <li
+            v-for="(item, key) in someData.hotspots"
+            :key="key"
+            @click="open(item)"
+          >
+            <img class="hot-spot-thumb" :src="item.img" alt="" />
+            <span class="hot-spot-title" v-title="item.hotspotTitle">{{
+              item.hotspotTitle
+            }}</span>
             <i
               class="iconfont icon-editor_list_delete icon-delete"
               v-tooltip="$i18n.t('hotspot.delete')"
               @click.stop="deleIndex = key"
             />
             <div class="deletion-confirm-wrap">
-              <div class="deletion-confirm" :class="deleIndex == key ? 'show' : 'hide'" v-clickoutside="clickoutside"
-                @click.stop="deleteHot(item)">
-                {{$i18n.t('hotspot.delete')}}
+              <div
+                class="deletion-confirm"
+                :class="deleIndex == key ? 'show' : 'hide'"
+                v-clickoutside="clickoutside"
+                @click.stop="deleteHot(item)"
+              >
+                {{ $i18n.t("hotspot.delete") }}
               </div>
             </div>
           </li>
         </ul>
         <div v-else class="empty-tip">
-          <img src="@/assets/images/default/empty_hotspot_list.png" alt="">
-          <div>{{$i18n.t('hotspot.no_hotspot')}}</div>
+          <img src="@/assets/images/default/empty_hotspot_list.png" alt="" />
+          <div>{{ $i18n.t("hotspot.no_hotspot") }}</div>
         </div>
       </div>
     </template>
 
     <div class="goto-4dkk-tip" v-if="currentScene.type === '4dkk'">
       <div class="img-wrap">
-        <img class="" src="@/assets/images/default/goto-4dage.png" alt="" draggable="false">
+        <img
+          class=""
+          src="@/assets/images/default/goto-4dage.png"
+          alt=""
+          draggable="false"
+        />
         <div class="tip-text">
-          {{$i18n.t('screen.goto_4dkk_edit_tips')}}
+          {{ $i18n.t("screen.goto_4dkk_edit_tips") }}
         </div>
       </div>
-      <button class="ui-button submit" @click="onClickGo4dkk">{{$i18n.t('navigation.go_scene_editor')}}</button>
+      <button class="ui-button submit" @click="onClickGo4dkk">
+        {{ $i18n.t("navigation.go_scene_editor") }}
+      </button>
     </div>
 
     <EditPanel
@@ -79,219 +102,238 @@
 </template>
 
 <script>
-import EditPanel from "./EditPanel"
-import { mapGetters } from "vuex"
-import browser from "@/utils/browser"
+import EditPanel from "./EditPanel";
+import { mapGetters } from "vuex";
+import browser from "@/utils/browser";
 import hotspotTypeList from "./hotspotTypeList.js";
 
 let mapFontSize = {
   12: 0.5,
   17: 1.5,
   20: 2,
-}
+};
 
 export default {
-  name: 'HotSpotList',
+  name: "HotSpotList",
   components: {
     EditPanel,
   },
   data() {
     return {
       hotspotTypeList,
-      
+
       showPanel: false,
       someData: { hotspots: [] },
       deleIndex: -1,
-      editTitle: '',
-    }
+      editTitle: "",
+    };
   },
   computed: {
     ...mapGetters({
       currentScene: "scene/currentScene",
-      hotspot: 'hotspot',
+      hotspot: "hotspot",
       info: "info",
     }),
   },
   watch: {
     "$route.name": function () {
-      this.showPanel = false
+      this.showPanel = false;
     },
     currentScene: {
       immediate: true,
       handler: function (newVal) {
-        this.someData = newVal.someData || ""
+        this.someData = newVal.someData || "";
         if (this.someData) {
-          if (typeof this.someData == 'string') {
+          if (typeof this.someData == "string") {
             try {
-              this.someData = JSON.parse(this.someData)
+              this.someData = JSON.parse(this.someData);
             } catch (e) {
-              console.error(e)
-              return false
+              console.error(e);
+              return false;
             }
           }
           if (!this.someData.hotspots) {
-            this.someData.hotspots = []
+            this.someData.hotspots = [];
           }
-        }
-        else {
-          this.someData = { hotspots: [] }
+        } else {
+          this.someData = { hotspots: [] };
         }
       },
     },
     showPanel(newVal) {
-      this.$store.commit("UpdateIsEditingState", newVal)
+      this.$store.commit("UpdateIsEditingState", newVal);
       this.$store.commit("tags/setIsConfirmingPosi", false);
     },
   },
   mounted() {
     this.$bus.on("updateHotSpotHV", (data) => {
-      let hptarget = this.someData.hotspots.find((item) => item.name.toLowerCase() == data.hpname.toLowerCase())
+      let hptarget = this.someData.hotspots.find(
+        (item) => item.name.toLowerCase() == data.hpname.toLowerCase()
+      );
       console.log(hptarget);
-      hptarget.ath = data.ath
-      hptarget.atv = data.atv
-    })
+      hptarget.ath = data.ath;
+      hptarget.atv = data.atv;
+    });
 
     this.$bus.on("openHotspot", (data) => {
-      let idx = this.someData.hotspots.findIndex((item) => item.name == data)
+      let idx = this.someData.hotspots.findIndex((item) => item.name == data);
       console.log(data);
       if (data == this.hotspot.name) {
-        window.__krfn.utils.looktohotspot(this.$getKrpano(), this.hotspot.name)
+        window.__krfn.utils.looktohotspot(this.$getKrpano(), this.hotspot.name);
         if (!this.showPanel) {
-          this.open(this.someData.hotspots[idx])
+          this.open(this.someData.hotspots[idx]);
         }
-        return
+        return;
       }
-      if (this.editTitle == '新增' || this.editTitle == this.$i18n.t('hotspot.add')) {
+      if (
+        this.editTitle == "新增" ||
+        this.editTitle == this.$i18n.t("hotspot.add")
+      ) {
         if (this.showPanel) {
           return this.$confirm({
-            content: this.$i18n.t('hotspot.close_dialog'),
+            content: this.$i18n.t("hotspot.close_dialog"),
             ok: () => {
-              this.deleteKRHotspot(this.hotspot)
-              this.open(this.someData.hotspots[idx])
-            }
-          })
+              this.deleteKRHotspot(this.hotspot);
+              this.open(this.someData.hotspots[idx]);
+            },
+          });
         }
-
       }
 
-      this.open(this.someData.hotspots[idx])
-
-    })
+      this.open(this.someData.hotspots[idx]);
+    });
   },
   methods: {
     deleteKRHotspot(data) {
-      this.$getKrpano().call("removehotspot(" + data.name + ",true);")
-      this.$getKrpano().call("removeplugin(" + ("tooltip_" + data.name) + ",true);")
+      this.$getKrpano().call("removehotspot(" + data.name + ",true);");
+      this.$getKrpano().call(
+        "removeplugin(" + ("tooltip_" + data.name) + ",true);"
+      );
     },
     close(data) {
       if (data) {
-        if (data.type == 'edit') {
-          this.deleteKRHotspot(data.data)
-          this.$bus.emit('addhotspot', data.data)
-          let idx = this.someData.hotspots.findIndex(item => item.name == data.data.name)
-          this.someData.hotspots[idx] = data.data
-        }
-        else {
-          this.deleteKRHotspot(data.data)
+        if (data.type == "edit") {
+          this.deleteKRHotspot(data.data);
+          this.$bus.emit("addhotspot", data.data);
+          let idx = this.someData.hotspots.findIndex(
+            (item) => item.name == data.data.name
+          );
+          this.someData.hotspots[idx] = data.data;
+        } else {
+          this.deleteKRHotspot(data.data);
         }
       }
-      this.showPanel = false
+      this.showPanel = false;
     },
 
     updateInfo() {
-      let iidx = this.info.scenes.findIndex(item => this.currentScene.sceneCode == item.sceneCode)
+      let iidx = this.info.scenes.findIndex(
+        (item) => this.currentScene.sceneCode == item.sceneCode
+      );
       if (iidx > -1) {
         this.info.scenes[iidx] = {
-          ...this.currentScene
-        }
+          ...this.currentScene,
+        };
       }
-      this.$store.commit("SetInfo", this.info)
+      this.$store.commit("SetInfo", this.info);
     },
     save(data) {
-      let HV = window.__krfn.utils.getHotspotHV(this.$getKrpano(), data.name)
-      data.ath = HV.ath
-      data.atv = HV.atv
-      let idx = this.someData.hotspots.findIndex((item) => item.name === data.name)
+      let HV = window.__krfn.utils.getHotspotHV(this.$getKrpano(), data.name);
+      data.ath = HV.ath;
+      data.atv = HV.atv;
+      let idx = this.someData.hotspots.findIndex(
+        (item) => item.name === data.name
+      );
       if (idx <= -1) {
-        this.someData.hotspots.push(data)
-      }
-      else {
-        this.someData.hotspots[idx] = data
+        this.someData.hotspots.push(data);
+      } else {
+        this.someData.hotspots[idx] = data;
       }
 
-      this.currentScene.someData = this.someData
-      this.$msg.success(this.editTitle + this.$i18n.t('hotspot.success'))
-
-      window.g_hotspotCurrentScale = mapFontSize[data.fontSize] || 1
+      this.currentScene.someData = this.someData;
+      this.$msg.success(this.editTitle + this.$i18n.t("hotspot.success"));
 
+      window.g_hotspotCurrentScale = mapFontSize[data.fontSize] || 1;
 
-      let iidx = this.info.scenes.findIndex(item => this.currentScene.sceneCode == item.sceneCode)
+      let iidx = this.info.scenes.findIndex(
+        (item) => this.currentScene.sceneCode == item.sceneCode
+      );
       if (iidx > -1) {
         this.info.scenes[iidx] = {
-          ...this.currentScene
-        }
+          ...this.currentScene,
+        };
       }
 
-      this.updateInfo()
-
+      this.updateInfo();
     },
     deleteHot(data) {
       this.someData.hotspots.splice(
         this.someData.hotspots.findIndex((item) => item.name === data.name),
         1
-      )
-      this.deleteKRHotspot(data)
-      this.currentScene.someData = this.someData
-      this.updateInfo()
-      this.$msg.success(this.$i18n.t('hotspot.delete')+this.$i18n.t('hotspot.success'))
+      );
+      this.deleteKRHotspot(data);
+      this.currentScene.someData = this.someData;
+      this.updateInfo();
+      this.$msg.success(
+        this.$i18n.t("hotspot.delete") + this.$i18n.t("hotspot.success")
+      );
     },
     open(data) {
-      let hotspotData = null
+      let hotspotData = null;
       if (data.isAdd) {
-        this.editTitle = this.$i18n.t('hotspot.add')
+        this.editTitle = this.$i18n.t("hotspot.add");
         hotspotData = {
           hotspotType: data.hotspotType, // 热点类型,切换场景、图片、视频、音频、链接、文本等等
-          
-          hotspotIconType: 'system_icon', // 热点图标的类型,系统图标(system_icon)、自定义图片(custom_image)、序列帧(serial_frame)、个性标签(personalized_tag)
-          img: this.$config.getStaticResource('/panoassets/images/hotspot/icon/') + `img_doticon_${String(data.idxInSystemIconList).padStart(2, '0')}.svg`, // 热点图标类型为系统图标时,图标在展时段使用的url
-          icontype: 'icon' + data.idxInSystemIconList, // 热点图标类型为系统图标时,图标的id
-          customIconInfo: { // 热点图标类型为自定义图标时,图标的数据
-            img: '',
+
+          hotspotIconType: "system_icon", // 热点图标的类型,系统图标(system_icon)、自定义图片(custom_image)、序列帧(serial_frame)、个性标签(personalized_tag)
+          img:
+            this.$config.getStaticResource("/panoassets/images/hotspot/icon/") +
+            `img_doticon_${String(data.idxInSystemIconList).padStart(
+              2,
+              "0"
+            )}.svg`, // 热点图标类型为系统图标时,图标在展时段使用的url
+          icontype: "icon" + data.idxInSystemIconList, // 热点图标类型为系统图标时,图标的id
+          customIconInfo: {
+            // 热点图标类型为自定义图标时,图标的数据
+            img: "",
           },
-          serialFrameInfo: { // 热点图标类型为序列帧时,序列帧的数据
-            url: '',
+          serialFrameInfo: {
+            // 热点图标类型为序列帧时,序列帧的数据
+            url: "",
             frameNumber: 0, // 总帧数
             duration: 0, // 总播放时长(秒)
           },
-          personalizedTagInfo: { // 热点图标类型为个性标签时,个性标签的数据
+          personalizedTagInfo: {
+            // 热点图标类型为个性标签时,个性标签的数据
             isShowLine: true,
-            lineDirection: 'left-top',
-            fillColor: 'rgba(0, 0, 0, 1)',
-            borderColor: 'rgba(0, 0, 0, 1)',
-            textColor: 'rgba(0, 0, 0, 1)',
-            textDirection: 'left-right',
+            lineDirection: "left-top",
+            fillColor: "rgba(0, 0, 0, 1)",
+            borderColor: "rgba(0, 0, 0, 1)",
+            textColor: "rgba(0, 0, 0, 1)",
+            textDirection: "left-right",
             isTextWrap: false,
             textNumPerLine: 10,
           },
           name: "_" + this.$randomWord(true, 8, 8),
-          hotspotTitle: this.$i18n.t('hotspot.click_to_comfirm'),
+          hotspotTitle: this.$i18n.t("hotspot.click_to_comfirm"),
           fontSize: 12,
-          type: '',
-          link: '',
-          titleDisplayMode: 'always', // 'always' | 'never' | 'hover' 标题显示方式
-          titlePosition: 'top', // 'top' | 'bottom' | 'left' | 'right' | 'custom' 标题相对图标位置
-          ath: '',
-          atv: '',
+          type: "",
+          link: "",
+          titleDisplayMode: "always", // 'always' | 'never' | 'hover' 标题显示方式
+          titlePosition: "top", // 'top' | 'bottom' | 'left' | 'right' | 'custom' 标题相对图标位置
+          ath: "",
+          atv: "",
           size: 1,
           secne: null,
-          hyperlink: '',
-          textarea: '',
+          hyperlink: "",
+          textarea: "",
           image: [], // 热点类型为图片时,图片列表
-          audio: '',
-          video: '',
-          imageTextInfo: { // 热点类型为图文时,图文内容
+          audio: "",
+          video: "",
+          imageTextInfo: {
+            // 热点类型为图文时,图文内容
             imageList: [],
-            text: '',
+            text: "",
             isApplyToAll: true,
             audio: {
               // ancestors: "",
@@ -313,104 +355,117 @@ export default {
               // type: "audio",
               // updateTime: "2022-11-01 19:49",
               // userId: "13825625448",
-            }
+            },
           },
-          phoneInfo: { // 热点类型为电话时,对应数据
-            phone: '',
+          phoneInfo: {
+            // 热点类型为电话时,对应数据
+            phone: "",
           },
-          pdfInfo: { // 热点类型为pdf时,对应数据
-            name: '',
-            url: '',
+          pdfInfo: {
+            // 热点类型为pdf时,对应数据
+            name: "",
+            url: "",
           },
           articleInfo: {
-            html: '',
-          }
-        }
+            html: "",
+          },
+        };
+
+        this.$bus.emit("addhotspot", hotspotData);
+        this.$getKrpano().set(
+          "layer[tooltip_" + hotspotData.name + "].visible",
+          true
+        );
+        setTimeout(() => {
+          this.$store.commit("tags/setIsConfirmingPosi", hotspotData.name);
+        }, 0);
+
+        console.log("hotspotData", hotspotData);
       } else {
-        hotspotData = browser.CloneObject(data)
+        hotspotData = browser.CloneObject(data);
         /**
          * v1.3新增
          */
         if (!hotspotData.hotspotIconType) {
-          hotspotData.hotspotIconType = 'system_icon'
+          hotspotData.hotspotIconType = "system_icon";
         }
         if (!hotspotData.customIconInfo) {
-          hotspotData.customIconInfo = { 
-            img: '',
-          }
+          hotspotData.customIconInfo = {
+            img: "",
+          };
         }
         if (!hotspotData.serialFrameInfo) {
           hotspotData.serialFrameInfo = {
-            url: '',
+            url: "",
             frameNumber: 0,
             duration: 0,
-          }
+          };
         }
         hotspotData.personalizedTagInfo = {
           isShowLine: true,
-          lineDirection: 'left-top',
-          fillColor: 'rgba(0, 0, 0, 1)',
-          borderColor: 'rgba(0, 0, 0, 1)',
-          textColor: 'rgba(0, 0, 0, 1)',
-          textDirection: 'left-right',
+          lineDirection: "left-top",
+          fillColor: "rgba(0, 0, 0, 1)",
+          borderColor: "rgba(0, 0, 0, 1)",
+          textColor: "rgba(0, 0, 0, 1)",
+          textDirection: "left-right",
           isTextWrap: false,
           textNumPerLine: 10,
-        }
+        };
         // v1.3把visible: Boolean换成了titleDisplayMode
         if (hotspotData.visible) {
-          hotspotData.titleDisplayMode = 'always'
+          hotspotData.titleDisplayMode = "always";
         } else if (hotspotData.visible === false) {
-          hotspotData.titleDisplayMode = 'never'
+          hotspotData.titleDisplayMode = "never";
         }
         if (!hotspotData.titlePosition) {
-          hotspotData.titlePosition = 'top'
+          hotspotData.titlePosition = "top";
         }
         if (!hotspotData.imageTextInfo) {
           hotspotData.imageTextInfo = {
             imageList: [],
-            text: '',
+            text: "",
             isApplyToAll: true,
-            audio: {}
-          }
+            audio: {},
+          };
         }
         if (!hotspotData.phoneInfo) {
           hotspotData.phoneInfo = {
-            phone: '',
-          }
+            phone: "",
+          };
         }
         if (!hotspotData.pdfInfo) {
           hotspotData.pdfInfo = {
-            name: '',
-            url: '',
-          }
+            name: "",
+            url: "",
+          };
         }
         if (!hotspotData.articleInfo) {
           hotspotData.articleInfo = {
-            html: '',
-          }
+            html: "",
+          };
         }
         /**
          * end of v1.3新增
          */
       }
-      this.$store.commit("SetHotspot", hotspotData)
-      this.showPanel = true
+      this.$store.commit("SetHotspot", hotspotData);
+      this.showPanel = true;
 
       if (!data.isAdd) {
-        this.editTitle =  this.$i18n.t('hotspot.edit')
-        window.__krfn.utils.looktohotspot(this.$getKrpano(), data.name)
+        this.editTitle = this.$i18n.t("hotspot.edit");
+        window.__krfn.utils.looktohotspot(this.$getKrpano(), data.name);
       }
     },
     clickoutside() {
       if (this.deleIndex > -1) {
-        this.deleIndex = -1
+        this.deleIndex = -1;
       }
     },
     onClickGo4dkk() {
-      window.open('/#/scene')
+      window.open("/#/scene");
     },
   },
-}
+};
 </script>
 
 <style lang="less" scoped>
@@ -428,7 +483,7 @@ export default {
     flex: 0 0 auto;
     margin-bottom: 24px;
 
-    >i {
+    > i {
       font-size: 12px;
       position: relative;
       top: -2px;
@@ -459,7 +514,7 @@ export default {
       }
       > .type-name {
         font-size: 12px;
-        color: #FFFFFF;
+        color: #ffffff;
       }
       > .exp-tag {
         position: absolute;
@@ -475,7 +530,7 @@ export default {
     flex: 0 0 auto;
     margin-top: 24px;
     font-size: 18px;
-    color: #FFFFFF;
+    color: #ffffff;
 
     .number {
       font-size: 14px;
@@ -489,7 +544,7 @@ export default {
     flex: 1 0 1px;
     margin-top: 16px;
     background: available;
-    background: #1A1B1D;
+    background: #1a1b1d;
     border-radius: 4px;
     border: 1px solid #404040;
     position: relative;
@@ -514,11 +569,11 @@ export default {
           }
         }
 
-        >.hot-spot-thumb {
+        > .hot-spot-thumb {
           width: 18px;
         }
 
-        >.hot-spot-title {
+        > .hot-spot-title {
           flex: 1 1 auto;
           margin-left: 10px;
           text-overflow: ellipsis;
@@ -526,7 +581,7 @@ export default {
           white-space: nowrap;
         }
 
-        >.icon-delete {
+        > .icon-delete {
           margin-left: 12px;
           display: none;
           cursor: pointer;
@@ -537,7 +592,7 @@ export default {
           }
         }
 
-        >.deletion-confirm-wrap {
+        > .deletion-confirm-wrap {
           position: absolute;
           top: 0;
           bottom: 0;
@@ -548,12 +603,12 @@ export default {
           border-top-right-radius: 2px;
           border-bottom-right-radius: 2px;
 
-          >.deletion-confirm {
+          > .deletion-confirm {
             position: absolute;
             top: 0;
             bottom: 0;
             width: 100%;
-            background: #FA5555;
+            background: #fa5555;
             transition: right 0.3s;
             cursor: pointer;
             text-align: center;
@@ -562,7 +617,7 @@ export default {
             pointer-events: auto;
 
             &::after {
-              content: '';
+              content: "";
               height: 100%;
               vertical-align: middle;
               display: inline-block;
@@ -612,7 +667,6 @@ export default {
     width: 100%;
   }
 
-  
   .goto-4dkk-tip {
     > .img-wrap {
       position: relative;

+ 20 - 19
packages/qjkankan-editor/vue.config.js

@@ -1,14 +1,14 @@
-const proxy_url = process.env.VUE_APP_PROXY_URL
+const proxy_url = process.env.VUE_APP_PROXY_URL;
 
-process.env.VUE_APP_VERSION = require('./package.json').version
+process.env.VUE_APP_VERSION = require("./package.json").version;
 
 let pages = {
-  edit: 'src/pages/edit.js',
+  edit: "src/pages/edit.js",
   // show: 'src/pages/show.js',
   // showMobile: 'src/pages/showMobile.js',
-  vr: 'src/pages/vr.js',
-  material: 'src/pages/material.js'
-}
+  vr: "src/pages/vr.js",
+  material: "src/pages/material.js",
+};
 
 module.exports = {
   pages: pages,
@@ -20,33 +20,34 @@ module.exports = {
     loaderOptions: {
       less: {
         globalVars: {
-          color: process.env.VUE_APP_MAIN_COLOR || "#0076F6"
-        }
-      }
-    }
+          color: process.env.VUE_APP_MAIN_COLOR || "#0076F6",
+        },
+      },
+    },
   },
   devServer: {
     inline: false,
     hot: true,
     liveReload: false,
-    port:8082,
+    port: 8089,
+    disableHostCheck: true,
     proxy: {
-      '/manage': {
-          target: proxy_url,
-          changeOrigin: true,
+      "/manage": {
+        target: proxy_url,
+        changeOrigin: true,
       },
-      '/ucenter': {
+      "/ucenter": {
         target: process.env.VUE_APP_PROXY_URL_ROOT,
         changeOrigin: true,
       },
-      '/web': {
+      "/web": {
         target: proxy_url,
         changeOrigin: true,
       },
-      '/api': {
+      "/api": {
         target: process.env.VUE_APP_PROXY_URL_ROOT,
         changeOrigin: true,
-      }
+      },
     },
-  }
+  },
 };

Разница между файлами не показана из-за своего большого размера
+ 6 - 8
packages/qjkankan-view/public/showviewer/lib/krpano/js/tour.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
packages/qjkankan-view/public/showviewer/lib/krpano/skin/vtourskin copy.xml


Разница между файлами не показана из-за своего большого размера
+ 1281 - 1
packages/qjkankan-view/public/showviewer/lib/krpano/skin/vtourskin.xml


+ 13 - 4
packages/qjkankan-view/src/sdk/QJKanKan/modules/Scene.js

@@ -26,8 +26,8 @@ export default class Scene extends Emiter {
     }
   }
 
-  sceneReady(){
-    this.emit('sceneReady')
+  sceneReady() {
+    this.emit("sceneReady");
   }
 
   async start() {
@@ -61,15 +61,24 @@ export default class Scene extends Emiter {
     }
 
     if (this.app.options.isHavePano) {
+      // debugger;
       embedpano({
         ...this.app.options,
         vars: {
           ...this.app.options.vars,
           ...settings,
         },
+
+        onready: (pano) => {
+          console.log("pano", pano);
+          this.emit("ready");
+        },
+        onerror: function (error) {
+          debugger;
+          console.error("error", error);
+        },
       });
-    }
-    else {
+    } else {
       this.emit("ready");
     }
   }