tremble %!s(int64=4) %!d(string=hai) anos
pai
achega
618e589413
Modificáronse 65 ficheiros con 2207 adicións e 1266 borrados
  1. 1 1
      .env
  2. 6 0
      .env.bendi
  3. 0 5
      .env.uat
  4. 27 0
      package-lock.json
  5. 4 1
      package.json
  6. 1 1
      public/edit.html
  7. 1 1
      public/material.html
  8. 4 1
      public/show.html
  9. 1 1
      public/showMobile.html
  10. 197 0
      public/static/lib/canvas2Image.js
  11. 6 0
      public/static/lib/html2canvas.js
  12. 1 1
      public/static/template/skin/vtourskin.xml
  13. 39 26
      src/api/index.js
  14. 5 0
      src/assets/style/component.less
  15. 35 6
      src/components/audio/index.vue
  16. 1 1
      src/components/preview/index.vue
  17. 43 47
      src/components/select.vue
  18. 1 1
      src/components/shared/message/LoginTips.vue
  19. 5 0
      src/components/shared/uploads/Upload.vue
  20. 13 5
      src/components/shared/uploads/UploadMultiple.vue
  21. 17 8
      src/components/tableSelect.vue
  22. 9 2
      src/components/tablist/index.vue
  23. 1 1
      src/core/utils.js
  24. 160 114
      src/framework/Head.vue
  25. 38 73
      src/framework/Toolbar.vue
  26. 20 22
      src/framework/core/index.vue
  27. 69 26
      src/framework/show/index.vue
  28. 118 75
      src/framework/show/list.vue
  29. 3 3
      src/framework/show/popup/password.vue
  30. 26 2
      src/framework/show/popup/preview.vue
  31. 45 0
      src/framework/showMobile/iframe.vue
  32. 264 172
      src/framework/showMobile/index.vue
  33. 216 61
      src/framework/showMobile/list.vue
  34. 3 3
      src/framework/showMobile/popup/password.vue
  35. 1 1
      src/framework/showMobile/popup/preview.vue
  36. 36 0
      src/framework/vr/index.vue
  37. 1 1
      src/lang/_zh.js
  38. 212 135
      src/mixins/index.js
  39. 16 10
      src/router/index.js
  40. 5 2
      src/utils/file.js
  41. 34 8
      src/utils/request.js
  42. 1 2
      src/views/base/EditPanel/logo.vue
  43. 2 1
      src/views/base/EditPanel/opening.vue
  44. 7 4
      src/views/base/Toolbar.vue
  45. 27 7
      src/views/hotspot/EditPanel.vue
  46. 28 64
      src/views/hotspot/Setting.vue
  47. 1 1
      src/views/hotspot/hotspotType/audio.vue
  48. 3 0
      src/views/hotspot/hotspotType/image.vue
  49. 13 2
      src/views/hotspot/hotspotType/link.vue
  50. 1 10
      src/views/hotspot/hotspotType/scene.vue
  51. 1 1
      src/views/hotspot/hotspotType/video.vue
  52. 1 0
      src/views/hotspot/index.vue
  53. 12 39
      src/views/information/Setting.vue
  54. 130 119
      src/views/information/Toolbar.vue
  55. 72 138
      src/views/information/index.vue
  56. 15 3
      src/views/material/audio/index.vue
  57. 11 4
      src/views/material/image/index.vue
  58. 113 28
      src/views/material/pano/index.vue
  59. 10 2
      src/views/material/popup/cover.vue
  60. 20 4
      src/views/material/popup/preview.vue
  61. 1 1
      src/views/material/popup/share.vue
  62. 5 2
      src/views/material/video/index.vue
  63. 45 14
      src/views/material/works/index.vue
  64. 2 2
      src/views/screen/Setting.vue
  65. 1 1
      src/views/screen/Toolbar.vue

+ 1 - 1
.env

@@ -3,4 +3,4 @@ VUE_APP_STATIC_DIR=static
 VUE_APP_INNERNET=https://fcb.intranet.4dkankan.com
 VUE_APP_CDN=https://oss-xiaoan.oss-cn-shenzhen.aliyuncs.com
 VUE_APP_PROXY_URL='http://test.4dkankan.com/qjkankan/'
-VUE_APP_URL_FILL='/qjkankan'
+VUE_APP_URL_FILL=/qjkankan

+ 6 - 0
.env.bendi

@@ -0,0 +1,6 @@
+VUE_APP_MAIN_COLOR=''
+VUE_APP_STATIC_DIR=static
+VUE_APP_INNERNET=https://fcb.intranet.4dkankan.com
+VUE_APP_CDN=https://oss-xiaoan.oss-cn-shenzhen.aliyuncs.com
+VUE_APP_PROXY_URL='http://192.168.0.135:8001/'
+VUE_APP_URL_FILL='/'

+ 0 - 5
.env.uat

@@ -1,5 +0,0 @@
-VUE_APP_MAIN_COLOR=''
-VUE_APP_STATIC_DIR=static
-VUE_APP_INNERNET=https://vr-mc01-uat.fcb.com.cn
-VUE_APP_CDN=https://vr-web02-uat.fcb.com.cn
-VUE_APP_PROXY_URL=''

+ 27 - 0
package-lock.json

@@ -5493,6 +5493,14 @@
         }
       }
     },
+    "dom7": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npm.taobao.org/dom7/download/dom7-3.0.0.tgz",
+      "integrity": "sha1-uGHOXWemvs16qjrQKUL/FLEkAzE=",
+      "requires": {
+        "ssr-window": "^3.0.0-alpha.1"
+      }
+    },
     "domain-browser": {
       "version": "1.2.0",
       "resolved": "https://registry.npm.taobao.org/domain-browser/download/domain-browser-1.2.0.tgz?cache=0&sync_timestamp=1604239998047&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdomain-browser%2Fdownload%2Fdomain-browser-1.2.0.tgz",
@@ -12105,6 +12113,11 @@
         "tweetnacl": "~0.14.0"
       }
     },
+    "ssr-window": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npm.taobao.org/ssr-window/download/ssr-window-3.0.0.tgz?cache=0&sync_timestamp=1604919636199&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fssr-window%2Fdownload%2Fssr-window-3.0.0.tgz",
+      "integrity": "sha1-/VuCgBY4lD4MxwTEaRgBQ1r3rDc="
+    },
     "ssri": {
       "version": "6.0.1",
       "resolved": "https://registry.npm.taobao.org/ssri/download/ssri-6.0.1.tgz",
@@ -12374,6 +12387,15 @@
         "util.promisify": "~1.0.0"
       }
     },
+    "swiper": {
+      "version": "6.5.6",
+      "resolved": "https://registry.npm.taobao.org/swiper/download/swiper-6.5.6.tgz",
+      "integrity": "sha1-TR3FzRJGlt12WBjySEoeyODT07w=",
+      "requires": {
+        "dom7": "^3.0.0",
+        "ssr-window": "^3.0.0"
+      }
+    },
     "table": {
       "version": "5.4.6",
       "resolved": "https://registry.npm.taobao.org/table/download/table-5.4.6.tgz?cache=0&sync_timestamp=1609732685428&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftable%2Fdownload%2Ftable-5.4.6.tgz",
@@ -13197,6 +13219,11 @@
       "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1609359872993&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
       "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
     },
+    "vue-awesome-swiper": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npm.taobao.org/vue-awesome-swiper/download/vue-awesome-swiper-4.1.1.tgz",
+      "integrity": "sha1-j3qyIa0AMCHXVrhqphj0KZJJAP4="
+    },
     "vue-cropperjs": {
       "version": "4.2.0",
       "resolved": "https://registry.npm.taobao.org/vue-cropperjs/download/vue-cropperjs-4.2.0.tgz",

+ 4 - 1
package.json

@@ -4,7 +4,8 @@
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
-    "serve-uat": "vue-cli-service serve  --mode uat",
+    "serve-uat": "vue-cli-service serve --mode uat",
+    "serve-local": "vue-cli-service serve --mode bendi",
     "build": "vue-cli-service build",
     "build-uat": "vue-cli-service build --mode uat",
     "lint": "vue-cli-service lint"
@@ -12,8 +13,10 @@
   "dependencies": {
     "core-js": "^3.8.2",
     "photoswipe": "^4.1.3",
+    "swiper": "^6.5.6",
     "v-viewer": "^1.5.1",
     "vue": "^2.6.12",
+    "vue-awesome-swiper": "^4.1.1",
     "vue-cropperjs": "^4.2.0",
     "vue-i18n": "^8.22.3",
     "vue-photo-preview": "^1.1.3",

+ 1 - 1
public/edit.html

@@ -13,7 +13,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/animate/animate.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/mCustomScrollbar/jquery.mCustomScrollbar.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.css"/>
-    <title>VR楼盘项目编辑器</title>
+    <title>全景看看作品制作工具</title>
   </head>
   <body>
     <div id="app"></div>

+ 1 - 1
public/material.html

@@ -12,7 +12,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/animate/animate.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/mCustomScrollbar/jquery.mCustomScrollbar.min.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.css"/>
-    <title>VR楼盘项目编辑器</title>
+    <title>全景看看作品制作工具</title>
   </head>
   <body>
     <div id="app"></div>

+ 4 - 1
public/show.html

@@ -8,7 +8,8 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfont/iconfont.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfontQJ/iconfont.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfontVR/iconfont.css"/>
-    <link rel="stylesheet" href="//at.alicdn.com/t/font_2410347_c69iaonqh7f.css"/>
+    <link rel="stylesheet" href="//at.alicdn.com/t/font_2410347_4htx35g8w1b.css"/>
+    <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.css"/>
     <link rel="icon" href="./favicon.ico" />
     <title>VR楼盘</title>
   </head>
@@ -17,5 +18,7 @@
     <!-- built files will be auto injected -->
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/jquery-2.1.1.min.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/krpano/js/tour.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>/lib/mCustomScrollbar/jquery.mCustomScrollbar.concat.min.js"></script>
+    <script src="<%= VUE_APP_STATIC_DIR %>/lib/scrollbar/perfect-scrollbar.min.js"></script>
   </body>
 </html>

+ 1 - 1
public/showMobile.html

@@ -8,7 +8,7 @@
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfont/iconfont.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfontQJ/iconfont.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfontVR/iconfont.css"/>
-    <link rel="stylesheet" href="//at.alicdn.com/t/font_2410347_c69iaonqh7f.css"/>
+    <link rel="stylesheet" href="//at.alicdn.com/t/font_2410347_4htx35g8w1b.css"/>
     <link rel="icon" href="./favicon.ico" />
     <title>VR楼盘</title>
   </head>

+ 197 - 0
public/static/lib/canvas2Image.js

@@ -0,0 +1,197 @@
+/*
+ * Canvas2Image v0.1
+ * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
+ * MIT License [http://www.opensource.org/licenses/mit-license.php]
+ */
+
+var Canvas2Image = (function() {
+    // check if we have canvas support
+    var oCanvas = document.createElement("canvas"),
+        sc = String.fromCharCode,
+        strDownloadMime = "image/octet-stream",
+        bReplaceDownloadMime = false;
+
+    // no canvas, bail out.
+    if (!oCanvas.getContext) {
+        return {
+            saveAsBMP : function(){},
+            saveAsPNG : function(){},
+            saveAsJPEG : function(){}
+        }
+    }
+
+    var bHasImageData = !!(oCanvas.getContext("2d").getImageData),
+        bHasDataURL = !!(oCanvas.toDataURL),
+        bHasBase64 = !!(window.btoa);
+
+    // ok, we're good
+    var readCanvasData = function(oCanvas) {
+        var iWidth = parseInt(oCanvas.width),
+            iHeight = parseInt(oCanvas.height);
+        return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
+    }
+
+    // base64 encodes either a string or an array of charcodes
+    var encodeData = function(data) {
+        var i, aData, strData = "";
+
+        if (typeof data == "string") {
+            strData = data;
+        } else {
+            aData = data;
+            for (i = 0; i < aData.length; i++) {
+                strData += sc(aData[i]);
+            }
+        }
+        return btoa(strData);
+    }
+
+    // creates a base64 encoded string containing BMP data takes an imagedata object as argument
+    var createBMP = function(oData) {
+        var strHeader = '',
+            iWidth = oData.width,
+            iHeight = oData.height;
+
+        strHeader += 'BM';
+
+        var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes
+        strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+        strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+        strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+        strHeader += sc(iFileSize % 256);
+
+        strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
+        strHeader += sc(40, 0, 0, 0); // info header size
+
+        var iImageWidth = iWidth;
+        strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+        strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+        strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+        strHeader += sc(iImageWidth % 256);
+
+        var iImageHeight = iHeight;
+        strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+        strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+        strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+        strHeader += sc(iImageHeight % 256);
+
+        strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
+        strHeader += sc(0, 0, 0, 0); // compression = none
+
+        var iDataSize = iWidth*iHeight*4;
+        strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+        strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+        strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+        strHeader += sc(iDataSize % 256);
+
+        strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
+
+        var aImgData = oData.data,
+            strPixelData = "",
+            c, x, y = iHeight,
+            iOffsetX, iOffsetY, strPixelRow;
+
+        do {
+            iOffsetY = iWidth*(y-1)*4;
+            strPixelRow = "";
+            for (x = 0; x < iWidth; x++) {
+                iOffsetX = 4*x;
+                strPixelRow += sc(
+                    aImgData[iOffsetY + iOffsetX + 2], // B
+                    aImgData[iOffsetY + iOffsetX + 1], // G
+                    aImgData[iOffsetY + iOffsetX], // R
+                    aImgData[iOffsetY + iOffsetX + 3] // A
+                );
+            }
+            strPixelData += strPixelRow;
+        } while (--y);
+
+        return encodeData(strHeader + strPixelData);
+    }
+
+    // sends the generated file to the client
+    var saveFile = function(strData) {
+        if (!window.open(strData)) {
+            document.location.href = strData;
+        }
+    }
+
+    var makeDataURI = function(strData, strMime) {
+        return "data:" + strMime + ";base64," + strData;
+    }
+
+    // generates a <img> object containing the imagedata
+    var makeImageObject = function(strSource) {
+        var oImgElement = document.createElement("img");
+        oImgElement.src = strSource;
+        return oImgElement;
+    }
+
+    var scaleCanvas = function(oCanvas, iWidth, iHeight) {
+        if (iWidth && iHeight) {
+            var oSaveCanvas = document.createElement("canvas");
+
+            oSaveCanvas.width = iWidth;
+            oSaveCanvas.height = iHeight;
+            oSaveCanvas.style.width = iWidth+"px";
+            oSaveCanvas.style.height = iHeight+"px";
+
+            var oSaveCtx = oSaveCanvas.getContext("2d");
+
+            oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth);
+
+            return oSaveCanvas;
+        }
+        return oCanvas;
+    }
+
+    return {
+        saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
+            if (!bHasDataURL) return false;
+            var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
+                strMime = "image/png",
+                strData = oScaledCanvas.toDataURL(strMime);
+
+            if (bReturnImg) {
+                return makeImageObject(strData);
+            } else {
+                saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
+            }
+            return true;
+        },
+
+        saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
+            if (!bHasDaaURL) return false;
+
+            var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
+                strMime = "image/jpeg",
+                strData = oScaledCanvas.toDataURL(strMime);
+
+            // check if browser actually supports jpeg by looking for the mime type in the data uri. if not, return false
+            if (strData.indexOf(strMime) != 5) return false;
+
+            if (bReturnImg) {
+                return makeImageObject(strData);
+            } else {
+                saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
+            }
+            return true;
+        },
+
+        saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
+            if (!(bHasDataURL && bHasImageData && bHasBase64)) return false;
+
+            var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
+                strMime = "image/bmp",
+                oData = readCanvasData(oScaledCanvas),
+                strImgData = createBMP(oData);
+
+            if (bReturnImg) {
+                return makeImageObject(makeDataURI(strImgData, strMime));
+            } else {
+                saveFile(makeDataURI(strImgData, strMime));
+            }
+            return true;
+        }
+    };
+})();

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 6 - 0
public/static/lib/html2canvas.js


+ 1 - 1
public/static/template/skin/vtourskin.xml

@@ -17,7 +17,7 @@
                    design_text_shadow="1"/> 
     <include url="%SWFPATH%/plugins/swipe_gallery.xml"/>
 	<include url="%SWFPATH%/plugins/showtext.xml" />
-    <autorotate enabled="false" waittime="1.0" speed="-3.0" horizon="0.0" tofov="120.0"/>
+    <autorotate enabled="false" waittime="1.0" speed="-2.0" horizon="0.0" tofov="120.0"/>
     <vtourskinxmlpath url="./"/>
     <include url="%SWFPATH%/plugins/tooltip.xml"/>
     <settings name="auto_thumbs" thumb_size="84" thumb_background_size="90" thumb_spacing="14" left="0" right="0"

+ 39 - 26
src/api/index.js

@@ -28,7 +28,8 @@ const URL_FILL =  config.urlFill
  * @param {*} no 
  */
  export function getPanoInfo(data, ok, no) {
-    return http.get(`${URL_FILL}/manage/work/detail/${number()}`, {}, ok, no)
+    let ossUrl = `https://ossxiaoan.4dage.com/720yun_fd_manage`
+    return http.get(`${ossUrl}/${data||number()}/someData.json`, {}, ok, no)
 }
 
 
@@ -106,7 +107,7 @@ const URL_FILL =  config.urlFill
  * @param {*} no 
  */
  export function getSceneList(data, ok, no) {
-    return http.postJson(`${URL_FILL}/manage/scene/select/4dkk/${number()}`, data, ok, no)
+    return http.postJson(`${URL_FILL}/manage/work/select/4dkk/${number()}`, data, ok, no)
 }
 
 
@@ -140,7 +141,7 @@ const URL_FILL =  config.urlFill
  * @param {*} no 
  */
  export function uploadCover(data, ok, no) {
-    return http.uploadBlobFile(`${URL_FILL}/manage/scene/upload`, data, ok, no)
+    return http.uploadBlobFile(`${URL_FILL}/manage/work/upload`, data, ok, no)
 }
 
 
@@ -247,6 +248,15 @@ export function saveInitScreen(data, ok, no) {
     return http.get(`${URL_FILL}/web/common/getCatalog/${number()}`, data, ok, no)
 }
 
+/**
+ * 检查作品是否可用
+ * @param {*} data 
+ * @param {*} ok 
+ * @param {*} no 
+ */
+ export function checkWork(data, ok, no) {
+    return http.get(`${URL_FILL}/web/common/checkWork/${number()}`, data, ok, no)
+}
 
 
 /**
@@ -264,11 +274,29 @@ export function saveInitScreen(data, ok, no) {
 /**
  * 检测登陆状态
  */
- export function checkLogin() {
-    return http.get(`${URL_FILL}/web/common/checkToken`)
+export function checkLogin() {
+    if (window.location.pathname.indexOf('material.html')>-1) {
+        return http.get(`${URL_FILL}/web/common/checkToken/`)
+
+    }else{
+        return http.get(`${URL_FILL}/manage/work/checkToken/${number()}`)
+    }
+}
+
+
+
+
+
+/**
+ * 检测素材状态
+ */
+ export function checkMStatus(data, ok, no) {
+    return http.get(`${URL_FILL}/manage/fodder/checkStatus/${data.ids.join(',')}`, data, ok, no)
 }
 
 
+
+
 /**
  * 获取作品基本信息(展示端)
  * @param {*} data 
@@ -321,22 +349,6 @@ export function saveInitScreen(data, ok, no) {
 
 
 /**
- * 上传全景图
- * @param {*} data 
- * @param {*} ok 
- * @param {*} no 
- */
-export function uploadPano(data, type, ok, no) {
-    return http.uploadFile(`/fcb/pano/scene/uploadPano/${number()}/${type}/${HDNumber()}`, data, ok, no)
-}
-
-
-
-
-
-
-
-/**
  * 保存全景图基本信息
  * @param {*} data 
  * @param {*} ok 
@@ -468,10 +480,10 @@ export function setListSort(data, ok, no) {
  * @param {*} no 
  */
  export function getMaterialList(data, ok, no) {
-     let url = `${URL_FILL}/manage/fodder/list`
-    if (data.urlSelect) {
-        url = `${URL_FILL}/manage/fodder/select/${data.type}/${number()}`
-    }
+    let url = `${URL_FILL}/manage/fodder/list`
+    // if (data.urlSelect) {
+    //     url = `${URL_FILL}/manage/fodder/select/${data.type}/${number()}`
+    // }
     return http.postJson(url, data, ok, no)
 }
 
@@ -533,7 +545,8 @@ export function setListSort(data, ok, no) {
  * @param {*} no 
  */
  export function saveWorks(data, ok, no) {
-    return http.postJson(`${URL_FILL}/manage/work/save`, data, ok, no)
+    data.id = number()
+    return http.postJson(`${URL_FILL}/manage/work/edit`, data, ok, no)
 }
 
 

+ 5 - 0
src/assets/style/component.less

@@ -173,7 +173,12 @@ textarea:-ms-input-placeholder {
       background: rgba(255, 255, 255, 0.08);
       position: relative;
       cursor: pointer;
+      max-width: 150px;
+      text-overflow: ellipsis;
+      overflow: hidden;
+      white-space: nowrap;
       &.hidden {
+        padding: 0 10px;
         .oper {
           display: none !important;
         }

+ 35 - 6
src/components/audio/index.vue

@@ -9,8 +9,8 @@
       <div class="circle"></div>
       <i class="iconfont iconbs_stop" :class="{ iconbs_play: myPlayTemp }"></i>
     </div>
-    <template v-if="showTime">
-      <div class="audio-name">东澳海景介绍.mp3</div>
+    <div v-if="showTime" class="namecon">
+      <div class="audio-name">{{name}}</div>
       <div class="audio-right">
         <div class="audio-time">
           <span class="audio-length-current" ref="audioCurTime">00:00</span>
@@ -18,14 +18,14 @@
           <span class="audio-length-total" ref="duration">00:00</span>
         </div>
       </div>
-    </template>
+    </div>
   </div>
 </template>
  
 <script>
 export default {
   name: "myAudio",
-  props: ["myAudioUrl", "showTime", "idleft", "idright"],
+  props: ["myAudioUrl", "showTime","name", "idleft", "idright"],
   data() {
     return {
       audio: "",
@@ -35,6 +35,11 @@ export default {
   },
   mounted() {
     this.init();
+    this.$bus.on('toggleAudio',data=>{
+      if (this.myAudioUrl == data) {
+        this.myPlay()
+      }
+    })
   },
   methods: {
     loadCircle() {
@@ -103,7 +108,7 @@ export default {
       this.loadCircle();
       let self = this;
       audioElement.addEventListener("loadedmetadata", function () {
-        let duration2 = (audioElement.duration / 100)
+        let duration2 = (audioElement.duration / 60)
           .toFixed(2)
           .replace(".", ":");
         self.$refs.duration &&
@@ -188,17 +193,25 @@ export default {
 
 .audio-name {
   font-size: 14px;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+  flex: 2;
+  margin-right: 10px;
 }
 
 .audio-right {
-  width: 80%;
   height: 100%;
+  flex: 1;
+
 }
 
 .audio-time {
   .hang {
     display: inline-block;
     margin: 0 4px;
+    color: #000;
+    font-size: 12px;
   }
 }
 
@@ -219,6 +232,7 @@ export default {
   position: relative;
   width: @raduiW;
   height: @raduiW;
+  min-width: @raduiW;
   background: #1fe4dc;
   border-radius: 50%;
   cursor: pointer;
@@ -229,6 +243,7 @@ export default {
     bottom: unset;
     transform: translate(-50%, -50%);
     font-size: @iconSize;
+    color: #202020;
   }
 }
 
@@ -258,5 +273,19 @@ export default {
   height: @rW;
   background: white;
   border-radius: 50%;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  bottom: unset;
+  right: unset;
+}
+
+.namecon{
+  margin-left: 20px;
+  display: flex;
+  width: 100%;
+  justify-content: space-between;
+  align-items: center;
 }
 </style>

+ 1 - 1
src/components/preview/index.vue

@@ -2,7 +2,7 @@
     <popup v-if="show">
       <div class="ui-message ui-message-confirm" style="width: 1280px">
         <div class="ui-message-header">
-          <span>{{name}}</span>
+          <span>{{name||'无标题'}}</span>
           <button class="ui-button submit ui-button-rect" @click="openBlank">新窗口打开</button>
           <span @click="$emit('close')">
             <i class="iconfont icon_close"></i>

+ 43 - 47
src/components/select.vue

@@ -17,19 +17,19 @@
 
     <template>
       <div class="scene-layer">
-        <tabList :list='tablist' :cls="'w-menu'" @clickItem="item=>{taboneActive = item}" :hiddenHover="true" :active="taboneActive" :id="'selct11'" :subId="'selct111'">
+        <tabList :list="info.catalogRoot" :cls="'w-menu'" @clickItem="item=>{taboneActive = item}" :hiddenHover="true" :active="taboneActive" :id="'selct11'" :subId="'selct111'">
         </tabList>
-        <tabList  v-if="taboneActive.children.length > 0" :cls="'w-menu'" :hiddenHover="true" :list='taboneActive.children' @clickItem="item=>{tabtowActive = item}"
-           :active="tabtowActive" :id="'subselct111'" :subId="'subselct111'">
+        <tabList v-if="childTab.length > 1" :list="childTab" :cls="'w-menu'" :hiddenHover="true" @clickItem="item=>{tabtowActive = item}"
+           :active="tabtowActive" :id="'subselct11'" :subId="'subselct111'">
         </tabList>
        
         <div>
-          <div class="pano-con">
+          <div class="pano-con"  v-if="scenes.length > 0">
             <ul>
               <li
-                v-for="(item, i) in list"
+                v-for="(item, i) in scenes"
                 @click="select = item"
-                :class="{ 'li-active': select == item }"
+                :class="{ 'li-active': select.sceneCode == item.sceneCode }"
                 :key="i"
               >
                 <div class="typeli">
@@ -72,7 +72,7 @@ components: {tabList},
       default() {
         return {};
       },
-      type: Object,
+      type: Object | String,
     },
     title: {
       default: "",
@@ -81,54 +81,49 @@ components: {tabList},
   },
   watch: {
     taboneActive: {
-      deep: true,
-      handler: function (newVal) {
-        if (newVal.children.length>0) {
-          this.tabtowActive = newVal.children[0]
-        }
-        if (this.tabtowActive) {
-          this.tabtowActive =
-            newVal.children.find((item) => {
-              return item.id == this.tabtowActive.id;
-            }) || "";
+      immediate:true,
+      deep:true,
+      handler: function (newVal,oldVal) {
+        
+        if (!newVal.id) {
+          this.taboneActive = this.info.catalogRoot[0]
         }
-        if (newVal.id) {
-          this.$emit("catalog", {
-            level:1,
-            data:newVal
-          });
-          if (newVal.children.length<=0) {
-            this.getTabSceneList(newVal.id)
-          }
+
+        let temp = []
+        newVal.children && newVal.children.forEach(item=>{
+          this.info.catalogs.forEach(sub=>{
+            if (item==sub.id) {
+              temp.push(sub)
+            }
+          })
+        })
+
+        this.childTab = temp
+
+        if (this.childTab.length == 1 || newVal!=oldVal) {
+          this.tabtowActive = this.childTab[0]
         }
-      }
-    },
-    tabtowActive: {
-      deep: true,
-      handler: function (newVal) {
-          this.$emit("catalog", {
-            level:2,
-            data:newVal
-          });
-          if (newVal) {
-            this.getTabSceneList(newVal.id)
-          }
       },
     },
-    tablist: {
-      deep: true,
-      immediate: true,
+    tabtowActive: {
+      immediate:true,
       handler: function (newVal) {
-        if (this.loadList) {
-          this.taboneActive = newVal[0] || { children: [] };
-          this.loadList = false
+        if (!newVal) {
+          this.tabtowActive = this.childTab[0]
+        } else{
+          this.$emit("catalog",newVal);
+          this.scenes = this.info.scenes.filter(item=>{
+            return newVal.id == item.category
+          })
         }
-      },
+      }
     }
   },
   computed: {
     ...mapGetters({
-      tablist:'tablist'
+      tablist:'tablist',
+      info: "info",
+      backupInfo: "backupInfo"
     }),
     disable() {
       return !this.select;
@@ -140,8 +135,9 @@ components: {tabList},
       tabtowActive:'',
       select:{...this.selected},
       list:[],
-      key: "",
-      loadList:true
+      childTab:[],
+      scenes:[],
+      key: ""
     };
   },
 

+ 1 - 1
src/components/shared/message/LoginTips.vue

@@ -46,7 +46,7 @@ export default {
             tips: "",
             content: "",
             okText: "确定",
-            noText: "放弃",
+            noText: "取消",
             okLink: null,
             noLink: null,
             ok: null,

+ 5 - 0
src/components/shared/uploads/Upload.vue

@@ -59,6 +59,11 @@ export default {
             if (this.limit > 0) {
                 if (!fileInfo.checkSizeLimitFree(this.file.size, this.limit)) {
                     e.target.value = "";
+                    if (this.limitFailStr) {
+                        return this.$alert({
+                            content:`“${this.file.name}”` + this.limitFailStr
+                        });
+                    }
                     return this.$alert({
                         content:`文件大小不能超过${this.limit}MB`,
                     });

+ 13 - 5
src/components/shared/uploads/UploadMultiple.vue

@@ -17,6 +17,8 @@ export default {
     mediaType: String,
     acceptType: String,
     failString: String,
+    limitFailStr:String
+
   },
   computed: {
     accept() {
@@ -43,17 +45,13 @@ export default {
 
       this.files = e.target.files;
 
-      // if(this.name === this.file.name){
-      //      e.target.value = "";
-      //      return
-      // }
 
       this.files.forEach((item) => {
         if (!fileInfo.checkMediaMime(this.mediaType, item.name)) {
           e.target.value = "";
           if (this.failString) {
             return this.$alert({
-              content: this.failString,
+              content: `“${item.name}”` + this.failString,
             });
           }
           return this.$alert({
@@ -63,12 +61,22 @@ export default {
         if (this.limit > 0) {
           if (!fileInfo.checkSizeLimitFree(item.size, this.limit)) {
             e.target.value = "";
+            if (this.limitFailStr) {
+                return this.$alert({
+                    content:`“${item.name}”` + this.limitFailStr
+                });
+            }
             return this.$alert({
               content: `文件大小不能超过${this.limit}MB`,
             });
           }
         } else if (!fileInfo.checkSizeLimit(this.mediaType, item.size)) {
           e.target.value = "";
+          if (this.limitFailStr) {
+              return this.$alert({
+                  content:`“${item.name}”` + this.limitFailStr
+              });
+          }
           return this.$alert({
             content: `上传文件太大,不能超过${
               fileInfo.mediaMaxSize[this.mediaType]

+ 17 - 8
src/components/tableSelect.vue

@@ -18,7 +18,7 @@
       <table class="list">
         <tr>
           <th>
-            <div class="checkbox">
+            <div class="checkbox" v-if="!hideAll">
               <input
                 type="checkbox"
                 v-model="allSelect"
@@ -120,6 +120,10 @@ props:{
   },
   primaryKey: {
     default:'id'
+  },
+  hideAll:{
+    type:Boolean,
+    default:false
   }
 },
   components:{
@@ -127,8 +131,7 @@ props:{
     vAudio
   },
   watch:{
-    select(newVal){
-      console.log(newVal);
+    select(){
     }
   },
   computed:{
@@ -162,12 +165,18 @@ props:{
       })
     },
     selectItem(item, isSelect) {
-      let index = this.select.findIndex(i => i[this.primaryKey] === item[this.primaryKey])
-      if (isSelect) {
-        !~index && this.select.push(item)
-      } else {
-        ~index && this.select.splice(index, 1)
+      if (this.hideAll) {
+        this.select = [item]
       }
+      else{
+        let index = this.select.findIndex(i => i[this.primaryKey] === item[this.primaryKey])
+        if (isSelect) {
+          !~index && this.select.push(item)
+        } else {
+          ~index && this.select.splice(index, 1)
+        }
+      }
+
     },
     
   },

+ 9 - 2
src/components/tablist/index.vue

@@ -7,9 +7,11 @@
           <i class="iconfont icon_plus"></i>
       </span>
     </template>
-    <div class="menu sub-menu" :class="cls" :id="id">
+    <div class="menu sub-menu" :class="(!isShowScroll&&!deviation?'sm-active':'') + ' ' + `${cls}`" :id="id">
+
       <ul class="mytablist" :id="subId" :style="{ left: oneLeft + 'px' }">
         <li
+          :title="item.name"
           v-for="(item, i) in list"
           :class="{ active: item.id == active.id,hidden:hiddenHover }"
           @click="$emit('clickItem',item)"
@@ -82,7 +84,7 @@ export default {
     },
     moveSlide(type) {
       if (type == 'back') {
-        if (this.menuWidth - this.oneLeft*2 > this.oneWidth) {
+        if ((this.menuWidth - this.oneLeft) > this.oneWidth) {
           return
         }
       }
@@ -186,5 +188,10 @@ export default {
       // }
     }
   }
+
+  .sm-active{
+    max-width: 100%;
+
+  }
 }
 </style>

+ 1 - 1
src/core/utils.js

@@ -41,7 +41,7 @@ export default class Utils {
   }
   getDataURL (canvas, type, width, height) {
     let cas = this.scaleCanvas(canvas, width, height);
-    return cas.toDataURL(type,0.5);
+    return cas.toDataURL(type,1.0);
   }
 
   setInitAngleImg(mycanvas){

+ 160 - 114
src/framework/Head.vue

@@ -1,151 +1,198 @@
 <template>
   <header class="app-head" app-border dir-bottom>
-    <span class="app-head-title">{{info.name}}</span>
-    <div class="app-head-save app-head-view" @click="onSave" :class="{disable:!canLoad}">
+    <span class="app-head-title">{{ info.name }}</span>
+    <div
+      class="app-head-save app-head-view"
+      @click="onSave"
+      :class="{ disable: !canLoad }"
+    >
       <i class="iconfont icon_save"></i>
       保存
     </div>
-    <div class="app-head-save" @click="onView" :class="{disable:!canLoad}">
+    <div class="app-head-save" @click="onView" :class="{ disable: !canLoad }">
       <i class="iconfont icon_eye"></i>
       预览
     </div>
-    <preview :name="info.name" :show="showPreview" :ifr="`./show.html?id=${firstScene&&firstScene.workId}`" @close="showPreview=false"/>
+    <preview
+      v-if="info"
+      :name="info.name"
+      :show="showPreview"
+      :ifr="`./show.html?id=${info.id}&vr=${info.firstScene?info.firstScene.sceneCode:info.scenes[0].sceneCode}`"
+      @close="showPreview = false"
+    />
   </header>
 </template>
 <script>
-import { saveWorks,getPanoInfo,getAllVrList,getTabList,getIndex } from "@/api";
+import { saveWorks, getPanoInfo, checkLogin } from "@/api";
 import { mapGetters } from "vuex";
 // import config from '@/config'
-import preview from '@/components/preview'
-
+import preview from "@/components/preview";
 
 export default {
   name: "app-head",
-  data(){
+  data() {
     return {
-      firstScene:'',
-      showPreview:false,
-      canLoad:false
-    }
+      showPreview: false,
+      canLoad: false,
+    };
   },
 
-  components:{preview},
-
-  mounted(){
-    this.canLoad = true
-    this.getInfo()
-    this.getIndex()
-    this.getAllVrList()
-
-    this.$bus.on('undateAllVrList',islongpolling=>{
-      this.getAllVrList(islongpolling)
-    })
-    
-    this.$bus.on('setInitScene',islongpolling=>{
-      this.getIndex(islongpolling)
-    })
-
-    this.$bus.on('initScene',(data)=>{
-      this.firstScene = data
-    })
+  components: { preview },
 
-    this.$bus.on('refresh',()=>{
-      this.getTabList()
-    })
-    this.getTabList()
+  mounted() {
+    this.$bus.on('canLoad',(data)=>{
+      this.canLoad = data
+      if (data) {
+        this.getInfo()
+      }
+    }) 
   },
   computed: {
     ...mapGetters({
-      allVrlist:'allVrlist',
-      info:'info',
-      isShow:'isShow'
-    })
+      info: "info",
+      isShow: "isShow",
+    }),
   },
   methods: {
-    getTabList(){
-      getTabList({},data=>{
-        this.$store.commit("SetTabList", data.data);
-      })
-    },
-    getAllVrList(islongpolling=null){
-       getAllVrList({
-        islongpolling
-      },async data=>{
-        this.$store.commit("SetAllVrlist", data.data);
-      })
+    checkParams() {
+      if (!this.info.name && !this.info.icon && !this.info.description) {
+        this.$alert({
+          content: "您还未创建任何内容哦",
+          ok: () => {
+            this.$router.push({ path: "/base" });
+          },
+        });
+        return false;
+      }
+      // if (this.info.scenes.length <= 0 && this.isShow) {
+      //   this.$alert({
+      //     content: "至少添加一个场景才保存/预览,请前往“场景导航”添加",
+      //     forceOK: true,
+      //     ok: () => {
+      //       this.$router.push({ path: "/information" });
+      //     },
+      //   });
+      //   return false;
+      // }
+      return true;
     },
-    checkParams(){
-       if (!this.info.name||!this.info.icon) {
-          this.$alert({
-            content: "请补全必填信息", 
-            ok:()=>{
-              this.$router.push({path:'/base'})
-            }})
-          return false
-        }
-       if (this.allVrlist.length<=0&&this.isShow) {
-          this.$alert({
-            content:'至少添加一个场景才可预览,请前往“场景导航”添加',
-            forceOK:true,
-            ok:()=>{
-              this.$router.push({path:'/information'})
-            }})
-          return false
+    onView() {
+      if (!this.checkParams()) {
+        return;
+      }
+      this.fixData()
+      saveWorks(
+        {
+          password: this.info.password,
+          someData: { ...this.info, status: 1 },
+        },
+        () => {
+          this.$tips({ content: "保存成功", icon: "ok" });
+          this.getInfo();
+          this.$store.commit("UpdateIsShowState", true);
+          setTimeout(() => {
+            if (this.info.scenes.length <= 0 && this.isShow) {
+              return this.$alert({
+                content: "至少添加一个场景才可预览,请前往“场景导航”添加",
+              });
+            }
+            this.showPreview = true;
+          }, 500);
         }
-      return true
+      );
     },
-    onView(){
 
-      if (!this.checkParams()) {
-        return
-      }
-      saveWorks({
-        ...this.info,
-        status:1
-      },()=>{
-        this.$tips({content:'保存成功',icon:'ok'})
-        this.$store.commit('UpdateIsShowState', true)
-        this.getTabList()
-        setTimeout(() => {
-          if (!this.firstScene&&this.isShow) {
-            return this.$alert({
-              content: "设置初始场景才可预览,请前往“场景导航”设置",
-            })
+    fixData() {
+      let tmp = [];
+      this.info.scenes.forEach((item) => {
+        this.info.catalogs.forEach((sub) => {
+          if (item.category == sub.id) {
+            tmp.push(sub);
+          }
+        });
+      });
+      tmp = this.$unique(tmp)
+      this.info.catalogs = tmp;
+      let rootmp = [];
+      tmp.forEach((item) => {
+        this.info.catalogRoot.forEach((sub) => {
+          sub.children = this.$unique(sub.children)
+          if (sub.children.indexOf(item.id) > -1) {
+            rootmp.push(sub);
           }
-          this.showPreview = true
-        }, 500);
-      })
+        });
+      });
+      rootmp = this.$unique(rootmp)
+
+      this.info.catalogRoot = rootmp.map((item,i) => {
+        let temp = [];
+        item.children = this.$unique(item.children)
+        item.children.forEach((sub) => {
+          tmp.forEach((jj) => {
+            if (jj.id == sub) {
+              temp.push(sub);
+            }
+          });
+        });
+        return {
+          ...item,
+          children: temp,
+        };
+      });
+      this.info.catalogs = tmp
+
+      let cid = 'c_'+this.$randomWord(true,8,8)
+
+      if (this.info.catalogRoot.length <= 0) {
+        this.info.catalogRoot.push({
+          id: 'r_'+this.$randomWord(true,8,8),
+          name: "全部场景",
+          children:[cid]
+        });
+      }
+
+      if (this.info.catalogs.length <= 0) {
+        this.info.catalogs.push({
+          id: cid,
+          name: "默认二级分组",
+        });
+      }
+
+      if (this.info.firstScene) {
+        this.info.firstScene = this.info.scenes.find(item=>item.sceneCode==this.info.firstScene.sceneCode)
+      }
+
+      this.$store.commit("SetInfo", this.info);
     },
-    onSave() {
-        // if (!this.checkParams()) {
-        //   return
-        // }
-        saveWorks({
-          ...this.info,
-          status:1
-        },()=>{
-          this.$tips({content:'保存成功',icon:'ok'})
-          this.getTabList()
-          this.$store.commit('UpdateIsShowState', true)
-        },()=>{
 
-        })
+    onSave() {
+      if (!this.checkParams()) {
+        return;
+      }
+      this.fixData();
+      saveWorks(
+        {
+          password: this.info.password,
+          someData: { ...this.info, status: 1 },
+        },
+        () => {
+          this.$tips({ content: "保存成功", icon: "ok" });
+          this.getInfo();
+          this.$store.commit("UpdateIsShowState", true);
+        },
+        () => {}
+      );
     },
     getInfo() {
-      getPanoInfo(
-        "",
-        (data) => {
-          this.$store.commit("SetInfo", data.data);
+      checkLogin().then((res) => {
+        if (res.code == 0) {
+          getPanoInfo("", (data) => {
+            this.$store.commit("SetInfo", data);
+          });
         }
-      );
+      });
     },
-    getIndex(islongpolling=null){
-      getIndex({islongpolling},data=>{
-        this.$bus.emit('initScene',data.data)
-        this.$store.commit("SetInitScene", data.data);
-      })
-    }
-  }
+  },
 };
 </script>
 <style lang="less">
@@ -188,8 +235,7 @@ export default {
   }
 }
 
-.app-head-view{
+.app-head-view {
   right: 100px;
-
 }
 </style>

+ 38 - 73
src/framework/Toolbar.vue

@@ -6,15 +6,15 @@
     dir-top
   >
     <div class="clip-center">
-      <tabList :list='tablist' @clickItem="item=>{taboneActive = item}" :hiddenHover="true" :active="taboneActive" :id="'rand11'" :subId="'rand111'">
+      <tabList :list="info.catalogRoot" @clickItem="item=>{taboneActive = item}" :hiddenHover="true" :active="taboneActive" :id="'rand11'" :subId="'rand111'">
       </tabList>
-       <tabList  v-if="taboneActive.children.length > 0"  :hiddenHover="true" :list='taboneActive.children' @clickItem="item=>{tabtowActive = item}"
-           :active="tabtowActive" :id="'subrand111'" :subId="'subrand111'">
+       <tabList v-if="childTab.length > 1" :list="childTab" :hiddenHover="true" @clickItem="item=>{tabtowActive = item}"
+           :active="tabtowActive" :id="'subrand11'" :subId="'subrand111'">
         </tabList>
       <div class="pano-con clip-scroller">
-        <ul ref="clip" v-if="list.length>0">
+        <ul ref="clip" v-if="scenes.length>0">
           <li
-            v-for="(item, i) in list"
+            v-for="(item, i) in scenes"
             @click="activeItem = item"
             :class="{ 'li-active': item.sceneCode == activeItem.sceneCode }"
             :key="i"
@@ -26,7 +26,7 @@
               ></i>
             </div>
             <div class="img">
-              <img :src="item.icon" alt="" />
+              <img :src="item.icon+`?${Math.random()}`" alt="" />
             </div>
             <div class="ui-title">
               <span>{{ item.sceneTitle }}</span>
@@ -41,7 +41,6 @@
   </div>
 </template>
 <script>
-import { getTabSceneList } from "@/api";
 import { mapGetters } from "vuex";
 import tabList from "@/components/tablist";
 
@@ -57,72 +56,51 @@ export default {
       activeItem: "",
       canEdit: true,
       hasCheck: false,
-      loadList:true
+      loadList:true,
+      childTab:[],
+      scenes:[],
     };
   },
   computed: {
     ...mapGetters({
-      vrlist: "vrlist",
-      tablist:'tablist'
-    }),
-    list(){
-      return this.vrlist.filter(item=>item.type!='4dkk')
-    }
+      info: "info",
+      backupInfo: "backupInfo"
+    })
   },
   methods: {
-    getTabSceneList(catalogId=null){
-      if (!catalogId) {
-        catalogId = this.taboneActive.children.length<=0 ? this.taboneActive.id : this.tabtowActive.id
-      }
-      getTabSceneList({catalogId},(data)=>{
-          this.$store.commit("SetVrList", data.data||[]);
-      })
-    },
-    handleType(item) {
-      if (item.id == "house") {
-        return this.$alert({
-          content: "请在VR模型设置",
-        });
-      }
-      this.type = item.id;
-    }
+    
   },
   created() {},
   watch: {
     taboneActive: {
-      deep: true,
-      handler: function (newVal) {
-        if (newVal.children.length>0) {
-          this.tabtowActive = newVal.children[0]
-        }
-        if (this.tabtowActive) {
-          this.tabtowActive =
-            newVal.children.find((item) => {
-              return item.id == this.tabtowActive.id;
-            }) || "";
-        }
-        if (newVal.id) {
-          this.$emit("catalog", {
-            level:1,
-            data:newVal
-          });
-          if (newVal.children.length<=0) {
-            this.getTabSceneList(newVal.id)
-          }
+      deep:true,
+      handler: function (newVal,oldVal) {
+        let temp = []
+        newVal.children && newVal.children.forEach(item=>{
+          this.info.catalogs.forEach(sub=>{
+            if (item==sub.id) {
+              temp.push(sub)
+            }
+          })
+        })
+        this.childTab = temp
+        if (this.childTab.length == 1 || newVal!=oldVal) {
+          this.tabtowActive = this.childTab[0]
         }
-      }
+      },
     },
     tabtowActive: {
-      deep: true,
+      immediate:true,
       handler: function (newVal) {
-          this.$emit("catalog", {
-            level:2,
-            data:newVal
-          });
-          if (newVal) {
-            this.getTabSceneList(newVal.id)
-          }
-      },
+        if (!newVal) {
+          this.tabtowActive = this.childTab[0]
+        } else{
+          this.scenes = this.info.scenes.filter(item=>{
+            return newVal.id == item.category && item.type!='4dkk'
+          })
+          this.activeItem = this.scenes[0]
+        }
+      }
     },
     '$route.meta.loadScene':{
       deep: true,
@@ -130,27 +108,14 @@ export default {
       handler: function (newVal) {
         if (newVal) {
           if (this.loadList) {
-              this.taboneActive = this.tablist[0] || { children: [] };
+              this.taboneActive = this.info.catalogRoot[0] || { children: [] };
               this.loadList = false
           }
         }
       }
     },
 
-    list: {
-      immediate: true,
-      handler: function(newVal) {
-        this.$nextTick(() => {
-          if (!frame) {
-            return;
-          }
-          frame.update();
-        });
-        this.activeItem = newVal[0]||''
-      },
-    },
     activeItem: {
-      immediate: true,
       handler: function(newVal) {
         this.$bus.emit("currentPcode", newVal);
         this.$store.commit("SetActiveItem", newVal || "");

+ 20 - 22
src/framework/core/index.vue

@@ -14,6 +14,7 @@
 import * as krfn from "@/core/index.js";
 import { uploadCover,savePosition,saveInitScreen } from "@/api";
 import { $waiting } from '@/components/shared/loading'
+import { mapGetters } from "vuex";
 
 import Snapshot from "@/components/Snapshot";
 import config from "@/config";
@@ -29,6 +30,10 @@ export default {
     };
   },
   computed: {
+    ...mapGetters({
+      info: "info",
+      backupInfo: "backupInfo"
+    }),
     showSnapshot() {
       return this.$route.name == "screen";
     },
@@ -47,27 +52,15 @@ export default {
         { file: data.url, filename: "initCover.jpg" },
         res => {
           if (res.code==0) {
-            saveInitScreen({
-              icon:res.data,
-              id: this.activeItem.id
-            },()=>{
-              this.$bus.emit("initView", res.data);
-              this.$bus.emit("setListThumb",{
-                icon:res.data,
-                initVisual: {
-                  hlookat: data.hlookat,
-                  vlookat: data.vlookat
-                }
-              });
-              this.$bus.emit('toggleFlash',false)
-              this.$tips({ content: "设置成功",icon:'ok' });
-              savePosition({
-                  id:this.activeItem.id,
-                  hlookat: data.hlookat,
-                  vlookat: data.vlookat
-              })
-            })
-            
+            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.$tips({ content: "设置成功",icon:'ok' });
+            this.$store.commit("SetInfo", this.info);
           }
         });
     },
@@ -84,6 +77,11 @@ export default {
     },
     activeItem:{
       handler(newVal) {
+        if (newVal) {
+          this.$nextTick(()=>{
+            this.$bus.emit("initView", newVal.icon);
+          })
+        }
         $('#pano').empty();
         window.vrInitFn = ()=>{
             $waiting.hide()
@@ -93,7 +91,7 @@ export default {
         }
         window.vrViewFn = ()=>{
           try {
-            let tmp = JSON.parse(newVal.initVisual)
+            let tmp = newVal.initVisual
             var krpano = document.getElementById('krpanoSWFObject');
             krpano.set('view.vlookat',tmp.vlookat);
             krpano.set('view.hlookat',tmp.hlookat);

+ 69 - 26
src/framework/show/index.vue

@@ -5,14 +5,14 @@
       :src="`https://test.4dkankan.com/spc.html?m=${activeItem.sceneCode}`" frameborder="0"></iframe>
       <div v-show="activeItem.type!='4dkk'" id="pano"></div>
 
-      <div class="pano-logo" v-if="showInfo.logo && showInfo.isLogo">
-        <img :src="showInfo.logo" alt="" />
+      <div class="pano-logo" v-if="showInfo.isLogo">
+        <img :src="showInfo.logo||require('@/assets/images/icons/img_logo.png')" alt="" />
       </div>
 
       <div
         class="oper-tips"
         :class="{ hidetips: !showTips }"
-        v-if="showInfo.isRemind && showInfo.remindTime && !localRemind"
+        v-if="localRemind"
       >
         <img
           :src="
@@ -42,7 +42,7 @@
         @close="showPreview = false"
       />
 
-      <ul class="aside">
+      <ul class="aside" v-if="activeItem.type!='4dkk'">
         <li v-for="(item, i) in aside" :key="i">
           <span @click="handleItem(item)">
             <i class="iconfont" :class="item.icon"></i>
@@ -50,18 +50,21 @@
         </li>
       </ul>
     </template>
-    <div class="hasDel" v-else>
+    <template v-else>
+      <div class="hasDel" v-if="loadFinish">
       <div>
         <img :src="$noresult" alt="">
         <p>作品已被删除</p>
       </div>
     </div>
+
+    </template>
   </div>
 </template>
 
 <script>
 import * as krfn from "@/core/index.js";
-import { getWebWorksInfo, checkPassword } from "@/api";
+import { getPanoInfo, checkPassword,checkWork } from "@/api";
 import password from "./popup/password";
 import preview from "./popup/preview";
 
@@ -87,8 +90,10 @@ export default {
   data() {
     return {
       showPreview: false,
+      isFullscreen:false,
       showTips: true,
       canLoad: false,
+      loadFinish:false,
       showPassword: false,
       showIntro: false,
       localRemind: false,
@@ -103,10 +108,6 @@ export default {
           icon: "icontool_about",
         },
         {
-          id: "vr",
-          icon: "icontool_vr",
-        },
-        {
           id: "full",
           icon: "icontool_full",
         },
@@ -114,10 +115,39 @@ export default {
     };
   },
   methods: {
+    onFullScreen() {
+        let element = document.documentElement;
+        if (this.isFullscreen) {
+            if (document.exitFullscreen) {
+                document.exitFullscreen();
+            } else if (document.webkitCancelFullScreen) {
+                document.webkitCancelFullScreen();
+            } else if (document.mozCancelFullScreen) {
+                document.mozCancelFullScreen();
+            } else if (document.msExitFullscreen) {
+                document.msExitFullscreen();
+            }
+        } else {
+            if (element.requestFullscreen) {
+                element.requestFullscreen();
+            } else if (element.webkitRequestFullScreen) {
+                element.webkitRequestFullScreen();
+            } else if (element.mozRequestFullScreen) {
+                element.mozRequestFullScreen();
+            } else if (element.msRequestFullscreen) {
+                element.msRequestFullscreen();
+            }
+        }
+          // 改变当前全屏状态
+        this.isFullscreen = !this.isFullscreen;
+      },
     handleItem(data) {
       if (data.id == "about") {
         this.showIntro = true;
       }
+      if (data.id == "full") {
+        this.onFullScreen()
+      }
     },
     handlePassword(data) {
       checkPassword(
@@ -128,9 +158,7 @@ export default {
           if (res.code == 0) {
             this.showPassword = false;
             this.canLoad = true;
-          } else {
-            return this.$alert({ content: "密码错误" });
-          }
+          } 
         }
       );
     },
@@ -142,10 +170,20 @@ export default {
     },
 
     getSceneInfo() {
-      getWebWorksInfo({}, (data) => {
-        this.$store.commit("SetShowInfo", data.data);
-      });
-    },
+      checkWork("",data=>{
+        if (data.data) {
+          getPanoInfo(
+            "",
+            (data) => {
+              this.loadFinish = true
+              this.$store.commit("SetShowInfo", data);
+            }
+          );
+        } else{
+          this.loadFinish = true
+        }
+      })
+    }
   },
   watch: {
     currentHotspot: {
@@ -176,14 +214,19 @@ export default {
       immediate: true,
       handler: function (newVal) {
         if (newVal) {
-          if (localStorage.getItem("localRemind") == 1) {
+          let locoR = "localRemind"+newVal.id
+          if (!newVal.description) {
+            this.aside.shift()
+          }
+          if (newVal.isRemind==1) {
+            this.localRemind = localStorage.getItem(locoR) == 1 ? false : true
+            localStorage.setItem(locoR, 1);
+          }
+          else{
             this.localRemind = true;
-          } else {
-            if (newVal.isRemind) {
-              localStorage.setItem("localRemind", newVal.isRemind);
-            }
+            localStorage.setItem(locoR, 0);
           }
-          newVal.isPassword ? (this.showPassword = true) : this.startLoad();
+          newVal.password ? (this.showPassword = true) : this.startLoad();
         }
       },
     },
@@ -196,10 +239,10 @@ export default {
         };
         window.vrViewFn = () => {
           try {
-            let tmp = JSON.parse(newVal.initVisual);
+            let tmp = newVal.initVisual||{};
             var krpano = document.getElementById("krpanoSWFObject");
-            krpano.set("view.vlookat", tmp.vlookat);
-            krpano.set("view.hlookat", tmp.hlookat);
+            krpano.set("view.vlookat", tmp.vlookat||0);
+            krpano.set("view.hlookat", tmp.hlookat||0);
             krpano.set("autorotate.enabled", Boolean(this.showInfo.isAuto));
           } catch (error) {
             error;

+ 118 - 75
src/framework/show/list.vue

@@ -1,26 +1,34 @@
 <template>
   <div class="list">
      <div class="l-con" :class="showList?'active':''">
-      <ul class="pic-list" v-if="vrlist.length>0">
-        <li @click="$emit('select',item)" v-for="(item,i) in vrlist" :key="i">
-          <div :class="{active:selected.sceneCode==item.sceneCode}">
-            <img :src="item.icon" alt="" />
-            <i class="iconfont iconscene_map_3d" :class="{'iconjump':item.type!=='4dkk'}"></i>
-            <span>{{item.sceneTitle}}</span>
-          </div>
-        </li>
-      </ul>
+       <div class="clip-scroller">
+        <ul class="pic-list" v-if="scenes.length>0">
+          <li @click="handleVR(item)" v-for="(item,i) in scenes" :key="i">
+            <div :class="{active:selected.sceneCode==item.sceneCode}">
+              <img :src="item.icon+`?${Math.random()}`" alt="" />
+              <i class="iconfont iconscene_map_3d" :class="{'iconjump':item.type!=='4dkk'}"></i>
+              <span>{{item.sceneTitle}}</span>
+            </div>
+          </li>
+        </ul>
+       </div>
       
-      <ul class="tap" v-if="taboneActive.children.length>0">
-        <li  @click="tabtowActive = item" v-for="(item,i) in taboneActive.children" :key="i">
-          <span :class="{active:item.id == tabtowActive.id}" class="btn rect">{{item.name}}</span>
-        </li>
-      </ul>
+      <div class="clip-scroller" v-if="childTab.length > 1">
+        <ul class="tap">
+          <li @click="tabtowActive = item" v-for="(item,i) in childTab" :key="i">
+            <span :title="item.name" :class="{active:item.id == tabtowActive.id}" class="btn rect">{{item.name}}</span>
+          </li>
+        </ul>
+      </div>
+
+      <div class="clip-scroller" v-if="showInfo.catalogRoot.length > 0 && showInfo.catalogs.length>1">
        <ul class="tap">
-        <li  @click="taboneActive = item" v-for="(item,i) in tablist" :key="i">
-          <span :class="{active:item.id == taboneActive.id}" class="btn rect">{{item.name}}</span>
+        <li @click="taboneActive = item" v-for="(item,i) in showInfo.catalogRoot" :key="i">
+          <span :title="item.name" :class="{active:item.id == taboneActive.id}" class="btn rect">{{item.name}}</span>
         </li>
       </ul>
+      </div>
+
     </div>
     <div class="btn dl" @click="showList=!showList">
       <i class="iconfont " :class="showList?'iconnav_scene_down':'iconnav_scene_up'"></i>场景导览</div>
@@ -28,8 +36,10 @@
 </template>
 
 <script>
-import { getWebTabList,getWebTabSceneList,getWebIndex } from "@/api";
 import { mapGetters } from "vuex";
+import config from "@/config";
+
+let $scroll = null;
 
 export default {
   props:['select'],
@@ -38,88 +48,103 @@ export default {
     return{
       taboneActive:{children:[]},
       tabtowActive:'',
+      childTab:[],
+      scenes:[],
       showList:true,
-      firstScene:''
+      loadFirst: true,
+      menuWidth:0,
+      sceneNum: config.sceneNum
     }
   },
   computed: {
       ...mapGetters({
-        tablist:'tablist',
-        vrlist:'vrlist'
+        showInfo: "showInfo"
       }),
       selected(){
         return {...this.select}
       }
   },
+
   methods:{
-    getTabSceneList(catalogId=null){
-      if (!catalogId) {
-        catalogId = this.taboneActive.children.length<=0 ? this.taboneActive.id : this.tabtowActive.id
-      }
-      getWebTabSceneList({catalogId},(data)=>{
-          this.$store.commit("SetVrList", data.data||[]);
-      })
-    },
-    getWebTabList(){
-      getWebTabList({},data=>{
-        this.$store.commit("SetTabList", data.data)
-        if (!this.firstScene) {
-          getWebIndex({},data=>{
-            this.firstScene = data.data
-          })
-        }
-      })
+    handleVR(item){
+      history.replaceState(null, null, "".concat(window.location.pathname, "?").concat(`id=${this.showInfo.id}&vr=${item.sceneCode}`));
+      this.sceneNum = item.sceneCode
     }
   },
-  watch:{
-    taboneActive:{
-      handler:function (newVal) {
-        if (newVal.children.length>0) {
-          this.tabtowActive=''
-          this.tabtowActive = newVal.children[0]
-          return
-        }
-        if (newVal.id) {
-          this.getTabSceneList(newVal.id)
-        }
+
+  mounted(){
+    this.$nextTick(() => {
+      if ($scroll == null) {
+        let eles = $(".clip-scroller")
+        Array.from(eles).forEach(item=>{
+          let frame = new PerfectScrollbar(item, {
+            useBothWheelAxes: true,
+            suppressScrollY: true,
+            wheelSpeed: 0.8,
+          });
+          $(item).data("scrollbar", frame);
+        })
       }
-    },
-    tabtowActive:{
-      handler:function (newVal) {
-        if (newVal.id) {
-          this.getTabSceneList(newVal.id)
+    });
+  },
+  
+  watch:{
+    taboneActive: {
+      handler: function (newVal) {
+        let temp = []
+        newVal.children && newVal.children.forEach(item=>{
+          this.showInfo.catalogs.forEach(sub=>{
+            if (item==sub.id) {
+              temp.push(sub)
+            }
+          })
+        })
+        this.childTab = temp
+        if (!this.loadFirst) {
+            this.tabtowActive = ''
         }
-      }
+      },
     },
-    firstScene:{
+    tabtowActive: {
       deep:true,
-      handler:function (newVal) {
-          let id = newVal.parentId||newVal.catalogId
-          let tmp = this.tablist.find(item => item.id == id);
-          if (this.firstScene.parentId) {
-            this.tabtowActive =tmp.children.find(item => {
-              return item.id == this.firstScene.catalogId
-            });
-          }
-          this.taboneActive = tmp
+      handler: function (newVal) {
+        if (!newVal) {
+          this.tabtowActive = this.childTab[0]
+        } else{
+          this.scenes = this.showInfo.scenes.filter(item=>{
+            return newVal.id == item.category
+          })
+        }
       }
     },
-    vrlist:{
+
+    sceneNum:{
       deep:true,
+      immediate:true,
       handler:function (newVal) {
-        this.$emit('select', newVal[0])
+          let val = this.showInfo.scenes.find(item=>item.sceneCode==newVal)
+          let tmp = this.showInfo.catalogs.find(item=>item.id==val.category)
+          let rootTmp = this.showInfo.catalogRoot.find(item => {
+            return item.children.indexOf(tmp.id)>-1
+          });
+          this.taboneActive = rootTmp
+          this.tabtowActive = tmp
+
+        setTimeout(() => {
+          this.$emit('select',val)
+          this.loadFirst = false 
+        });
       }
     },
+   
     selected:{
       handler:function (newVal) {
+        this.handleVR(newVal)
         if (newVal.type == '4dkk') {
           this.showList = false
         }
       }
     }
-  },
-  mounted(){
-    this.getWebTabList()
   }
 }
 </script>
@@ -136,6 +161,11 @@ export default {
     border: 1px solid rgba(255, 255, 255, 0.2);
     opacity: 1;
     cursor: pointer;
+    word-break: keep-all;
+    max-width: 150px;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
     &.active{
       background: rgba(0, 0, 0, 0.3);
       border: 1px solid #1FE4DC;
@@ -182,12 +212,18 @@ export default {
     max-height: 0px;
     overflow: hidden;
     pointer-events: auto;
+    .clip-scroller{
+      position: relative;
+      background: rgba(0, 0, 0, 0.3);
+      margin-bottom: 2px;
+    }
     ul{
-      justify-content: center;
-      align-items: center;
-      display: flex;
+      display: inline-block;
+      white-space: nowrap;
+      position: relative;
       li{
         margin: 0 5px;
+        display: inline-block;
         >div{
           width: 72px;
           height: 72px;
@@ -228,16 +264,23 @@ export default {
     }
     .tap{
       padding: 12px 0;
-      background: rgba(0, 0, 0, 0.3);
-      margin-top: 2px;
     }
     .pic-list{
-      background: rgba(0, 0, 0, 0.3);
       padding: 12px 0;
       >li{
         cursor: pointer;
       }
     }
+
+    .onecls{
+      background: rgba(0, 0, 0, 0.3);
+      display: inline-block;
+      width: 100%;
+    }
+
+    .towcls{
+      background: rgba(0, 0, 0, 0.3);
+    }
     &.active{
       max-height: 200px;
     }

+ 3 - 3
src/framework/show/popup/password.vue

@@ -13,8 +13,8 @@
             <input
               @keyup.enter="emitname"
               class="ui-input"
-              type="text"
-              maxlength="15"
+              type="password"
+              maxlength="20"
               placeholder="请输入访问密码"
               v-model="key"
             />
@@ -23,7 +23,7 @@
         <div class="ma-line"></div>
         <div class="ui-message-footer">
           <div class="btn">
-            <button @click="emitname" :class="`ui-button ui-button-rect submit`" >
+            <button @click="emitname"  class="ui-button ui-button-rect submit" :class="{disable:!key}" >
               确定
             </button>
           </div>

+ 26 - 2
src/framework/show/popup/preview.vue

@@ -1,6 +1,7 @@
 <template>
     <popup v-if="show">
-      <div class="ui-message ui-message-confirm" style="width: 960px">
+      <div class="ui-message ui-message-confirm" 
+      style="width:`${item.hotspotType=='audio'?'960px':'500px'}`">
         <div class="ui-message-header">
           <span>{{item.hotspotTitle}}</span>
           <span @click="$emit('close')">
@@ -16,6 +17,11 @@
               <span>{{item.textarea}}</span>
             </div>
           </template>
+          <template v-else-if="item.hotspotType=='audio'">
+            <div class="v-audio">
+              <v-audio :showTime=true :name="item.audio.name" :idleft="`_${$randomWord(true,8,8)}`" :idright="`_${$randomWord(true,8,8)}`" :myAudioUrl="item.audio.ossPath"></v-audio>
+            </div>
+          </template>
           <video :poster="item.video.icon" v-else controls autoplay :src="item.video.ossPath"></video>
         </div>
       </div>
@@ -25,13 +31,15 @@
 <script>
 import Popup from "@/components/shared/popup";
 import imgview from "./imgview";
+import vAudio from '@/components/audio'
 
 
 export default {
   props:['show','item'],
   components:{
     Popup,
-    imgview
+    imgview,
+    vAudio
   },
   data(){
     let typeStr={
@@ -53,6 +61,9 @@ export default {
 <style lang="less" scoped>
 .ui-message-confirm{
   border-radius: 0;
+  top: unset;
+  left: unset;
+  transform: none;
   .icon_close{
     color: #909090;
   }
@@ -78,6 +89,19 @@ export default {
         color: #202020;
       }
     }
+
+    .v-audio{
+      margin: 20px 50px;
+      max-height: 540px;
+      overflow-y: auto;
+      padding: 20px 15px;
+      text-align: left;
+      border: 1px solid #909090;
+      >span{
+        font-size: 14px;
+        color: #202020;
+      }
+    }
     
   }
   .ui-message-footer{

+ 45 - 0
src/framework/showMobile/iframe.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="ifrcon">
+    <iframe ref="iframe" id="showifr" :src="url" frameborder="0" @load="onIframLoad"></iframe>
+  </div>
+</template>
+
+<script>
+export default {
+  props:['url'],
+  methods:{
+    onIframLoad(){
+      window.onmessage = e =>{
+        if (e.data.source != "4dage") {
+            return
+        }
+
+        if (e.data.event == "guide-rooms") {
+          this.$bus.emit('guideRoomsData',e.data.params)
+        }
+
+
+        if (e.data.event == "loaded") {
+          this.$bus.emit('sceneData',e.data.params)
+          this.$refs.iframe.contentWindow.postMessage({
+              source: "mingyuan",
+              event: 'guide-rooms'
+          },"*")
+        }
+
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.ifrcon{
+  width: 100%;
+  height: 100%;
+  >iframe{
+    width: 100%;
+    height: 100%;
+  }
+}
+</style>

+ 264 - 172
src/framework/showMobile/index.vue

@@ -1,267 +1,359 @@
 <template>
   <div class="panocon">
-    <div id="pano"></div>
+    <template v-if="showInfo&&showInfo.firstScene">
+      <v-ifr v-if="activeItem.type=='4dkk'" :url="`https://test.4dkankan.com/embed.html?from=mingyuan&m=${activeItem.sceneCode}`" />
+      <div v-show="activeItem.type!='4dkk'" id="pano"></div>
 
-    <div class="pano-logo" v-if="showInfo.logo&&showInfo.isLogo">
-      <img :src="showInfo.logo" alt="">
-    </div>
+      <div class="pano-logo" v-if="showInfo.isLogo">
+        <img :src="showInfo.logo||require('@/assets/images/icons/img_logo.png')" alt="" />
+      </div>
 
-    <div class="oper-tips" :class="{hidetips:!showTips}" v-if="showInfo.isRemind&&showInfo.remindTime">
-      <img :src="showInfo.pcIcon||require('@/assets/images/default/show/img_tipsmb_default.png')" alt="">
-    </div>
+      <ul class="aside" v-show="activeItem.type!='4dkk'">
+        <li v-for="(item, i) in aside" :key="i">
+          <span @click="handleItem(item)">
+            <i class="iconfont" :class="item.icon"></i>
+          </span>
+        </li>
+      </ul>
 
+      <list
+        v-if="canLoad"
+        @select="handleSelect"
+        :firstScene="firstScene"
+        :select="activeItem"
+      ></list>
 
-    <list v-if="canLoad" @select="handleSelect" :firstScene="firstScene" :select="activeItem"></list>
-    <password :bg="showInfo.icon" :show='showPassword' @submit="handlePassword" @close="showPassword=false" />
-    <popup :title="'简介'" :show='showIntro' @close="showIntro=false" >
-      <div slot="content" class="introcon">
-        {{showInfo.description}}
+      <div
+        class="oper-tips"
+        :class="{ hidetips: !showTips }"
+        v-if="localRemind"
+      >
+        <img
+          :src="
+            showInfo.pcIcon ||
+            require('@/assets/images/default/show/img_tipsmb_default.png')
+          "
+          alt=""
+        />
       </div>
-    </popup>
-    <imgview @close="showImage = false" v-if="showImage" :image="currentHotspot.image"/>
+      <password
+        :bg="showInfo.icon"
+        :show="showPassword"
+        @submit="handlePassword"
+        @close="showPassword = false"
+      />
+      <popup :title="'简介'" :show="showIntro" @close="showIntro = false">
+        <div slot="content" class="introcon">
+          {{ showInfo.description }}
+        </div>
+      </popup>
+      <imgview
+        @close="showImage = false"
+        v-if="showImage"
+        :image="currentHotspot.image"
+      />
 
-    <preview
-      :item="currentHotspot"
-      :show="showPreview"
-      @close="showPreview = false"
-    />
+      <preview
+        :item="currentHotspot"
+        :show="showPreview"
+        @close="showPreview = false"
+      />
 
-    <popup :title="currentHotspot.hotspotTitle" :show='showTextarea' @close="showTextarea=false" >
-      <div slot="content" class="introcon">
-        {{currentHotspot.textarea}}
+      <popup
+        :title="currentHotspot.hotspotTitle"
+        :show="showTextarea"
+        @close="showTextarea = false"
+      >
+        <div slot="content" class="introcon">
+          {{ currentHotspot.textarea }}
+        </div>
+      </popup>
+
+      
+    </template>
+
+  <template v-else>
+     <div class="hasDel" v-if="loadFinish">
+      <div>
+        <img :src="$noresult" alt="">
+        <p>作品已被删除</p>
       </div>
-    </popup>
-    
-    <ul class="aside">
-      <li v-for="(item,i) in aside" :key="i">
-        <span @click="handleItem(item)">
-          <i class="iconfont" :class="item.icon"></i>
-        </span>
-      </li>
-    </ul>
+    </div>
+  </template>
+
+   
   </div>
 </template>
 
 <script>
 import * as krfn from "@/core/index.js";
-import { getWebWorksInfo, checkPassword,getWebIndex } from "@/api";
-import password from './popup/password'
-import preview from './popup/preview'
+import { getPanoInfo, checkPassword,checkWork } from "@/api";
+import password from "./popup/password";
+import preview from "./popup/preview";
 
 import imgview from "./popup/imgview";
+import vIfr from "./iframe";
 
-import popup from './popup/'
-import { mapGetters } from "vuex";
 
+import popup from "./popup/";
+import { mapGetters } from "vuex";
 
 import list from "./list";
 
 let __krfn = krfn.default;
 
 export default {
-  components:{
-      list,
-      password,
-      popup,
-      preview,
-      imgview
+  components: {
+    list,
+    password,
+    popup,
+    preview,
+    imgview,
+    vIfr
   },
   computed: {
     ...mapGetters({
-      showInfo:'showInfo',
-    })
+      showInfo: "showInfo",
+    }),
   },
-  data(){
+  data() {
     return {
-      showPreview:false,
-      showTips:true,
-      showImage:false,
-      canLoad:false,
-      showPassword:false,
-      showIntro:false,
-      showTextarea:false,
-      password:'',
-      activeItem:'',
-      firstScene:'',
-      someData:'',
-      currentHotspot:'',
-      list:[],
-      aside:[{
-        id:'about',
-        icon:'icontool_about'
-      },{
-        id:'vr',
-        icon:'icontool_vr'
-      }]
-    }
+      showPreview: false,
+      showTips: true,
+      showImage: false,
+      canLoad: false,
+      showPassword: false,
+      showIntro: false,
+      showTextarea: false,
+      password: "",
+      activeItem: "",
+      firstScene: "",
+      someData: "",
+      currentHotspot: "",
+      list: [],
+      loadFinish:false,
+      aside: [
+        {
+          id: "about",
+          icon: "icontool_about",
+        },
+        {
+          id: "vr",
+          icon: "icontool_vr",
+        },
+      ],
+    };
   },
-  methods:{
-    handleItem(data){
-      if (data.id=='about') {
-        this.showIntro = true
+  methods: {
+    handleItem(data) {
+      if (data.id == "about") {
+        this.showIntro = true;
       }
     },
-    handlePassword(data){
-      checkPassword({
-        password:data
-      },res=>{
-        if (res.code == 0) {
-          this.showPassword = false
-          this.canLoad = true
-        }
-        else{
-            return this.$alert({ content: '密码错误' })
+    handlePassword(data) {
+      checkPassword(
+        {
+          password: data,
+        },
+        (res) => {
+          if (res.code == 0) {
+            this.showPassword = false;
+            this.canLoad = true;
+          }
         }
-      })
+      );
     },
-    startLoad(){
-      this.canLoad = true
-      this.getWebIndex()
+    startLoad() {
+      this.canLoad = true;
     },
-    handleSelect(data){
-      this.activeItem = data
+    handleSelect(data) {
+      this.activeItem = data;
     },
-    getWebIndex(){
-      getWebIndex({},data=>{
-        this.firstScene = data.data
+    
+    getSceneInfo() {
+      checkWork("",data=>{
+        if (data.data) {
+          getPanoInfo(
+            "",
+            (data) => {
+              this.loadFinish = true
+              this.$store.commit("SetShowInfo", data);
+            }
+          );
+        } else{
+          this.loadFinish = true
+        }
       })
     },
-    getSceneInfo(){
-      getWebWorksInfo({},data=>{
-        this.$store.commit("SetShowInfo", data.data);
-      })
-    }
   },
-  watch:{
-    currentHotspot:{
-      deep:true,
-      handler:function (newVal) {
+  watch: {
+    currentHotspot: {
+      deep: true,
+      handler: function (newVal) {
         console.log(newVal);
         if (newVal) {
-          if (newVal.hotspotType=="link") {
-            window.open(newVal.hyperlink,'_blank')
-            return
+          if (newVal.hotspotType == "link") {
+            window.open(newVal.hyperlink, "_blank");
+            return;
           }
-          if (newVal.hotspotType=="scene") {
-            this.activeItem = newVal.secne
-            return
+          if (newVal.hotspotType == "scene") {
+            this.activeItem = newVal.secne;
+            return;
           }
-          if (newVal.hotspotType=="image") {
-            this.showImage = true
-            return
+          if (newVal.hotspotType == "image") {
+            this.showImage = true;
+            return;
           }
-           if (newVal.hotspotType=="textarea") {
-            this.showTextarea = true
-            return
+          if (newVal.hotspotType == "textarea") {
+            this.showTextarea = true;
+            return;
           }
-          this.showPreview = true
+          this.showPreview = true;
         }
+      },
+    },
+    canLoad(newVal) {
+      if (newVal) {
+        setTimeout(() => {
+          this.showTips = false;
+        }, this.showInfo.remindTime * 1000);
       }
     },
-    showInfo:{
-      deep:true,
-      immediate:true,
-      handler:function (newVal) {
+    showInfo: {
+      deep: true,
+      immediate: true,
+      handler: function (newVal) {
         if (newVal) {
-          setTimeout(() => {
-            this.showTips = false
-          }, this.showInfo.remindTime*1000);
-          newVal.isPassword?(this.showPassword = true):(this.startLoad())
+        let locoR = "localRemind"+newVal.id
+
+          if (!newVal.description) {
+            this.aside.shift()
+          }
+          if (newVal.isRemind==1) {
+            this.localRemind = localStorage.getItem(locoR) == 1 ? false : true
+            localStorage.setItem(locoR, 1);
+          }
+          else{
+            this.localRemind = true;
+            localStorage.setItem(locoR, 0);
+          }
+          newVal.password ? (this.showPassword = true) : this.startLoad();
         }
-      }
+      },
     },
-    activeItem:{
+    activeItem: {
       handler(newVal) {
-        $('#pano').empty();
-        window.vrInitFn = ()=>{
-            var krpano = document.getElementById('krpanoSWFObject');
-            __krfn.utils.initHotspot(krpano,newVal&&newVal.someData,false);
-        }
-        window.vrViewFn = ()=>{
+        $("#pano").empty();
+        window.vrInitFn = () => {
+          var krpano = document.getElementById("krpanoSWFObject");
+          __krfn.utils.initHotspot(krpano, newVal && newVal.someData, false);
+        };
+        window.vrViewFn = () => {
           try {
-              let tmp = JSON.parse(newVal.initVisual)
-              var krpano = document.getElementById('krpanoSWFObject');
-              krpano.set('view.vlookat',tmp.vlookat);
-              krpano.set('view.hlookat',tmp.hlookat);
-            } catch (error) {
-              error
-            }
-        }
+            let tmp = newVal.initVisual||{};
+            var krpano = document.getElementById("krpanoSWFObject");
+            krpano.set("view.vlookat", tmp.vlookat||0);
+            krpano.set("view.hlookat", tmp.hlookat||0);
+            krpano.set("autorotate.enabled", Boolean(this.showInfo.isAuto));
+          } catch (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')
-            embedpano({
-              // 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: 0.7,
-              vars:settings,
-              passQueryParameters: true,
-            });
-
+          removepano("#pano");
+          embedpano({
+            // 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: 0.7,
+            vars: settings,
+            passQueryParameters: true,
+          });
         }
-       
-      }
-    }
+      },
+    },
   },
-  mounted(){
+  mounted() {
     window.__krfn = __krfn;
     this.$bus.on("clickHotspot", (data) => {
-      let someData = JSON.parse(this.activeItem.someData)
+      let someData = JSON.parse(this.activeItem.someData);
       let idx = someData.hotspots.findIndex((item) => item.name == data);
       this.currentHotspot = someData.hotspots[idx];
     });
-    this.getSceneInfo()
-  }
-}
+    this.getSceneInfo();
+  },
+};
 </script>
 
 <style lang="less" scoped>
-.panocon{
+.panocon {
   width: 100%;
   height: 100%;
-  #pano{
+  #pano {
+    width: 100%;
+    height: 100%;
+  }
+  .hasDel{
+    background: #fff;
+    width: 100%;
+    height: 100%;
+    position: relative;
+    >div{
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%,-50%);
+      color: #909090;
+      text-align: center;
+      font-size: 18px;
+      >p{
+        margin-top: 20px;
+      }
+    }
+  }
+  >iframe{
     width: 100%;
     height: 100%;
   }
 
-   .pano-logo{
+  .pano-logo {
     position: absolute;
     top: 10px;
     left: 10px;
-    >img{
+    > img {
       max-width: 80px;
     }
   }
 
-  .oper-tips{
+  .oper-tips {
     position: absolute;
     top: 50%;
     left: 50%;
-    transform: translate(-50%,-50%);
+    transform: translate(-50%, -50%);
     transition: all 0.3s ease;
-    >img{
+    > img {
       max-width: 90%;
     }
   }
 
-  .hidetips{
+  .hidetips {
     display: none;
   }
-  .aside{
+  .aside {
     position: fixed;
     z-index: 999;
     right: 10px;
     bottom: 0;
     display: flex;
-    >li{
-      margin:0 0 5px 5px;
-      >span{
+    > li {
+      margin: 0 0 5px 5px;
+      > span {
         width: 36px;
         height: 36px;
         display: inline-block;
@@ -271,16 +363,16 @@ export default {
         border-radius: 18px;
         position: relative;
         cursor: pointer;
-        >i{
+        > i {
           position: absolute;
           top: 50%;
           left: 50%;
-          transform: translate(-50%,-50%);
+          transform: translate(-50%, -50%);
         }
       }
     }
   }
-  .introcon{
+  .introcon {
     line-height: 20px;
     color: #909090;
   }

+ 216 - 61
src/framework/showMobile/list.vue

@@ -1,120 +1,206 @@
 <template>
   <div class="list">
      <div class="l-con" :class="showList?'active':''">
-      <ul class="pic-list" v-if="vrlist.length>0">
-        <li @click="$emit('select',item)" v-for="(item,i) in vrlist" :key="i">
+      <ul class="pic-list" v-if="scenes.length>0">
+        <li @click="handleVR(item)" v-for="(item,i) in scenes" :key="i">
           <div :class="{active:selected.sceneCode==item.sceneCode}">
-            <img :src="item.icon" alt="" />
+            <img :src="item.icon+`?${Math.random()}`" alt="" />
             <i class="iconfont iconscene_map_3d" :class="{'iconjump':item.type!=='4dkk'}"></i>
             <span>{{item.sceneTitle}}</span>
           </div>
         </li>
       </ul>
       
-      <ul class="tap" v-if="taboneActive.children.length>0">
-        <li  @click="tabtowActive = item" v-for="(item,i) in taboneActive.children" :key="i">
-          <span :class="{active:item.id == tabtowActive.id}" class="btn rect">{{item.name}}</span>
+      <ul class="tap" v-if="childTab.length > 1" >
+        <li  @click="tabtowActive = item" v-for="(item,i) in childTab" :key="i">
+          <span :title="item.name" :class="{active:item.id == tabtowActive.id}" class="btn rect">{{item.name}}</span>
         </li>
       </ul>
-       <ul class="tap">
-        <li  @click="taboneActive = item" v-for="(item,i) in tablist" :key="i">
-          <span :class="{active:item.id == taboneActive.id}" class="btn rect">{{item.name}}</span>
+       <ul class="tap" v-if="showInfo.catalogRoot.length > 1">
+        <li @click="taboneActive = item" v-for="(item,i) in showInfo.catalogRoot" :key="i">
+          <span :title="item.name"  :class="{active:item.id == taboneActive.id}" class="btn rect">{{item.name}}</span>
         </li>
       </ul>
     </div>
-    <div class="btn dl" @click="showList=!showList">
-      <i class="iconfont " :class="showList?'iconnav_scene_down':'iconnav_scene_up'"></i>场景导览</div>
+    <div v-if="selected.type=='4dkk'" class="menu">
+      <ul :class="{shouqi:shouqi}">
+        <li>
+          <i class="iconfont"  @click="showList=!showList" :class="showList?'iconnav_scene_down':'iconnav_scene_up'"></i>
+        </li>
+
+        <li class="licon">
+          <ul>
+            <li v-for="(item,i) in menu" @click="handleMenu(item)" :key="i">
+              <i class="iconfont" :class="currentActive==item.id?item.active:item.icon"></i>
+              <span :title="item.name" >{{item.name}}</span>
+              <!-- <i style="font-size:10px; margin-left:6px" v-if="item.id == 'daolan'" class="iconfont iconshow_drop-down"></i> -->
+            </li>
+          </ul>
+        </li>
+        
+        <i  @click="shouqi = !shouqi" class="iconfont iconshow_function_collect"></i>
+      </ul>
+    </div>
+
+    <div class="btn dl" @click="showList=!showList" v-else>
+      <i class="iconfont " :class="showList?'iconnav_scene_down':'iconnav_scene_up'"></i>场景导览
+    </div>
   </div>
 </template>
 
 <script>
-import { getWebTabList } from "@/api";
 import { mapGetters } from "vuex";
+import config from "@/config";
 
 export default {
-  props:['select','firstScene'],
+  props:['select'],
   
   data(){
+    let menu = [{
+      id:'daolan',
+      name:'导览',
+      icon:'iconshow_playback',
+      active:'iconshow_suspension'
+    },{
+      id:'manyou',
+      name:'漫游',
+      icon:'iconshow_roaming_normal',
+      active:'iconshow_roaming_selected',
+      params:'pano'
+    },{
+      id:'pingmian',
+      name:'平面',
+      icon:'iconshow_plane_normal',
+      active:'iconshow_plane_selected',
+      params:'2d'
+    },{
+      id:'sanwei',
+      name:'三维',
+      icon:'iconshow_3d_normal',
+      active:'iconshow_3d_selected',
+      params:'3d'
+    }]
     return{
+      currentActive:'manyou',
       taboneActive:{children:[]},
       tabtowActive:'',
+      childTab:[],
+      sceneNum: config.sceneNum,
+      scenes:[],
+      menu,
       showList:true,
-      checkFirst:true
+      loadFirst: true,
+      shouqi:false
     }
   },
   computed: {
       ...mapGetters({
-        tablist:'tablist',
-        vrlist:'vrlist'
+        showInfo: "showInfo"
       }),
       selected(){
         return {...this.select}
       }
   },
-  methods:{
-    getWebTabList(){
-      getWebTabList({},data=>{
-        this.$store.commit("SetTabList", data.data);
-        if (this.firstScene) {
-          let id = this.firstScene.parentId||this.firstScene.catalogId
-          let tmp = data.data.find(item => item.id == id);
-          if (this.firstScene.parentId) {
-            this.tabtowActive =tmp.children.find(item => {
-              return item.id == this.firstScene.catalogId
-            });
-          }
-          this.taboneActive = tmp
+
+  mounted(){
+      this.$bus.on('guideRoomsData',data=>{
+        if (data.length<0) {
+          this.menu.shift()
         }
-        setTimeout(() => {
-          this.checkFirst = false
-        });
-     
       })
+  },
+  methods:{
+    handleMenu(data){
+      if (this.currentActive == data.id) {
+        this.currentActive = ''
+      }
+      else{
+        this.currentActive = data.id
+      }
+
+      if (data.id=='manyou') {
+        this.currentActive = data.id
+      }
+      
+
+      let ele = document.getElementById('showifr');
+      let event = ''
+      let params = null
+      if (data.id=='daolan') {
+        this.currentActive?(event='guide-start'):(event='guide-pause')
+      }
+      else{
+        event = 'mode'
+        params = data.params
+      }
+      ele.contentWindow.postMessage({
+          source: "mingyuan",
+          event: event,
+          params: params,
+      },"*")
+    },
+    handleVR(item){
+      history.replaceState(null, null, "".concat(window.location.pathname, "?").concat(`id=${this.showInfo.id}&vr=${item.sceneCode}`));
+      this.sceneNum = item.sceneCode
     }
   },
   watch:{
-    taboneActive:{
-      deep:true,
-      handler:function (newVal) {
-        if (newVal.children.length>0&&!this.checkFirst) {
-          this.tabtowActive = newVal.children[0]
+    taboneActive: {
+      handler: function (newVal) {
+        let temp = []
+        newVal.children && newVal.children.forEach(item=>{
+          this.showInfo.catalogs.forEach(sub=>{
+            if (item==sub.id) {
+              temp.push(sub)
+            }
+          })
+        })
+        this.childTab = temp
+        if (!this.loadFirst) {
+            this.tabtowActive = ''
         }
-        if (newVal.id) {
-          this.$store.commit("SetVrList", newVal.scenes);
-        }
-      }
+      },
     },
-    tabtowActive:{
-      deep:true,
-      handler:function (newVal) {
-        if (newVal.id) {
-          this.$store.commit("SetVrList", newVal.scenes);
+    tabtowActive: {
+      handler: function (newVal) {
+        if (!newVal) {
+          this.tabtowActive = this.childTab[0]
+        } else{
+          this.scenes = this.showInfo.scenes.filter(item=>{
+            return newVal.id == item.category
+          })
         }
       }
     },
-    vrlist:{
+
+    sceneNum:{
       deep:true,
+      immediate:true,
       handler:function (newVal) {
-        this.$emit('select',this.checkFirst ? this.firstScene : newVal[0])
+          let val = this.showInfo.scenes.find(item=>item.sceneCode==newVal)
+          let tmp = this.showInfo.catalogs.find(item=>item.id==val.category)
+          let rootTmp = this.showInfo.catalogRoot.find(item => {
+            return item.children.indexOf(tmp.id)>-1
+          });
+          this.taboneActive = rootTmp
+          this.tabtowActive = tmp
+
+        setTimeout(() => {
+          this.$emit('select',val)
+          this.loadFirst = false 
+        });
       }
     },
+
+   
     selected:{
       handler:function (newVal) {
-        if (!this.checkFirst) {
-          let id = newVal.parentId||newVal.catalogId
-          let tmp = this.tablist.find(item => item.id == id);
-          if (newVal.parentId) {
-            this.tabtowActive =tmp.children.find(item => {
-              return item.id == newVal.catalogId
-            });
-          }
-          this.taboneActive = tmp
+        this.handleVR(newVal)
+        if (newVal.type == '4dkk') {
+          this.showList = false
         }
       }
     }
-  },
-  mounted(){
-    this.getWebTabList()
   }
 }
 </script>
@@ -130,6 +216,9 @@ export default {
     border: 1px solid rgba(255, 255, 255, 0.2);
     min-width: 78px;
     cursor: pointer;
+    text-overflow: ellipsis;
+    overflow: hidden;
+    white-space: nowrap;
     &.active{
       background: rgba(0, 0, 0, 0.3);
       border: 1px solid #1FE4DC;
@@ -170,6 +259,68 @@ export default {
       font-size: 18px;
     }
   }
+
+  .menu{
+    display: inline-block;
+    margin: 10px 0 32px;
+    >ul{
+      display: flex;
+      border: 1px solid rgba(255, 255, 255, 0.10196078431372549);
+      border-radius: 0px 24px 24px 0px;
+      background: rgba(0, 0, 0, 0.5);
+      padding-right: 30px;
+      align-items: center;
+      position: relative;
+      >li{
+        color: #fff;
+        margin: 0;
+        padding: 0;
+        padding-left: 10px;
+        height: 48px;
+        line-height: 48px;
+        background: none;
+        transition: 0.3s all ease;
+        >ul{
+          display: flex;
+          align-items: center;
+          >li{
+            color: #fff;
+            margin: 0;
+            height: 48px;
+            line-height: 48px;
+            padding: 0 10px;
+            background: none;
+            >span{
+              display: inline-block;
+              margin-left: 6px;
+            }
+          }
+        }
+      }
+
+
+      &.shouqi{
+        .licon{
+          overflow: hidden;
+          width: 0;
+        }
+        >i{
+          transform: translateY(-50%) rotate(180deg);
+        }
+      }
+      
+      
+      >i{
+        font-size: 10px;
+        position: absolute;
+        right: 14px;
+        top: 50%;
+        transform: translateY(-50%);
+      }
+
+
+    }
+  }
   .l-con{
     width: 100%;
     transition: all ease 0.3s;
@@ -232,6 +383,10 @@ export default {
     .pic-list{
       background: rgba(0, 0, 0, 0.3);
       padding: 12px 0;
+      overflow-x: auto;
+      &::-webkit-scrollbar {
+        display: none;
+      }
       >li{
         cursor: pointer;
       }

+ 3 - 3
src/framework/showMobile/popup/password.vue

@@ -13,8 +13,8 @@
             <input
               @keyup.enter="emitname"
               class="ui-input"
-              type="text"
-              maxlength="15"
+              type="password"
+              maxlength="20"
               placeholder="请输入访问密码"
               v-model="key"
             />
@@ -23,7 +23,7 @@
         <div class="ma-line"></div>
         <div class="ui-message-footer">
           <div class="btn">
-            <button @click="emitname" :class="`ui-button ui-button-rect submit`" >
+            <button @click="emitname" class="ui-button ui-button-rect submit" :class="{disable:!key}" >
               确定
             </button>
           </div>

+ 1 - 1
src/framework/showMobile/popup/preview.vue

@@ -49,7 +49,7 @@ export default {
   color: rgba(255, 255, 255, 0.88);
   top: 28px;
   font-size: 14px;
-  left: 28px;
+  right: 28px;
 }
 .ui-message-confirm{
   border-radius: 0;

+ 36 - 0
src/framework/vr/index.vue

@@ -15,6 +15,8 @@ window.__krfn = __krfn
 
 window.screenshot = function () {
   let canvas = $("#krpanoSWFObject canvas")[0];
+  
+
   let krpano = document.getElementById('krpanoSWFObject');
   let data = __krfn.utils.setInitView(krpano, canvas);
   return data
@@ -28,6 +30,32 @@ export default {
     }
   },
   methods:{
+    onFullScreen() {
+        let element = document.documentElement;
+        if (this.isFullscreen) {
+            if (document.exitFullscreen) {
+                document.exitFullscreen();
+            } else if (document.webkitCancelFullScreen) {
+                document.webkitCancelFullScreen();
+            } else if (document.mozCancelFullScreen) {
+                document.mozCancelFullScreen();
+            } else if (document.msExitFullscreen) {
+                document.msExitFullscreen();
+            }
+        } else {
+            if (element.requestFullscreen) {
+                element.requestFullscreen();
+            } else if (element.webkitRequestFullScreen) {
+                element.webkitRequestFullScreen();
+            } else if (element.mozRequestFullScreen) {
+                element.mozRequestFullScreen();
+            } else if (element.msRequestFullscreen) {
+                element.msRequestFullscreen();
+            }
+        }
+          // 改变当前全屏状态
+        // this.isFullscreen = !this.isFullscreen;
+      },
     onclick(){
       let canvas = $("#krpanoSWFObject canvas")[0];
       let krpano = document.getElementById('krpanoSWFObject');
@@ -41,6 +69,14 @@ export default {
   },
  
   mounted(){
+    window.addEventListener('message',data=>{
+      if (data.data.event=="onfull") {
+        this.onFullScreen()
+      }
+      // this.onFullScreen()
+
+    })
+ 
     // this.getSceneInfo()
         $('#pano').empty();
         removepano('#pano')

+ 1 - 1
src/lang/_zh.js

@@ -394,7 +394,7 @@ module.exports = {
         "cancel": "取消",
         "complete": "完成",
         "edit": "修改",
-        "giveup": "放弃",
+        "giveup": "取消",
         "commit": "提交",
         "photo": "图片",
         "voice": "音频",

+ 212 - 135
src/mixins/index.js

@@ -1,154 +1,231 @@
-import Vue from 'vue'
+import Vue from "vue";
 
-import config from '../config'
-import bus from '../utils/eventbus'
-import {
-    Alert,
-    Confirm,
-    Tips
-} from '../components/shared/message'
+import config from "../config";
+import bus from "../utils/eventbus";
+import { Alert, Confirm, Tips } from "../components/shared/message";
 
-import clickoutside from './v-clickoutside'
-import clickwindow from './v-clickwindow'
-import * as api from '../api'
+import clickoutside from "./v-clickoutside";
+import clickwindow from "./v-clickwindow";
+import * as api from "../api";
 
-const MARERIAL = ['image','pano','scene','audio','video']
+const MARERIAL = ["image", "pano", "scene", "audio", "video"];
 
-const MAPTABLEHEADER = {}
-MARERIAL.forEach(item=>{
-  MAPTABLEHEADER[item] = require(`@/views/material/${item}/${item}`).data
-})
+const MAPTABLEHEADER = {};
+MARERIAL.forEach((item) => {
+  MAPTABLEHEADER[item] = require(`@/views/material/${item}/${item}`).data;
+});
 
 const MARERIALSTR = {
-    'image':'图片',
-    'pano':'全景图',
-    'scene':'场景',
-    'audio':'音频',
-    'video':'视频'
-}
-
-Vue.prototype.$bus = bus
-Vue.prototype.$api = api
-Vue.prototype.$intranet = config.intranet
-Vue.prototype.$cdn = config.CDN
-Vue.prototype.$config = config
-Vue.prototype.$thumb = config.thumb
-Vue.prototype.$noresult = config.noresult
-Vue.prototype.$MAPTABLEHEADER = MAPTABLEHEADER
-Vue.prototype.$MARERIALSTR = MARERIALSTR
-
-Vue.prototype.$videoImg = '?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto'
-
-
-Vue.prototype.$panoType = [{
-    id:'building',
-    name:'楼盘全景'
-  },{
-    id:'garden',
-    name:'园林全景'
-  },{
-    id:'house',
-    name:'户型'
-  }]
+  image: "图片",
+  pano: "全景图",
+  scene: "场景",
+  audio: "音频",
+  video: "视频",
+};
+
+Vue.prototype.$bus = bus;
+Vue.prototype.$api = api;
+Vue.prototype.$intranet = config.intranet;
+Vue.prototype.$cdn = config.CDN;
+Vue.prototype.$config = config;
+Vue.prototype.$thumb = config.thumb;
+Vue.prototype.$noresult = config.noresult;
+Vue.prototype.$MAPTABLEHEADER = MAPTABLEHEADER;
+Vue.prototype.$MARERIALSTR = MARERIALSTR;
+
+Vue.prototype.$videoImg =
+  "?x-oss-process=video/snapshot,t_0,f_jpg,w_0,h_0,m_fast,ar_auto";
+
+Vue.prototype.$panoType = [
+  {
+    id: "building",
+    name: "楼盘全景",
+  },
+  {
+    id: "garden",
+    name: "园林全景",
+  },
+  {
+    id: "house",
+    name: "户型",
+  },
+];
 
 Vue.prototype.$nameStr = {
-    'building':'楼盘全景',
-    'garden':'园林全景',
-    'house':'户型'
-  }
+  building: "楼盘全景",
+  garden: "园林全景",
+  house: "户型",
+};
 
 Vue.prototype.$nameSort = {
-    'building':1,
-    'garden':2,
-    'house':3
-}
+  building: 1,
+  garden: 2,
+  house: 3,
+};
 
-Vue.prototype.$scrollbars = []
+Vue.prototype.$scrollbars = [];
 
-let SettingPanel = require('@/framework/SettingPC').default
+let SettingPanel = require("@/framework/SettingPC").default;
 
 Vue.mixin({
-    components: {
-        SettingPanel
+  components: {
+    SettingPanel,
+  },
+  directives: {
+    clickoutside: clickoutside,
+    clickwindow: clickwindow,
+  },
+  data() {
+    return {};
+  },
+  methods: {
+    $alert(data = {}) {
+      let instance = new Alert({
+        data,
+      }).$mount();
+
+      document.body.appendChild(instance.$el);
+
+      Vue.nextTick(() => {
+        instance.show = true;
+      });
     },
-    directives: {
-        'clickoutside': clickoutside,
-        'clickwindow': clickwindow
+    $confirm(data = {}) {
+      let instance = new Confirm({
+        data,
+      }).$mount();
+
+      document.body.appendChild(instance.$el);
+
+      Vue.nextTick(() => {
+        instance.show = true;
+      });
     },
-    data() {
-        return {
+    $tips(data = {}) {
+      let instance = new Tips({
+        data,
+      }).$mount();
+
+      document.body.appendChild(instance.$el);
 
+      Vue.nextTick(() => {
+        instance.show = true;
+      });
+    },
+    $isCacheId(id) {
+      return String(id).indexOf("tmp") > -1;
+    },
+    $getStaticResource(url) {
+      return config.getStaticResource(url);
+    },
+    $html_encode(str) {
+      return config.html_encode(str);
+    },
+    $getKrpano(str) {
+      return config.getKrpano(str);
+    },
+    $randomWord(randomFlag, min, max) {
+      //随机字符串
+      var str = "",
+        range = min,
+        arr = [
+          "0",
+          "1",
+          "2",
+          "3",
+          "4",
+          "5",
+          "6",
+          "7",
+          "8",
+          "9",
+          "a",
+          "b",
+          "c",
+          "d",
+          "e",
+          "f",
+          "g",
+          "h",
+          "i",
+          "j",
+          "k",
+          "l",
+          "m",
+          "n",
+          "o",
+          "p",
+          "q",
+          "r",
+          "s",
+          "t",
+          "u",
+          "v",
+          "w",
+          "x",
+          "y",
+          "z",
+          "A",
+          "B",
+          "C",
+          "D",
+          "E",
+          "F",
+          "G",
+          "H",
+          "I",
+          "J",
+          "K",
+          "L",
+          "M",
+          "N",
+          "O",
+          "P",
+          "Q",
+          "R",
+          "S",
+          "T",
+          "U",
+          "V",
+          "W",
+          "X",
+          "Y",
+          "Z",
+        ];
+
+      if (randomFlag) {
+        // 随机长度
+        range = Math.round(Math.random() * (max - min)) + min;
+      }
+      for (var i = 0; i < range; i++) {
+        var pos = Math.round(Math.random() * (arr.length - 1));
+        str += arr[pos];
+      }
+      return str;
+    },
+    $unique(arr) {
+      let map = new Map();
+      let array = new Array(); // 数组用于返回结果
+      for (let i = 0; i < arr.length; i++) {
+        if (map.has(arr[i])) {
+          // 如果有该key值
+          map.set(arr[i], true);
+        } else {
+          map.set(arr[i], false); // 如果没有该key值
+          array.push(arr[i]);
         }
+      }
+      return array;
+    },
+    $htmlEncode(str) {
+      var s = "";
+      if (str.length == 0) return "";
+      s = str.replace(/\'/g, "&#39;");
+      s = s.replace(/\"/g, "&quot;");
+      s = s.replace(/\(/g, "(");
+      s = s.replace(/\)/g, ")");
+      s = s.replace(/,/g, ",");
+      return s;
     },
-    methods: {
-        $alert(data = {}) {
-            let instance = new Alert({
-                data
-            }).$mount()
-
-            document.body.appendChild(instance.$el)
-
-            Vue.nextTick(() => {
-                instance.show = true
-            })
-        },
-        $confirm(data = {}) {
-            let instance = new Confirm({
-                data
-            }).$mount()
-
-            document.body.appendChild(instance.$el)
-
-            Vue.nextTick(() => {
-                instance.show = true
-            })
-        },
-        $tips(data = {}) {
-            let instance = new Tips({
-                data
-            }).$mount()
-
-            document.body.appendChild(instance.$el)
-
-            Vue.nextTick(() => {
-                instance.show = true
-            })
-        },
-        $isCacheId(id){
-          return String(id).indexOf("tmp") > -1
-        },
-        $getStaticResource(url) {
-            return config.getStaticResource(url)
-        },
-        $html_encode(str){
-            return config.html_encode(str)
-        },
-        $getKrpano(str){
-            return config.getKrpano(str)
-        },
-        $randomWord(randomFlag, min, max) {//随机字符串
-            var str = "",
-                range = min,
-                arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
-        
-            if (randomFlag) { // 随机长度
-                range = Math.round(Math.random() * (max - min)) + min;
-            }
-            for (var i = 0; i < range; i++) {
-                var pos = Math.round(Math.random() * (arr.length - 1));
-                str += arr[pos];
-            }
-            return str;
-        },
-        $htmlEncode(str) {
-                var s = "";
-                if (str.length == 0) return "";
-                s = str.replace(/\'/g, "&#39;");
-                s = s.replace(/\"/g, "&quot;");
-                s = s.replace(/\(/g, "(");
-                s = s.replace(/\)/g, ")");
-                s = s.replace(/,/g, ",");
-                return s;
-            }
-    }
-})
+  },
+});

+ 16 - 10
src/router/index.js

@@ -37,21 +37,26 @@ OnlineDetector.register(
   detector => new Promise(resolve => detector.resolve(resolve))
 );
 
-// checkLogin().then(response => {
-//   if (response.code == 0) {
-//       LoginDetector.valid();
-//   }
-// });
+//检验是不是该用户作品
+checkLogin().then(response => {
+  if (response.code == 3005) {
+    store.commit('UpdateIsShowState', false)
+    vue.$bus.emit('canLoad',false) 
+    return vue.$alert({content: '不是该用户作品'});
+  } else{
+    vue.$bus.emit('canLoad',true) 
+    LoginDetector.valid();
+  }
+});
 
 getPanoInfo().then(response => {
-  if(response.data&&response.data.status == 1){
+  if(response&&response.status == 1){
     store.commit('UpdateIsShowState', true)
   }
-    vue.$bus.emit('canLoad',true) 
-    OnlineDetector.valid();
-  
+  OnlineDetector.valid();
 });
 
+
 const router = new Router({
   routes: routes
 })
@@ -59,13 +64,14 @@ const router = new Router({
 
 router.beforeEach(async (to, from, next) => {
   
-    // await LoginDetector.listener();
+    await LoginDetector.listener();
     await OnlineDetector.listener();
     if (from.name == 'hotspot') {
       if (store.getters.isEditing) {
         vue.$confirm({
             content: "热点内容未编辑完,确定要关闭吗",
             ok: () => {
+              vue.$bus.emit('delhotspot') 
              return next()
             }
         });

+ 5 - 2
src/utils/file.js

@@ -106,7 +106,9 @@ export const blobToBase64 = function (blob) {
  * 获取图片文件尺寸
  * @param {*} file 
  */
-export const getImgWH = (file) => {
+export const getImgWH = (data) => {
+    let file = data.file
+
     return new Promise((resolve) => {
         var reader = new FileReader();
         //读取图片文件
@@ -125,6 +127,7 @@ export const getImgWH = (file) => {
                         height,
                         width
                     },
+                    list:data.list,
                     file
                 })
             };
@@ -146,6 +149,6 @@ export const changeByteUnit = (x) => {
     while (n >= 1024 && ++l) {
         n = n / 1024;
     }
-    return (n.toFixed(n < 10 && l > 0 ? 1 : 0) + units[l]);
+    return (n.toFixed(n < 10 && l > 0 ? 2 : 0) + units[l]);
 
 }

+ 34 - 8
src/utils/request.js

@@ -6,6 +6,7 @@
  * @Description: Request
  */
 
+import Vue from 'vue'
 import logger from './logger'
 import browser from './browser'
 import { base64ToBlob } from './file'
@@ -15,6 +16,9 @@ import { $alert, $loginTips } from '@/components/shared/message'
 import { $waiting } from '@/components/shared/loading'
 
 
+let vue = new Vue()
+
+
 // 空函数
 const noop = function() {}
 // 请求回调队列
@@ -27,6 +31,11 @@ export const statusCode = {
     FAILURE_CODE_3001: 3001, //素材已被引用,无法删除
     FAILURE_CODE_3002: 3002, //素材已被引用,无法删除
     FAILURE_CODE_3003: 3003, //文件名称不允许超过50个字符
+    FAILURE_CODE_3005: 3005, //不是该用户作品
+    FAILURE_CODE_3006: 3006, //作品已被删除,无法编辑
+
+
+    
 
     FAILURE_CODE_5003: 5003, //不支持此图片
 
@@ -109,30 +118,41 @@ export function statusCodesHandler(result, callback) {
         return $alert({ content: '请至少保留一个场景。' })
     }
 
+    if (result.code == statusCode.FAILURE_CODE_3006) {
+        return $alert({ content: '作品已被删除,无法编辑' })
+    }
+    
+
+    if (result.code == statusCode.FAILURE_CODE_3005) {
+        return
+    }
+    
     if (result.code == statusCode.FAILURE_CODE_3003) {
-        return $alert({ content: '文件名称不允许超过50个字符' })
+        return statusCode.FILE
+        // return $alert({ content: '文件名称不允许超过50个字符' })
     }
     
     if (result.code == statusCode.FAILURE_CODE_5003) {
-        return $alert({ content: '不支持此图片' })
+        return statusCode.FILE
+        // return $alert({ content: '不支持此图片' })
     }
 
     if (result.code == statusCode.FAILURE_CODE_5004) {
         return $alert({ content: '密码错误' })
     }
-    
 
     if (result.code == statusCode.EXCEPTION) {
-        return !http.__loading && $alert({ content: `${result.message},请稍后再试`})
+        return !http.__loading && $alert({ content: `${result.msg},请稍后再试`})
     }
-
     
-
     if (result.code == statusCode.FAILURE_CODE_5001) {
         callback(result.code)
         return showLoginTips()
     }
 
+    if (result.code != statusCode.SUCCESS) {
+        return $alert({ content: `${result.msg}`})
+    }
     return statusCode.NEXT
 }
 
@@ -161,7 +181,7 @@ $.ajaxSetup({
     },
     complete: function(data) {
         // Post类型请求无论成功或失败都关闭等待提示
-        if (this.type === 'POST'&& this.url.indexOf('pano/scene/uploadPano') == -1) {
+        if (this.type === 'POST'&& this.url.indexOf('manage/fodder/upload') == -1) {
             let isLongpolling = ''
             try {
                  isLongpolling = JSON.parse(this.data).islongpolling
@@ -202,6 +222,10 @@ export const http = {
                     }
                 })
 
+                if (flag === statusCode.FILE) {
+                    done(result)
+                }
+
                 if (flag === statusCode.NEXT) {
                     done(result, result.code == 0)
                 }
@@ -334,7 +358,9 @@ export const http = {
                 },
             }), 'postForm', url, formData, done, fail)
         } else {
-            http.__loading && $waiting.show()
+            if (url.indexOf('manage/fodder/upload') == -1) {
+                http.__loading && $waiting.show()
+            }
             return this.__request($.ajax({
                 type: "POST",
                 url: url,

+ 1 - 2
src/views/base/EditPanel/logo.vue

@@ -5,7 +5,6 @@
         <li app-border dir-bottom>
           <div class="preview-con">
             <div class="preview">
-              
               <img :src="info.logo||require('@/assets/images/default/img_logo_default.png')" alt="" />
             </div>
             <div class="upload-con">
@@ -39,7 +38,6 @@
 
 <script>
 import Switcher from "@/components/shared/Switcher";
-import Upload from "@/components/shared/uploads/Upload";
 import { mapGetters } from "vuex";
 
 export default {
@@ -56,6 +54,7 @@ export default {
     select(newVal) {
       if (newVal) {
         this.info[this.param] = newVal;
+        this.info.logoChange = true
         this.select = "";
       }
     },

+ 2 - 1
src/views/base/EditPanel/opening.vue

@@ -57,7 +57,7 @@ export default {
         immediate:true,
         deep:true,
         handler:function (newVal) {
-          this.rang.value = newVal.remindTime || 1
+          this.rang.value = newVal.remindTime
         }
       },
       select(newVal){
@@ -92,6 +92,7 @@ export default {
       onFileChange(){
       },
       onRangeChange(data) {
+        console.log(data.value);
         this.info.remindTime = parseInt(data.value)
       },
       onSwitcherChange(data){

+ 7 - 4
src/views/base/Toolbar.vue

@@ -2,7 +2,7 @@
   <div class="app-view-toolbar app-view-full-toolbar">
     <div class="main">
       <div class="ui-title-big">基础设置</div>
-      <div class="ui-title"><span class="require">封面</span></div>
+      <div class="ui-title"><span class="">封面</span></div>
       <div class="upload-con">
         <div class="uc-l">
           <div class="preview">
@@ -22,7 +22,7 @@
         </div>
         <div class="uc-r">
           <div class="ui-title">
-            <span class="require">标题</span>
+            <span class="">标题</span>
           </div>
           <div :class="{ 'ui-warning': false }">
             <input
@@ -40,8 +40,8 @@
               v-model="info.description"
               @blur="$store.commit('SetInfo',info)"
               style="height:110px;"
-              maxlength="200"
-              placeholder="请填写简介限200字"
+              maxlength="500"
+              placeholder="请填写简介限500字"
               type="text"
               class="ui-input ui-textarea"
             />
@@ -67,6 +67,7 @@
         :title="`选择${$MARERIALSTR[type]}`"
         @changeCurrent="changeCurrent"
         :paging="paging"
+        :hideAll="true"
         @submit="handleSelect"
       >
     </Table>
@@ -134,6 +135,7 @@ export default {
     isShowSelect(newVal){
       if (!newVal) {
         this.paging.pageNum = 1
+        this.key = ''
       }
     }
   },
@@ -169,6 +171,7 @@ export default {
           this.paging.total = data.data.total;
 
           this.list = data.data.list.map(i=>{
+            i.isUse = i.fileSize>600 ?'1':'0'
             i.fileSize = changeByteUnit(Number(i.fileSize))
             return i
           })

+ 27 - 7
src/views/hotspot/EditPanel.vue

@@ -8,7 +8,7 @@
     <div class="hots-panel" v-show="show">
       <div class="ui-between header" app-border dir-bottom>
         <span>{{editTitle}}热点</span>
-        <i class="iconfont icon_close" @click="cancel"></i>
+        <i class="iconfont icon_close" @click="confirmCancel"></i>
       </div>
       <div class="content">
         <div>
@@ -111,7 +111,7 @@
         </div>
       </div>
       <div class="ui-between footer" app-border dir-top>
-        <button class="ui-button submit" @click="save">完成</button>
+        <button class="ui-button submit"  :class="{disable: false}" @click="save">完成</button>
       </div>
     </div>
   </transition>
@@ -179,6 +179,7 @@ export default {
 
    
     return {
+      canSave:false,
       hotSpotTypeList:[
         {
           id:'scene',
@@ -292,6 +293,10 @@ export default {
         sceneCode: this.infoItem.link
       }
       this.$bus.on('selectUrl',this.listerFn)
+      this.$bus.on('delhotspot',()=>{
+        this.cancel()
+      }) 
+
   },
 
   methods: {
@@ -312,6 +317,14 @@ export default {
       this.infoItem.link = data.sceneCode
       this.infoItem.thumb = data.icon  
     },
+    confirmCancel(){
+      this.$confirm({
+            content: "热点内容未编辑完,确定要关闭吗",
+            ok: () => {
+              this.cancel()
+            }
+        });
+    },
     cancel() {
       this.$store.commit("SetHotspot", this.backupHotSpot);
       this.$emit("close",{
@@ -328,15 +341,22 @@ export default {
     save() {
       let {img,hotspotTitle,hotspotType} = this.hotspot
       let item = HTMap[hotspotType]
-    
-      if (!this.hotspot[item.key]||(item.type == 'Array'&&this.hotspot[item.key].length<=0)) {
+
+      if (!img) {
         return this.$alert({
-          content: `${item.errortxt}`,
+          content: "请选择热点图标",
         });
       }
-      if (!img||!hotspotTitle) {
+
+       if (!hotspotTitle) {
+        return this.$alert({
+          content: "请输入热点标题",
+        });
+      }
+
+       if (!this.hotspot[item.key]||(item.type == 'Array'&&this.hotspot[item.key].length<=0)) {
         return this.$alert({
-          content: "请完善热点信息",
+          content: `${item.errortxt}`,
         });
       }
       this.$store.commit("SetHotspot", this.hotspot);

+ 28 - 64
src/views/hotspot/Setting.vue

@@ -6,14 +6,14 @@
         <div class="ui-remark">在全景图中添加图标热点,并设置热点的效果。</div>
         <button
           class="ui-button submit"
-          :class="{ disable: vrlist.length <= 0 }"
+          :class="{ disable: !activeItem }"
           @click="open(null)"
         >
           添加热点
         </button>
       </li>
       <li app-border class="list">
-        <div class="tips">当前场景热点({{ someData.hotspots.length }})</div>
+        <div class="tips" v-if="someData.hotspots.length>0">当前场景热点({{ someData.hotspots.length }})</div>
         <div class="hots">
           <ul v-if="someData.hotspots.length > 0">
             <li
@@ -61,20 +61,16 @@
 </template>
 <script>
 import EidtPanel from "./EditPanel";
-import { saveSomeData, saveUseHots } from "@/api";
 import { mapGetters } from "vuex";
 import browser from "@/utils/browser";
-
-// import ConfirmPanel from "./ConfirmPanel";
 export default {
   components: {
     EidtPanel,
-    // ConfirmPanel
   },
   computed: {
     ...mapGetters({
-      vrlist: "vrlist",
       activeItem: "activeItem",
+      info:"info"
     }),
   },
   data() {
@@ -130,83 +126,51 @@ export default {
       }
       this.showPanel = false;
     },
+
+    updateInfo(){
+      let iidx = this.info.scenes.findIndex(item=>this.activeItem.sceneCode == item.sceneCode)
+      if (iidx>-1) {
+        this.info.scenes[iidx] = {
+          ...this.activeItem
+        }
+      }
+      this.$store.commit("SetInfo", this.info);
+    },
     save(data) {
       var krpano = document.getElementById("krpanoSWFObject");
       let HV = window.__krfn.utils.getHotspotHV(krpano, data.name);
       data.ath = HV.ath;
       data.atv = HV.atv;
-      let type = "edit";
-      let idx = this.someData.hotspots.findIndex((item) => item.name === data.name) 
+      let idx = this.someData.hotspots.findIndex((item) => item.name === data.name)
       if (idx<=-1) {
-        type = "add";
         this.someData.hotspots.push(data);
       }
       else{
         this.someData.hotspots[idx] = data
       }
-      saveSomeData(
-        {
-          id: this.activeItem.id,
-          sceneTitle: this.activeItem.sceneTitle,
-          someData: this.someData,
-        },
-        () => {
-          this.activeItem.someData = JSON.stringify(this.someData);
-          this.$tips({ content: this.editTitle + "成功", icon: "ok" });
 
-          let tmp = JSON.parse(this.activeItem.useHots || '{"data":[]}');
-          if (type == "add") {
-            tmp.data.push(data.link);
-          } else {
-            let idx = tmp.data.findIndex((item) => item == this.editLink);
-            if (idx > -1) {
-              tmp.data[idx] = data.link;
-            }
-          }
+      this.activeItem.someData = JSON.stringify(this.someData);
+      this.$tips({ content: this.editTitle + "成功", icon: "ok" });
 
-          saveUseHots(
-            {
-              id: this.activeItem.id,
-              sceneCodes: tmp.data,
-            },
-            () => {
-              this.activeItem.useHots = JSON.stringify(tmp);
-            }
-          );
+      let iidx = this.info.scenes.findIndex(item=>this.activeItem.sceneCode == item.sceneCode)
+      if (iidx>-1) {
+        this.info.scenes[iidx] = {
+          ...this.activeItem
         }
-      );
+      }
+      
+      this.updateInfo()
+
     },
     deleteHot(data) {
       this.someData.hotspots.splice(
         this.someData.hotspots.findIndex((item) => item.name === data.name),
         1
       );
-      saveSomeData(
-        {
-          id: this.activeItem.id,
-          sceneTitle: this.activeItem.sceneTitle,
-          someData: this.someData,
-        },
-        () => {
-          this.deleteKRHotspot(data);
-          this.activeItem.someData = JSON.stringify(this.someData);
-          this.$tips({ content: "删除成功", icon: "ok" });
-
-          let tmp = JSON.parse(this.activeItem.useHots || '{"data":[]}');
-          let idx = tmp.data.findIndex((item) => item == data.link);
-          tmp.data.splice(idx, 1);
-
-          saveUseHots(
-            {
-              id: this.activeItem.id,
-              sceneCodes: tmp.data,
-            },
-            () => {
-              this.activeItem.useHots = JSON.stringify(tmp);
-            }
-          );
-        }
-      );
+      this.deleteKRHotspot(data);
+      this.activeItem.someData = JSON.stringify(this.someData);
+      this.updateInfo()
+      this.$tips({ content: "删除成功", icon: "ok" });
     },
     open(data) {
       this.editTitle = "新增";

+ 1 - 1
src/views/hotspot/hotspotType/audio.vue

@@ -53,7 +53,7 @@ export default {
   },
   methods:{
     del(){
-      this.tAudio = {}
+      this.tAudio = ''
     },
     selectHandle(){
       this.isShowSelect = true 

+ 3 - 0
src/views/hotspot/hotspotType/image.vue

@@ -103,6 +103,9 @@ export default {
       }
     },
     images(newVal){
+      if (newVal.length>20) {
+        return this.$alert({ content: "最多添加20张图片" });
+      }
       this.$emit('imageChange',newVal)
     }
   }

+ 13 - 2
src/views/hotspot/hotspotType/link.vue

@@ -3,8 +3,9 @@
     <input
       type="text"
       class="ui-input"
-      placeholder="请填写链接地址"
-      v-model="hyperlink"
+      placeholder="https://"
+      v-model.trim="hyperlink"
+      @change="onUrlChange()"
     />
   </div>
 </template>
@@ -17,6 +18,16 @@ export default {
       hyperlink:this.link
     }
   },
+  methods:{
+    onUrlChange() {
+            if (this.hyperlink) {
+                if (!/^http(s)?:\/\//.test(this.hyperlink)) {
+                    this.hyperlink =
+                        window.location.protocol + "//" + this.hyperlink;
+                }
+            }
+        },
+  },
   watch:{
     hyperlink(newVal){
       this.$emit('linkChange',newVal)

+ 1 - 10
src/views/hotspot/hotspotType/scene.vue

@@ -15,8 +15,6 @@
   <button class="ui-button submit" @click="showScene = true">选择场景</button>
   <div class="dialog" style="z-index: 2000" v-if="showScene">
       <Select
-        :tablist="tablist"
-        :vrlist="vrlist"
         @cancle="showScene = false"
         :selected='selected'
         :title="'选择素材'"
@@ -29,17 +27,10 @@
 
 <script>
 import Select from "@/components/select";
-import { mapGetters } from "vuex";
 
 export default {
   props:['scene'],
   components:{Select},
-  computed: {
-    ...mapGetters({
-      tablist:'tablist',
-      vrlist:'vrlist',
-    })
-  },
   data(){
     return {
       showScene:false,
@@ -54,7 +45,7 @@ export default {
     },
     del(){
       this.selected = ''
-      this.$emit('sceneSelect',{})
+      this.$emit('sceneSelect','')
     }
   }
 }

+ 1 - 1
src/views/hotspot/hotspotType/video.vue

@@ -52,7 +52,7 @@ export default {
   },
   methods:{
     del(){
-      this.tVideo = {}
+      this.tVideo = ''
     },
     selectHandle(){
       this.isShowSelect = true 

+ 1 - 0
src/views/hotspot/index.vue

@@ -50,6 +50,7 @@ export default {
     Select
   },
   mounted(){
+    
   },
   watch: {
     show(newVal){

+ 12 - 39
src/views/information/Setting.vue

@@ -2,12 +2,12 @@
   <div class="view-setting" app-border dir-left>
     <div class="ui-title">初始场景</div>
     <div class="preview">
-      <img v-if="img" :src="img" alt="">
+      <img v-if="info.firstScene" :src="info.firstScene.icon" alt="">
       <div class="tips" v-else>
         <i class="iconfont iconphotoview" style="font-size: 40px"></i>
       </div>
     </div>
-    <div class="setinit" v-if="img">
+    <div class="setinit" v-if="info.firstScene">
       <button class="ui-button" @click="deleteIndexInfo">删除场景</button>
       <button @click="showInitScene=true" class="ui-button submit" :class="{disable:false}">
         修改场景
@@ -25,10 +25,8 @@
 
     <div class="dialog" style="z-index: 2000" v-if="showInitScene">
       <Select
-        :tablist="tablist"
-        :vrlist="vrlist"
         @cancle="showInitScene = false"
-        :selected='initScene'
+        :selected='info.firstScene'
         :title="'选择素材'"
         @submit="handleSelect"
       >
@@ -38,7 +36,6 @@
 </template>
 
 <script>
-import { saveIndexInfo,deleteIndexInfo } from "@/api";
 import { mapGetters } from "vuex";
 import Select from "@/components/select";
 
@@ -46,59 +43,35 @@ export default {
   components:{Select},
   data(){
     return {
-      img:'',
       showInitScene:false
     }
   },
   methods:{
-    del(){
-      
-    },
-    update(){
-
-    },
     deleteIndexInfo(){
       this.$confirm({
           content: "是否删除?",
           ok: () => {
-              deleteIndexInfo({},res=>{
-                this.img = ''
-                if (res.code == 0) {
-                  this.$bus.emit('setInitScene')
-                  this.$tips({content:'删除成功',icon:'ok'})
-                }
-              })
+              this.info.firstScene = ''
+              this.$store.commit("SetInfo", this.info);
+              this.$tips({content:'删除成功',icon:'ok'})
           }
       });
       
     },
     handleSelect(data){
-      saveIndexInfo({id:data.id},res=>{
-        this.img = data.icon
-        if (res.code == 0) {
-          this.showInitScene=false
-          this.$bus.emit('setInitScene')
-          this.$tips({content:'设置成功',icon:'ok'})
-        }
-      })
+      this.info.firstScene = data
+      this.$store.commit("SetInfo", this.info);
+      this.showInitScene=false
     }
   },
   computed: {
     ...mapGetters({
-      initScene:'initScene',
-      tablist:'tablist',
-      vrlist:'vrlist',
-      allVrlist:'allVrlist'
+      info: "info",
+      backupInfo: "backupInfo"
     })
   },
   mounted(){
-    this.img = this.initScene ? this.initScene.icon :''
-    this.$bus.on('initScene',(data)=>{
-      this.img = data ? data.icon :''
-    })
-    this.$bus.on('getInitScene',data=>{
-      this.img = data.icon
-    })
+ 
   }
 }
 </script>

+ 130 - 119
src/views/information/Toolbar.vue

@@ -12,7 +12,7 @@
       <div class="pano-con">
         <tabList
           :deviation="-35"
-          :list="tablist.concat(temptablist)"
+          :list="info.catalogRoot"
           @clickItem="
             (item) => {
               taboneActive = item;
@@ -46,8 +46,8 @@
 
         <tabList
           :deviation="-35"
-          v-if="taboneActive.children.length > 0"
-          :list="taboneActive.children"
+          v-if="childTab.length > 1"
+          :list="childTab"
           @clickItem="
             (item) => {
               tabtowActive = item;
@@ -74,14 +74,14 @@
           </template>
         </tabList>
 
-        <template v-if="vrlist.length > 0">
+        <template v-if="scenes.length > 0">
           <draggable
             tag="ul"
-            v-model="vrlist"
+            v-model="scenes"
             animation="300"
             @sort="uploadListSort"
           >
-            <li v-for="(item, i) in vrlist" :key="i">
+            <li v-for="(item, i) in scenes" :key="i">
               <div class="typeli">
                 <i
                   class="iconfont iconscene_map_3d"
@@ -89,7 +89,7 @@
                 ></i>
               </div>
               <div class="img">
-                <img :src="item.icon" alt="" />
+                <img :src="item.icon+`?${Math.random()}`" alt="" />
               </div>
               <div class="oper">
                 <i class="iconfont iconmore"></i>
@@ -124,19 +124,18 @@
 </template>
 
 <script>
-import { delTab, delPano, setListSort, getTabSceneList } from "@/api";
+import { delPano, setListSort } from "@/api";
 import tabList from "@/components/tablist";
+import browser from "@/utils/browser";
 
 import draggable from "vuedraggable";
 import { mapGetters } from "vuex";
 
-const LONGPOLLINGTIME = 30;
 export default {
   computed: {
     ...mapGetters({
-      tablist: "tablist",
       vrlist: "vrlist",
-      temptablist: "temptablist",
+      info: "info",
     }),
     oneWidth() {
       let tmp = $("#tablist").width();
@@ -151,6 +150,8 @@ export default {
     return {
       taboneActive: { children: [] },
       tabtowActive: "",
+      childTab: [],
+      scenes: [],
       interval: null,
       list: [],
       isLongPolling: false,
@@ -159,81 +160,79 @@ export default {
     };
   },
   watch: {
-    taboneActive: {
+    "info.scenes": {
+      deep: true,
       handler: function (newVal) {
-        if (newVal.children.length > 0) {
-          this.tabtowActive = newVal.children[0];
-        }
-        if (this.tabtowActive) {
-          this.tabtowActive =
-            newVal.children.find((item) => {
-              return item.id == this.tabtowActive.id;
-            }) || "";
-        }
-        if (newVal.id) {
-          this.$emit("catalog", {
-            level: 1,
-            data: newVal,
-          });
-          if (newVal.children.length <= 0) {
-            this.$isCacheId(newVal.id)
-              ? this.$store.commit("SetVrList", [])
-              : this.getTabSceneList(newVal.id);
-          }
-        }
+        this.scenes = newVal.filter((item) => {
+          return this.tabtowActive.id == item.category;
+        });
       },
     },
-    tabtowActive: {
+    "info.catalogs": {
+      deep: true,
       handler: function (newVal) {
-        this.$emit("catalog", {
-          level: 2,
-          data: newVal,
-        });
-        if (newVal) {
-          this.$isCacheId(newVal.id)
-            ? this.$store.commit("SetVrList", [])
-            : this.getTabSceneList(newVal.id);
+        let temp = [];
+        this.childTab = [];
+        let id = this.taboneActive.id;
+        let oneActive = this.info.catalogRoot.find((item) => item.id == id);
+        if (!oneActive) {
+          oneActive = this.info.catalogRoot[0]
+          this.taboneActive = this.info.catalogRoot[0]
         }
+        oneActive.children &&
+          oneActive.children.forEach((item) => {
+            newVal.forEach((sub) => {
+              if (item == sub.id) {
+                temp.push(sub);
+              }
+            });
+          });
+        this.childTab = temp;
       },
     },
-    tablist: {
+    taboneActive: {
+      immediate: true,
       deep: true,
+      handler: function (newVal, oldVal) {
+        if (!newVal.id) {
+          this.taboneActive = this.info.catalogRoot[0];
+        }
+        let temp = [];
+        newVal.children &&
+          newVal.children.forEach((item) => {
+            this.info.catalogs.forEach((sub) => {
+              if (item == sub.id) {
+                temp.push(sub);
+              }
+            });
+          });
+        this.childTab = temp;
+        if (this.childTab.length == 1 || newVal != oldVal) {
+          this.tabtowActive = this.childTab[0];
+        }
+      },
+    },
+    tabtowActive: {
       immediate: true,
       handler: function (newVal) {
-        if (this.loadList) {
-          this.taboneActive = newVal[0] || { children: [] };
-          this.loadList = false;
+        if (!newVal) {
+          this.tabtowActive = this.childTab[0];
+        } else {
+          this.$emit("catalog", newVal);
+          this.scenes = this.info.scenes.filter((item) => {
+            return newVal.id == item.category;
+          });
         }
       },
     },
   },
 
   methods: {
-    getTabSceneList(catalogId = null) {
-      if (!catalogId) {
-        catalogId =
-          this.taboneActive.children.length <= 0
-            ? this.taboneActive.id
-            : this.tabtowActive.id;
-      }
-      getTabSceneList({ catalogId }, (data) => {
-        this.$store.commit("SetVrList", data.data || []);
-      });
-    },
 
     hadnleAddGroup() {
       this.$emit("addGroup", { type: 1, oper: "add", item: {} });
     },
-    clearinter() {
-      this.interval && clearInterval(this.interval);
-      this.interval = null;
-    },
-    Longpolling() {
-      this.clearinter();
-      this.interval = setInterval(() => {
-        // this.getPanoList(true)
-      }, LONGPOLLINGTIME * 1000);
-    },
+    
     uploadListSort() {
       let tmp = {};
       this.list.forEach((item, i) => {
@@ -241,9 +240,58 @@ export default {
       });
       setListSort(tmp);
     },
-    del(item, type) {
-      let list = this.tablist.concat(this.temptablist);
-      if (list.length <= 1 && type == "one") {
+
+    delTree(data, type) {
+      let fn = (ele) => {
+        let tmp = [];
+        this.info.catalogs.forEach((sub, i) => {
+          if (ele == sub.id) {
+            this.info.scenes.forEach((item) => {
+              if (sub.id != item.category) {
+                tmp.push(item);
+              }
+            });
+            this.info.scenes = tmp;
+            this.info.catalogs.splice(i, 1);
+          }
+        });
+      };
+      if (type == "one") {
+        data.children.forEach((ele) => {
+          fn(ele);
+        });
+        let idx = this.info.catalogRoot.findIndex((item) => item.id == data.id);
+        this.info.catalogRoot.splice(idx, 1);
+        this.taboneActive = this.info.catalogRoot[0];
+      }
+
+      if (type == "two") {
+        let id = this.taboneActive.id;
+        let oneActive = this.info.catalogRoot.find((item) => item.id == id);
+        let idx = oneActive.children.findIndex((item) => item == data.id);
+        oneActive.children.splice(idx, 1);
+        fn(data.id);
+
+        let temp = browser.CloneObject(this.taboneActive);
+        this.taboneActive = "";
+        this.taboneActive = temp;
+      }
+
+
+      this.delFirstScene()
+
+      this.$store.commit("SetInfo", this.info);
+    },
+
+    delFirstScene(){
+        if (this.info.firstScene) {
+          let firIdx = this.info.scenes.findIndex(item=>item.sceneCode == this.info.firstScene.sceneCode);
+          (firIdx>-1)&&(this.info.firstScene='')
+        }
+    },
+
+    del(data, type) {
+      if (this.info.catalogRoot.length <= 1 && type == "one") {
         return this.$alert({
           content: "请至少保留一个分组",
           ok: () => {
@@ -251,69 +299,32 @@ export default {
           },
         });
       }
+
       this.$confirm({
-        content: "是否删除?",
+        content: `分组“${data.name}”下所有${
+          type == "one" ? "二级分组和" : ""
+        }(场景/全景图)也都将会被删除,是否删除?`,
         ok: () => {
-          if (this.$isCacheId(item.id)) {
-            if (type == "one") {
-              let temp = this.temptablist.findIndex((ele) => {
-                return ele.id == item.id;
-              });
-              this.temptablist.splice(temp, 1);
-              this.$tips({ content: "删除成功", icon: "ok" });
-            } else {
-              let tempList =
-                this.$isCacheId(this.taboneActive.id)
-                  ? this.temptablist
-                  : this.tablist;
-              let parentIdx = tempList.findIndex((ele) => {
-                return ele.id == this.taboneActive.id;
-              });
-              let temp = this.taboneActive.children.findIndex((ele) => {
-                return ele.id == item.id;
-              });
-              this.taboneActive.children.splice(temp, 1);
-              tempList[parentIdx] = this.taboneActive;
-              this.$tips({ content: "删除成功", icon: "ok" });
-            }
-          } else {
-            delTab(item.id, () => {
-              this.$tips({ content: "删除成功", icon: "ok" });
-              this.$bus.emit("refresh");
-              this.getTabSceneList();
-            });
-          }
-          //
+          this.delTree(data, type);
+          this.$tips({ content: "删除成功", icon: "ok" });
         },
       });
     },
     delPano(item) {
       this.$confirm({
-        content: "是否删除?",
+        content: `${item.type=='4dkk'?'场景':'全景图'}“${item.sceneTitle}”下所有设置也都将会被删除,是否删除?`,
         ok: () => {
-          delPano(item.id, () => {
-            this.$tips({ content: "删除成功", icon: "ok" });
-            this.getTabSceneList();
-          });
+          this.delFirstScene()
+          let idx = this.info.scenes.findIndex(ele=>ele.id==item.id)
+          this.info.scenes.splice(idx,1)
+          this.$store.commit("SetInfo", this.info);
+          this.$tips({ content: "删除成功", icon: "ok" });
         },
       });
     },
   },
 
-  mounted() {
-    this.$bus.on("updateList", () => {
-      this.getTabSceneList();
-    });
-    this.$bus.on("changeActive", (data) => {
-      console.log('data',data);
-      this.tablist.forEach((item) => {
-        if (item.id == data.id) {
-          this.taboneActive = item;
-        }
-      });
-      this.getTabSceneList();
-    });
-  },
+  mounted() {},
   components: {
     draggable,
     tabList,

+ 72 - 138
src/views/information/index.vue

@@ -2,7 +2,7 @@
   <div>
     <setting @select="handleInitScene"></setting>
     <toolbar
-      @catalog="handleCatalog"
+      @catalog="data=>activeCataLog = data"
       @addPano="onAddPano"
       @addGroup="onAddGroup"
       @addScene="onAddScene"
@@ -25,8 +25,8 @@
             <input
               class="ui-input"
               type="text"
-              maxlength="50"
-              placeholder="请输入分组名,限50个字"
+              maxlength="15"
+              placeholder="请输入分组名,限15个字"
               v-model="currentTabAtri.name"
             />
           </div>
@@ -36,7 +36,11 @@
           <button class="ui-button cancel" @click="showAddGroup = false">
             取消
           </button>
-          <button class="ui-button submit" :class="{disable:!currentTabAtri.name}" @click="handleAddGroup()">
+          <button
+            class="ui-button submit"
+            :class="{ disable: !currentTabAtri.name }"
+            @click="handleAddGroup()"
+          >
             确定
           </button>
         </div>
@@ -47,7 +51,7 @@
       <div class="ui-message ui-message-confirm dark" style="width: 400px">
         <div class="ui-message-header">
           <span>重命名</span>
-          <span @click="showRename = false">
+          <span @click="handleRenameClose">
             <i class="iconfont icon_close"></i>
           </span>
         </div>
@@ -56,18 +60,22 @@
             <input
               class="ui-input"
               type="text"
-              maxlength="15"
+              maxlength="50"
               placeholder="输入名字"
-              v-model="reNameItem.reName"
+              v-model="reNameItem.sceneTitle"
             />
           </div>
         </div>
 
         <div class="ui-message-footer">
-          <button class="ui-button cancel" @click="showRename = false">
+          <button class="ui-button cancel" @click="handleRenameClose">
             取消
           </button>
-          <button class="ui-button submit" :class="{disable:!reNameItem.reName}" @click="handleRename()">
+          <button
+            class="ui-button submit"
+            :class="{ disable: !reNameItem.sceneTitle }"
+            @click="handleRename()"
+          >
             确定
           </button>
         </div>
@@ -96,13 +104,11 @@ import Toolbar from "./Toolbar";
 import Popup from "@/components/shared/popup";
 import {
   getSceneList,
-  editPanoName,
-  editCatalogName,
   getMaterialList,
 } from "@/api";
 import Table from "@/components/tableSelect";
 import { mapGetters } from "vuex";
-import { editTabName, savePanoToWorks } from "@/api";
+import { savePanoToWorks } from "@/api";
 
 export default {
   name: "home",
@@ -115,14 +121,13 @@ export default {
   computed: {
     ...mapGetters({
       sceneList: "sceneList",
-      tablist: "tablist",
-      temptablist: "temptablist",
+      info: "info",
+      backupInfo: "backupInfo"
     }),
   },
   data() {
     return {
       activeCataLog: "",
-      activeCataLog2: "",
       type: "scene",
       currentTabAtri: "",
       showAddGroup: false,
@@ -131,7 +136,7 @@ export default {
       showInitScene: true,
       reNameItem: {
         id: "",
-        reName: "",
+        sceneTitle: "",
       },
       key: "",
       paging: {
@@ -148,7 +153,7 @@ export default {
 
   watch: {
     "paging.pageNum": function () {
-      this.getSceneList();
+      this.type == "scene" ? this.getSceneList() : this.getMaterialList();
     },
     showList(newVal) {
       if (!newVal) {
@@ -164,13 +169,6 @@ export default {
   },
 
   methods: {
-    handleCatalog(data) {
-      if (data.level == 1) {
-        this.activeCataLog = data.data;
-      } else {
-        this.activeCataLog2 = data.data;
-      }
-    },
     handleInitScene() {
       this.showInitScene = true;
     },
@@ -179,59 +177,43 @@ export default {
       this.type == "scene" ? this.getSceneList() : this.getMaterialList();
     },
     handleSelect(data) {
-      let catalog = this.activeCataLog;
-      let catalog2 = this.activeCataLog2;
-
-      let cid = this.$isCacheId(catalog.id) ? null : catalog.id;
-      let cname = this.$isCacheId(catalog.id) ? catalog.name : null;
-
-      let c2id =
-        catalog2 &&
-       (this.$isCacheId(catalog2.id) ? null : catalog2.id);
-      let c2name =
-        catalog2 &&
-        (this.$isCacheId(catalog2.id) ? catalog2.name : null);
-
-      let params = {
-        catalogId: catalog2 ? c2id : cid,
-        catalogName: catalog2 ? c2name : cname,
-        parentId: catalog2 ? cid : null,
-        parentName: catalog2 ? cname : null,
-        scenes: [],
-      };
-
+     let params = ''
+     let id = this.info.scenes.length+1
       if (this.type == "scene") {
-        params.scenes = data.map((item) => {
+        params = data.map((item) => {
           return {
             icon: item.thumb,
             sceneCode: item.num,
             sceneTitle: item.sceneName,
             type: "4dkk",
+            category:this.activeCataLog.id,
+            id
           };
         });
       } else {
-        params.scenes = data.map((item) => {
+        params = data.map((item) => {
           return {
             icon: item.icon,
             sceneCode: item.sceneCode,
             sceneTitle: item.name,
+            category:this.activeCataLog.id,
             type: "pano",
+            id
           };
         });
       }
 
-      savePanoToWorks(params, (data) => {
-        let cid = !catalog2 ? catalog.id : catalog2.id;
-
-        let temp = this.temptablist.findIndex((item) => {
-          return item.id == cid;
-        });
-
-        this.temptablist.splice(temp, 1);
-        this.tablist.push(data.data[0]);
-        this.$bus.emit("changeActive", data.data[0]);
-        this.showList = false;
+      params.forEach(item => {
+        let temp = this.info.scenes.find(sub=>sub.sceneCode == item.sceneCode)
+        if (temp) {
+            this.$tips({ content: `已添加${item.type=='4dkk'?'场景':'全景图'}${item.sceneTitle},无法重复添加`, icon: "ok" });
+            return
+        }
+        !temp&&this.info.scenes.push(item)
       });
+
+      this.$store.commit("SetInfo", this.info);
+      this.showList = false;
     },
 
     changeCurrent(data) {
@@ -245,27 +227,21 @@ export default {
     },
 
     onRename(data) {
-      this.reNameItem.id = data.id;
-      this.reNameItem.reName = data.sceneTitle;
+      this.reNameItem = data;
       this.showRename = true;
     },
 
+    handleRenameClose(){
+      this.showRename = false
+      this.$store.commit("SetInfo", this.backupInfo);
+    },
+
     handleRename() {
       if (!this.reNameItem) {
         return this.$alert({ content: "请输入名字" });
       }
-
-      editPanoName(
-        {
-          id: this.reNameItem.id,
-          name: this.reNameItem.reName,
-        },
-        () => {
-          this.$tips({ content: "重命名成功", icon: "ok" });
-          this.showRename = false;
-          this.$bus.emit("refresh");
-        }
-      );
+      this.$tips({ content: "重命名成功", icon: "ok" });
+      this.showRename = false;
     },
 
     onAddGroup(data) {
@@ -277,91 +253,49 @@ export default {
       if (!this.currentTabAtri.name) {
         return this.$alert({ content: "请输入名字" });
       }
-
       let tmp = this.currentTabAtri.item;
-
-
       if (this.currentTabAtri.oper == "edit") {
-        if (this.$isCacheId(tmp.id)) {
-          tmp.name= this.currentTabAtri.name
-          this.$tips({ content: "重命名成功", icon: "ok" });
-          this.showAddGroup = false;
-        }
-        else{
-          editCatalogName(
-            {
-              id: tmp.id,
-              name: this.currentTabAtri.name,
-            },
-            () => {
-              this.$tips({ content: "重命名成功", icon: "ok" });
-              this.showAddGroup = false;
-              this.$bus.emit("refresh");
-            }
-          );
-        }
-
-        return;
-      }
-
-
-      let temp = {
-        children: [],
-        id: "tmp" + this.$randomWord(true,6,8),
-        name: this.currentTabAtri.name,
-        scenes: [],
-      };
-
-      if (this.currentTabAtri.type == 1) {
-        this.temptablist.push(temp);
+        tmp.name = this.currentTabAtri.name;
       } else {
-        if (this.$isCacheId(tmp.parentId)) {
-          this.temptablist.forEach((item) => {
-            if (item.id == tmp.parentId) {
-              item.children.push(temp);
-            }
+        if (this.currentTabAtri.type == 1) {
+          let id = 'c_'+this.$randomWord(true,8,8)
+          this.info.catalogRoot.push({
+            id: 'r_'+this.$randomWord(true,8,8),
+            name: this.currentTabAtri.name,
+            children: [id],
+          });
+          this.info.catalogs.push({
+            id,
+            name: '默认二级分组',
           });
-        } else {
-          this.tablist.forEach((item) => {
-            if (item.id == tmp.parentId) {
-              if (item.children.length <= 0) {
-                editTabName(
-                  {
-                    id: tmp.id,
-                    name: this.currentTabAtri.name,
-                    parentId: tmp.parentId,
-                  },
-                  () => {
-                    this.$tips({ content: "操作成功", icon: "ok" });
-                    this.showAddGroup = false;
-                    this.$bus.emit("refresh");
-                  }
-                );
-              } else {
-                item.children.push(temp);
-              }
-            }
+          console.log(this.info.catalogs);
+        }
+        if (this.currentTabAtri.type == 2) {
+          let id = 'c_'+this.$randomWord(true,8,8)
+          let item = this.info.catalogRoot.find(
+            (item) => item.id == tmp.parentId
+          );
+          item.children.push(id);
+          this.info.catalogs.push({
+            id,
+            name: this.currentTabAtri.name,
           });
         }
       }
 
+
+      this.$store.commit("SetInfo", this.info);
       this.$tips({ content: "操作成功", icon: "ok" });
       this.showAddGroup = false;
     },
 
     onAddScene() {
-      if (!this.activeCataLog) {
-        return this.$alert({ content: "请新建并选择标签" });
-      }
       this.type = "scene";
       this.getSceneList();
       this.showList = true;
     },
 
     onAddPano() {
-      if (!this.activeCataLog) {
-        return this.$alert({ content: "请新建并选择标签" });
-      }
       this.type = "pano";
       this.getMaterialList();
       this.showList = true;

+ 15 - 3
src/views/material/audio/index.vue

@@ -19,7 +19,10 @@
                 
 
       <button @mouseover.stop="showList=true"  @click="$refs.uploadFile.click();" class="ui-button ui-button-rect submit"><span>上传素材</span><i class="iconfont iconbs_upload"></i>
-        <upload ref="uploadFile" accept-type="audio/mp3" media-type="audio" :limit="20"  @file-change="onFileChange"></upload>
+        <upload ref="uploadFile"
+          :failString="'格式错误,请上传20MB以内、mp3格式的音频'"
+          :limitFailStr="'过大,请上传20MB以内、mp3格式的音频'"
+         accept-type="audio/mp3" media-type="audio" :limit="20"  @file-change="onFileChange"></upload>
         <div @click.stop class="upload-list" v-if="showList">
           <div class="top">
             <span>上传列表({{uploadList.length}})</span>
@@ -62,7 +65,7 @@
           <div class="audio" v-else-if="sub.type=='audio'" >
               <v-audio :idleft="`_${$randomWord(true,8,8)}`" :idright="`_${$randomWord(true,8,8)}`" :myAudioUrl="data"></v-audio>
           </div>
-          <span v-else :style="{fontWeight:sub.fontweight,color:'#202020'}">{{data||'-'}}</span>
+          <span v-else @click="sub.fontweight&&($bus.emit('toggleAudio',item.ossPath))" :style="{fontWeight:sub.fontweight,color:'#202020'}">{{data||'-'}}</span>
         </div>
       </tableList>
       <div class="nodata" v-if="list.length == 0">
@@ -180,12 +183,21 @@ export default {
           status:'上传中',
           name:item.name
         }
+
+        if (item.name.toLowerCase().indexOf("mp3") <= -1) {
+          return this.$alert({
+              content: `“${item.name}”格式错误,请上传20MB以内、mp3格式的音频`
+          });
+        }
+        
         let tname= item.name.substring(0, item.name.lastIndexOf("."));
-         if (tname.length > 50) {
+        
+        if (tname.length > 50) {
           return this.$alert({
               content: `“${item.name}”名称过长,请上传标题在50字以内的音频`
             });
         }
+        
         this.uploadList.push(tmp)
         canUploadList.push(item)
       }

+ 11 - 4
src/views/material/image/index.vue

@@ -18,7 +18,10 @@
                 
 
       <button @mouseover.stop="showList=true"  @click="$refs.uploadFile.click();" class="ui-button ui-button-rect submit"><span>上传素材</span><i class="iconfont iconbs_upload"></i>
-        <upload ref="uploadFile" accept-type="image/png,image/jpeg" media-type="image" :limit="10"  @file-change="onFileChange"></upload>
+        <upload ref="uploadFile"
+        :failString="'格式错误,请上传10MB以内、jpg/png格式的图片'"
+        :limitFailStr="'过大,请上传10MB以内、jpg/png格式的图片'"
+         accept-type="image/png,image/jpeg" media-type="image" :limit="10"  @file-change="onFileChange"></upload>
         <div @click.stop class="upload-list" v-if="showList">
           <div class="top">
             <span>上传列表({{uploadList.length}})</span>
@@ -58,10 +61,10 @@
               </div>
             </i>
           </div>
-          <div class="img" v-else-if="sub.type=='image'" @click="(showPreview = true), (popupItem = item)">
-            <img :src="data" alt="">
+          <div class="img" v-else-if="sub.type=='image'">
+            <img :id="'img'+item.id" v-viewer :src="data+`?${Math.random()}`" alt="">
           </div>
-          <span v-else :style="{fontWeight:sub.fontweight,color:'#202020'}">{{data||'-'}}</span>
+          <span v-else @click="sub.fontweight&&(viewImg('img'+item.id))" :style="{fontWeight:sub.fontweight,color:'#202020'}">{{data||'-'}}</span>
         </div>
       </tableList>
       <div class="nodata" v-if="list.length == 0">
@@ -149,6 +152,10 @@ export default {
     }
   },
   methods:{
+    viewImg(id){
+      const viewer = this.$el.querySelector('#'+id).$viewer
+      viewer.show()
+    },
     handleRename(data){
       editMaterial({
           id:this.popupItem.id,

+ 113 - 28
src/views/material/pano/index.vue

@@ -41,7 +41,11 @@
           <ul v-if="uploadList.length > 0">
             <li v-for="(item, i) in uploadList" :key="i">
               <span>{{ item.name }}</span>
-              <span class="success" :class="item.status.indexOf('失败')>-1?'error':''">{{item.status}}</span>
+              <span
+                class="success"
+                :class="item.status == 2 || item.status == 5 ? 'error' : ''"
+                >{{ StrStatus[item.status] }}</span
+              >
               <i @click="delUploadItem(i)" class="iconfont icon_close"></i>
             </li>
           </ul>
@@ -95,11 +99,16 @@
             v-else-if="sub.type == 'image'"
             @click="(showPreview = true), (popupItem = item)"
           >
-            <img :src="data" alt="" />
+            <img :src="data + `?${Math.random()}`" alt="" />
           </div>
-          <span v-else :style="{fontWeight:sub.fontweight,color:'#202020'}">{{
-            data || "-"
-          }}</span>
+          <span
+            v-else
+            @click="
+              sub.fontweight && ((showPreview = true), (popupItem = item))
+            "
+            :style="{ fontWeight: sub.fontweight, color: '#202020' }"
+            >{{ data || "-" }}</span
+          >
         </div>
       </tableList>
       <div class="nodata" v-if="list.length == 0">
@@ -146,7 +155,7 @@ import preview from "../popup/preview";
 import cover from "../popup/cover";
 import Paging from "../components/paging";
 import Upload from "@/components/shared/uploads/UploadMultiple";
-import { getImgWH,changeByteUnit } from "@/utils/file";
+import { getImgWH, changeByteUnit } from "@/utils/file";
 
 import {
   getMaterialList,
@@ -154,10 +163,20 @@ import {
   editMaterial,
   delMaterial,
   uploadCover,
+  checkMStatus,
 } from "@/api";
 
-const TYPE = "pano";
+// 1切图,2失败,3成功
 
+const TYPE = "pano";
+const LONGPOLLINGTIME = 10;
+let StrStatus = {
+  1: "制作中",
+  2: "制作失败",
+  3: "制作成功",
+  4: "上传中",
+  5: "上传失败",
+};
 export default {
   components: {
     tableList,
@@ -170,6 +189,8 @@ export default {
   },
   data() {
     return {
+      StrStatus,
+      isLongPolling: false,
       showRename: false,
       showPreview: false,
       showCover: false,
@@ -203,8 +224,27 @@ export default {
     "paging.pageNum": function () {
       this.getMaterialList();
     },
+    isLongPolling: {
+      handler: function (newVal) {
+        if (!newVal) {
+          this.clearinter();
+        } else {
+          this.Longpolling();
+        }
+      },
+    },
   },
   methods: {
+    clearinter() {
+      this.interval && clearInterval(this.interval);
+      this.interval = null;
+    },
+    Longpolling() {
+      this.clearinter();
+      this.interval = setInterval(() => {
+        this._checkMStatus(true);
+      }, LONGPOLLINGTIME * 1000);
+    },
     handleRename(data) {
       editMaterial(
         {
@@ -220,12 +260,17 @@ export default {
       );
     },
     handlePanoCover(data) {
+      if (data.indexOf("http") > -1) {
+        this.showCover = false;
+        this.popupItem = "";
+        return;
+      }
       uploadCover({ file: data, filename: "cover.jpg" }, (res) => {
         if (res.code == 0) {
           editMaterial(
             {
               id: this.popupItem.id,
-              icon:res.data,
+              icon: res.data,
             },
             () => {
               this.$tips({ content: "设置成功", icon: "ok" });
@@ -240,6 +285,33 @@ export default {
     delUploadItem(index) {
       ~index && this.uploadList.splice(index, 1);
     },
+
+    _checkMStatus(islongpolling = null) {
+      let ids = this.uploadList.filter((item) => item.id);
+      if (ids.length > 0) {
+        checkMStatus(
+          {
+            ids: ids.map((item) => item.id),
+            islongpolling,
+          },
+          (res) => {
+            let tmp = [];
+            this.uploadList.forEach((item) => {
+              let titem = res.data.find((sub) => item.id == sub.id);
+              if (titem) {
+                tmp.push(titem);
+              } else {
+                tmp.push(item);
+              }
+            });
+            this.uploadList = tmp;
+            if (!tmp.some((item) => item == 1)) {
+              this.isLongPolling = false;
+            }
+          }
+        );
+      }
+    },
     del(item) {
       this.$confirm({
         content: "是否删除?",
@@ -256,22 +328,28 @@ export default {
       for (let i = 0; i < file.files.length; i++) {
         let item = file.files[i];
         let tmp = {
-          status: "上传中",
+          statusStr: "上传中",
+          status: 4,
+          uid: `u_${this.$randomWord(true, 8, 8)}`,
           name: item.name,
         };
+        item.uid = tmp.uid;
         if (item.type.indexOf("jpeg") <= -1) {
           return this.$alert({
-                    content: '请上传jpg格式的全景图'
-                });
+            content: `“${item.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+          });
         }
-        let tname= item.name.substring(0, item.name.lastIndexOf("."));
-         if (tname.length > 50) {
+        let tname = item.name.substring(0, item.name.lastIndexOf("."));
+        if (tname.length > 50) {
           return this.$alert({
-              content: `“${item.name}”名称过长,请上传标题在50字以内的全景图片`
-            });
+            content: `“${item.name}”名称过长,请上传标题在50字以内的全景图片`,
+          });
         }
         this.uploadList.push(tmp);
-        canUploadList.push(item);
+        canUploadList.push({
+          file: item,
+          list: { ...tmp },
+        });
       }
 
       let p = [];
@@ -287,16 +365,15 @@ export default {
             let { width, height } = data.WH;
             if (width != 2 * height) {
               let idx = this.uploadList.findIndex(
-                (sub) => sub.name == data.file.name
+                (sub) => sub.uid == data.list.uid
               );
               ~idx && this.uploadList.splice(idx, 1);
               return this.$alert({
-                    content: '全景图片必须为2:1比例'
-                });
+                content: `“${data.file.name}”格式错误,请上传2:1、120MB以内、jpg格式的全景图片`,
+              });
             }
             let params = {};
             params["file"] = data.file;
-
             let promise = new Promise((resolve, reject) => {
               uploadMaterial(
                 params,
@@ -315,11 +392,19 @@ export default {
           Promise.all(pp).then((response) => {
             if (response.length > 0) {
               response.forEach((item, i) => {
-                if (item.code != 0) {
-                  this.uploadList[i].status = "上传失败";
-                } else {
-                  this.uploadList.splice(i,1)
+                let idx = this.uploadList.findIndex(sub=>sub.name == item.name)
+                if (idx>-1) {
+                  if (item.code != 0) {
+                    this.uploadList[idx].status = 5;
+                  } else {
+                    this.uploadList[idx] = {
+                      ...this.uploadList[idx],
+                      ...item.data,
+                    };
+                    this.isLongPolling = true;
+                  }
                 }
+                
               });
               this.getMaterialList();
             }
@@ -340,10 +425,10 @@ export default {
           type: TYPE,
         },
         (data) => {
-          this.list = data.data.list.map(i=>{
-            i.fileSize = changeByteUnit(Number(i.fileSize))
-            return i
-          })
+          this.list = data.data.list.map((i) => {
+            i.fileSize = changeByteUnit(Number(i.fileSize));
+            return i;
+          });
           this.paging.pageNum = data.data.pageNum;
           this.paging.pageSize = data.data.pageSize;
           this.paging.total = data.data.total;

+ 10 - 2
src/views/material/popup/cover.vue

@@ -45,7 +45,15 @@ export default {
   },
   data(){
     return {
-      img:''
+      img: this.item.icon||''
+    }
+  },
+  watch:{
+    item:{
+      deep:true,
+      handler:function (newVal) {
+        this.img = newVal.icon
+      }
     }
   },
   methods:{
@@ -58,8 +66,8 @@ export default {
       if (!this.img) {
         return this.$alert({ content: "请点击“截图”按钮截取封面" });
       }
+      
       this.$emit('panocover',this.img)
-        
     }
   }
 }

+ 20 - 4
src/views/material/popup/preview.vue

@@ -14,7 +14,12 @@
                <img :src="require('@/assets/images/icons/tool_full@2x.png')" alt="">
              </span>
           </template>
-          <iframe v-else-if="item.type=='pano'" :src="'./vr.html?vr='+item.sceneCode" frameborder="0"></iframe>
+          <template v-else-if="item.type=='pano'">
+            <iframe ref="pifr" :src="'./vr.html?vr='+item.sceneCode" frameborder="0"></iframe>
+            <span class="scale" @click="onFullScreen">
+               <img :src="require('@/assets/images/icons/tool_full@2x.png')" alt="">
+             </span>
+          </template>
           <video v-else controls autoplay :src="item.ossPath"></video>
         </div>
       </div>
@@ -37,14 +42,17 @@ export default {
       // image:'icon',
     }
     return {
-      typeStr
+      typeStr,
+      isFullscreen:false
     }
   },
   methods:{
     viewImg(){
       const viewer = this.$el.querySelector('.v-image').$viewer
-      console.log(viewer);
       viewer.show()
+    },
+    onFullScreen() {
+      this.$refs.pifr.contentWindow.postMessage({event:'onfull'},'*')
     }
   }
 }
@@ -53,6 +61,9 @@ export default {
 <style lang="less" scoped>
 .ui-message-confirm{
   border-radius: 0;
+  top: unset;
+  left: unset;
+  transform: none;
   .icon_close{
     color: #909090;
   }
@@ -63,10 +74,15 @@ export default {
     width: 100%;
     font-size: 0;
     position: relative;
-    >img,>video,>iframe{
+    >video,>iframe{
       width: 100%;
       height: 540px;
     }
+    >img{
+      width: auto;
+      max-height: 80vh;
+      height: auto;
+    }
     >.scale{
       font-size: 0;
       bottom: 10px;

+ 1 - 1
src/views/material/popup/share.vue

@@ -11,7 +11,7 @@
           <div>
             <div>作品二维码</div>
             <div>
-              <img :src="item.qrCode||$thumb" alt="">
+              <img :src="(item.qrCode+`?${Math.random()}`)||$thumb" alt="">
               <button @click="downloadImg(item.qrCode)" :class="`ui-button ui-button-rect submit`">下载</button>
             </div>
             <div>作品链接</div>

+ 5 - 2
src/views/material/video/index.vue

@@ -18,7 +18,10 @@
                 
 
       <button @mouseover.stop="showList=true"  @click="$refs.uploadFile.click();" class="ui-button ui-button-rect submit"><span>上传素材</span><i class="iconfont iconbs_upload"></i>
-        <upload ref="uploadFile" accept-type="video/mp4" media-type="video" :limit="200"  @file-change="onFileChange"></upload>
+        <upload ref="uploadFile"
+        :failString="'格式错误,请上传200MB以内、mp4格式的视频'"
+        :limitFailStr="'过大,请上传200MB以内、mp4格式的视频'"
+         accept-type="video/mp4" media-type="video" :limit="200"  @file-change="onFileChange"></upload>
         <div @click.stop class="upload-list" v-if="showList">
           <div class="top">
             <span>上传列表({{uploadList.length}})</span>
@@ -63,7 +66,7 @@
           >
             <img :src="`${data}`||$thumb" alt="">
           </div>
-          <span v-else :style="{fontWeight:sub.fontweight,color:'#202020'}">{{data||'-'}}</span>
+          <span v-else @click="sub.fontweight&&((showPreview = true), (popupItem = item))" :style="{fontWeight:sub.fontweight,color:'#202020'}">{{data||'-'}}</span>
         </div>
       </tableList>
       <div class="nodata" v-if="list.length == 0">

+ 45 - 14
src/views/material/works/index.vue

@@ -8,7 +8,7 @@
           <div>
             <input
               type="text"
-              placeholder="搜索文件夹或素材"
+              placeholder="搜索全景作品"
               v-model="searchKey"
               @keyup.enter="(paging.current = 1) && getWorksList()"
             >
@@ -20,16 +20,16 @@
     <ul class="w-list">
       <li v-for="(item,i) in list" :key="i">
         <div class="view" :title="item.visit">
-          <i class="iconfont iconlist_views"></i>{{item.visit}}
+          <i class="iconfont iconlist_views"></i>{{item.visit>10000?'1w+':item.visit}}
         </div>
         <div class="share" @click="openShare(item)">
           <i class="iconfont iconbs_share"></i>
         </div>
-        <div class="img">
+        <div class="img" @click="handlePreview(item)">
           <img class="real" :src="item.icon||$thumb" alt="" />
         </div>
         <div class="li-info">
-          <span class="shenglve">{{item.name}}</span>
+          <span class="shenglve"  @click="handlePreview(item)">{{item.name||'无标题'}}</span>
           <div>
             <span>{{item.createTime}}</span>
             <div>
@@ -51,32 +51,42 @@
         @changeCurrent="changeCurrent"
       />
     </div>
-    <share :show='showShare' :item="shareItem" @share="handleShare" @close="showShare=false"></share>
+    <share :show='showShare' :item="shareItem" @close="showShare=false"></share>
+    <preview
+      v-if="showItem"
+      :name="showItem.name"
+      :show="showPreview"
+      :ifr="`./show.html?id=${showItem.id}&vr=${showItem.firstScene?showItem.firstScene.sceneCode:showItem.scenes[0].sceneCode}`"
+      @close="showPreview = false"
+    />
   </div>
 </template>
 
 <script>
 import Paging from '../components/paging'
 import share from '../popup/share'
-
-
+import preview from "@/components/preview";
 
 import {
   addWorks,
   getWorksList,
-  delWorks
+  delWorks,
+  getPanoInfo
 } from "@/api";
 
 export default {
   components:{
     Paging,
-    share
+    share,
+    preview
   },
   data(){
     return {
       list:[],
       searchKey:'',
       showShare:false,
+      showPreview:false,
+      showItem:'',
       shareItem:'',
       paging: {
         pageSize: 12,
@@ -96,13 +106,32 @@ export default {
     }
   },
   methods:{
+
     openShare(data){
-      this.showShare = true
-      this.shareItem = data
-      console.log(this.shareItem);
+      getPanoInfo(data.id, (data) => {
+        if (data.scenes.length<=0) {
+          return this.$tips({
+            content: "链接未生成,请编辑作品添加素材"
+          });
+        }
+        this.showShare = true
+        this.shareItem = data
+      })
     },
-    handleShare(){
-
+    
+    handlePreview(item){
+      getPanoInfo(item.id, (data) => {
+        if (data.scenes.length<=0) {
+          return this.$tips({
+            content: "链接未生成,请编辑作品添加素材"
+          });
+        }
+        this.showItem = {
+          ...item,
+          ...data
+        }
+        this.showPreview=true
+      })
     },
     changeCurrent(data){
       this.paging.pageNum = data
@@ -226,6 +255,7 @@ export default {
         height: 285px;
         position: relative;
         overflow: hidden;
+        cursor: pointer;
         .real{
           height: 100%;
           position: absolute;
@@ -248,6 +278,7 @@ export default {
           overflow: hidden;
           white-space: nowrap;
           width: 100%;
+          cursor: pointer;
         }
         >div{
           display: flex;

+ 2 - 2
src/views/screen/Setting.vue

@@ -4,7 +4,7 @@
       <div class="ui-title">初始画面</div>
       <div class="ui-remark">初始画面为进入场景时第一画面,请拖动全景图选择合适的画面设置。</div>
       <div class="preview">
-        <img :src="initImg" v-if="initImg" alt="">
+        <img :src="initImg+`?${Math.random()}`" v-if="initImg" alt="">
         <div class="tips" v-else>
           <i class="iconfont iconphotoview" style="font-size: 40px"></i>
         </div>
@@ -20,7 +20,7 @@ export default {
   },
   data(){
     return {
-      initImg:localStorage.initImg || ''
+      initImg:''
     }
   },
   mounted(){

+ 1 - 1
src/views/screen/Toolbar.vue

@@ -20,7 +20,7 @@
               <i class="iconfont iconscene_map_3d" :class="{'iconjump':item.type!=='house'}"></i>
             </div>
             <div class="img">
-              <img :src="item.icon" alt="">
+              <img :src="item.icon+`?${Math.random()}`" alt="">
             </div>
             <div class="ui-title">
               <span>{{item.fileName}}</span>