tremble vor 2 Jahren
Ursprung
Commit
8ef6ec0f58
100 geänderte Dateien mit 13606 neuen und 71011 gelöschten Zeilen
  1. 0 64101
      package-lock.json
  2. 505 0
      packages/qjkankan-components/package-lock.json
  3. 2 1
      packages/qjkankan-kankan-view/.env.development
  4. 2217 2209
      packages/qjkankan-kankan-view/package-lock.json
  5. 1 0
      packages/qjkankan-kankan-view/package.json
  6. 1 1
      packages/qjkankan-kankan-view/public/spg.html
  7. 539 0
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/demo.css
  8. 3385 0
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/demo_index.html
  9. 571 0
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.css
  10. 1 0
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.js
  11. 982 0
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.json
  12. BIN
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.ttf
  13. BIN
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.woff
  14. BIN
      packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.woff2
  15. 24 2
      packages/qjkankan-kankan-view/src/app.js
  16. 0 485
      packages/qjkankan-kankan-view/src/app.vue
  17. BIN
      packages/qjkankan-kankan-view/src/assets/images/browser/browser_Chrome.png
  18. BIN
      packages/qjkankan-kankan-view/src/assets/images/browser/browser_Edge.png
  19. BIN
      packages/qjkankan-kankan-view/src/assets/images/browser/browser_Firefox.png
  20. BIN
      packages/qjkankan-kankan-view/src/assets/images/browser/browser_Safari.png
  21. BIN
      packages/qjkankan-kankan-view/src/assets/images/browser/pic_update.png
  22. 9 4
      packages/qjkankan-kankan-view/src/components/Controls/BottomControl.vue
  23. 3 1
      packages/qjkankan-kankan-view/src/components/Controls/FloorSwitch.vue
  24. 5 5
      packages/qjkankan-kankan-view/src/components/Controls/LeftButtons.vue
  25. 27 1
      packages/qjkankan-kankan-view/src/components/Controls/RightButtons.vue
  26. 64 0
      packages/qjkankan-kankan-view/src/components/Controls/rules/index.vue
  27. 411 0
      packages/qjkankan-kankan-view/src/components/Controls/tours.vue
  28. 12 11
      packages/qjkankan-kankan-view/src/components/Information/View.Pc.vue
  29. 7 6
      packages/qjkankan-kankan-view/src/components/Information/index.vue
  30. 44 36
      packages/qjkankan-kankan-view/src/components/Tags/constant.js
  31. 0 353
      packages/qjkankan-kankan-view/src/components/Tags/goods-list.vue
  32. 170 172
      packages/qjkankan-kankan-view/src/components/Tags/index.vue
  33. 0 130
      packages/qjkankan-kankan-view/src/components/Tags/link-manage.vue
  34. 0 104
      packages/qjkankan-kankan-view/src/components/Tags/metas-upload.vue
  35. 154 0
      packages/qjkankan-kankan-view/src/components/Tags/metas/image-view.vue
  36. 1 1
      packages/qjkankan-kankan-view/src/components/Tags/metas/metas-audio.vue
  37. 149 42
      packages/qjkankan-kankan-view/src/components/Tags/metas/metas-image.vue
  38. 5 5
      packages/qjkankan-kankan-view/src/components/Tags/metas/metas-video.vue
  39. 1 1
      packages/qjkankan-kankan-view/src/components/Tags/metas/metas-web.vue
  40. 145 0
      packages/qjkankan-kankan-view/src/components/Tags/metas/scale/index.js
  41. 8 10
      packages/qjkankan-kankan-view/src/components/Tags/show-tag.vue
  42. 0 332
      packages/qjkankan-kankan-view/src/components/Tags/style-icon.vue
  43. 0 230
      packages/qjkankan-kankan-view/src/components/Tags/tag-info.vue
  44. 20 7
      packages/qjkankan-kankan-view/src/components/Tags/tag-view.vue
  45. 0 102
      packages/qjkankan-kankan-view/src/components/Tags/treasure.vue
  46. 0 116
      packages/qjkankan-kankan-view/src/components/Tags/waterfall.vue
  47. 168 0
      packages/qjkankan-kankan-view/src/components/shared/Checkbrowser.vue
  48. 1 1
      packages/qjkankan-kankan-view/src/i18n/index.js
  49. 0 13
      packages/qjkankan-kankan-view/src/main.js
  50. 15 0
      packages/qjkankan-kankan-view/src/pages/DesignOption/index.vue
  51. 51 14
      packages/qjkankan-kankan-view/src/pages/SPG.vue
  52. 47 10
      packages/qjkankan-kankan-view/src/pages/spg.js
  53. 26 3
      packages/qjkankan-kankan-view/src/store/index.js
  54. 12 0
      packages/qjkankan-kankan-view/src/utils/fns/Delegate.js
  55. 53 0
      packages/qjkankan-kankan-view/src/utils/messageHandler.js
  56. 18 0
      packages/qjkankan-kankan-view/src/utils/track.js
  57. 2054 1951
      packages/qjkankan-view/package-lock.json
  58. 3 3
      packages/qjkankan-view/package.json
  59. 2 1
      packages/qjkankan-view/public/show.html
  60. 4 0
      packages/qjkankan-view/public/static/lib/howler/howler.min.js
  61. BIN
      packages/qjkankan-view/public/static/lib/krpano/skin/krpano-roundlogo.png
  62. BIN
      packages/qjkankan-view/public/static/lib/krpano/skin/masking.png
  63. 312 229
      packages/qjkankan-view/public/static/lib/krpano/skin/vtourskin.xml
  64. 1 1
      packages/qjkankan-view/public/static/lib/krpano/tour.xml
  65. 23 0
      packages/qjkankan-view/src/assets/images/icon/3d_normal.svg
  66. 31 0
      packages/qjkankan-view/src/assets/images/icon/3d_selected.svg
  67. 23 0
      packages/qjkankan-view/src/assets/images/icon/collect.svg
  68. 26 0
      packages/qjkankan-view/src/assets/images/icon/commentary.svg
  69. 24 0
      packages/qjkankan-view/src/assets/images/icon/commentary_disabled.svg
  70. 28 0
      packages/qjkankan-view/src/assets/images/icon/function_off.svg
  71. 28 0
      packages/qjkankan-view/src/assets/images/icon/function_on.svg
  72. 28 0
      packages/qjkankan-view/src/assets/images/icon/link.svg
  73. 24 0
      packages/qjkankan-view/src/assets/images/icon/more.svg
  74. 23 0
      packages/qjkankan-view/src/assets/images/icon/music.svg
  75. 24 0
      packages/qjkankan-view/src/assets/images/icon/music_disabled.svg
  76. 24 0
      packages/qjkankan-view/src/assets/images/icon/pause01.svg
  77. 23 0
      packages/qjkankan-view/src/assets/images/icon/plane_normal.svg
  78. 24 0
      packages/qjkankan-view/src/assets/images/icon/plane_selected.svg
  79. 0 0
      packages/qjkankan-view/src/assets/images/icon/player_pic01.png
  80. 24 0
      packages/qjkankan-view/src/assets/images/icon/playing01.svg
  81. 26 0
      packages/qjkankan-view/src/assets/images/icon/roaming_normal.svg
  82. 24 0
      packages/qjkankan-view/src/assets/images/icon/roaming_selected.svg
  83. 29 0
      packages/qjkankan-view/src/assets/images/icon/rotation.svg
  84. 26 0
      packages/qjkankan-view/src/assets/images/icon/rotation_disabled.svg
  85. 26 0
      packages/qjkankan-view/src/assets/images/icon/share.svg
  86. 25 0
      packages/qjkankan-view/src/assets/images/icon/telephone.svg
  87. 23 0
      packages/qjkankan-view/src/assets/images/icon/text.svg
  88. 26 0
      packages/qjkankan-view/src/assets/images/icon/vr.svg
  89. 0 15
      packages/qjkankan-view/src/assets/scss/_base-vars.scss
  90. 227 243
      packages/qjkankan-view/src/assets/scss/theme.scss
  91. 64 4
      packages/qjkankan-view/src/components/Fdkk/index.vue
  92. 42 8
      packages/qjkankan-view/src/components/Pano/index.vue
  93. 166 32
      packages/qjkankan-view/src/components/UIGather/control.vue
  94. 92 0
      packages/qjkankan-view/src/components/UIGather/control/link.vue
  95. 108 0
      packages/qjkankan-view/src/components/UIGather/control/telephone.vue
  96. 87 0
      packages/qjkankan-view/src/components/UIGather/control/text.vue
  97. 6 13
      packages/qjkankan-view/src/components/UIGather/index.vue
  98. 1 1
      packages/qjkankan-view/src/components/UIGather/list.vue
  99. 1 1
      packages/qjkankan-view/src/components/UIGather/logo.vue
  100. 0 0
      packages/qjkankan-view/src/components/UIGather/menu.vue

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 64101
package-lock.json


+ 505 - 0
packages/qjkankan-components/package-lock.json

@@ -0,0 +1,505 @@
+{
+  "name": "@qjkankan/components",
+  "version": "1.2.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "@qjkankan/components",
+      "version": "1.2.0",
+      "dependencies": {
+        "c-scrollbar": "^0.1.6",
+        "vue-cropper": "^1.0.2",
+        "vue3-smooth-scrollbar": "^1.0.2"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.19.3",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.19.3.tgz",
+      "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==",
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.40.tgz",
+      "integrity": "sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA==",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz",
+      "integrity": "sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw==",
+      "dependencies": {
+        "@vue/compiler-core": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.40.tgz",
+      "integrity": "sha512-tzqwniIN1fu1PDHC3CpqY/dPCfN/RN1thpBC+g69kJcrl7mbGiHKNwbA6kJ3XKKy8R6JLKqcpVugqN4HkeBFFg==",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.40",
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/compiler-ssr": "3.2.40",
+        "@vue/reactivity-transform": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7",
+        "postcss": "^8.1.10",
+        "source-map": "^0.6.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.40.tgz",
+      "integrity": "sha512-80cQcgasKjrPPuKcxwuCx7feq+wC6oFl5YaKSee9pV3DNq+6fmCVwEEC3vvkf/E2aI76rIJSOYHsWSEIxK74oQ==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.40.tgz",
+      "integrity": "sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==",
+      "dependencies": {
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/reactivity-transform": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.40.tgz",
+      "integrity": "sha512-HQUCVwEaacq6fGEsg2NUuGKIhUveMCjOk8jGHqLXPI2w6zFoPrlQhwWEaINTv5kkZDXKEnCijAp+4gNEHG03yw==",
+      "dependencies": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.40.tgz",
+      "integrity": "sha512-U1+rWf0H8xK8aBUZhnrN97yoZfHbjgw/bGUzfgKPJl69/mXDuSg8CbdBYBn6VVQdR947vWneQBFzdhasyzMUKg==",
+      "dependencies": {
+        "@vue/reactivity": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.40.tgz",
+      "integrity": "sha512-AO2HMQ+0s2+MCec8hXAhxMgWhFhOPJ/CyRXnmTJ6XIOnJFLrH5Iq3TNwvVcODGR295jy77I6dWPj+wvFoSYaww==",
+      "dependencies": {
+        "@vue/runtime-core": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "csstype": "^2.6.8"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.40.tgz",
+      "integrity": "sha512-gtUcpRwrXOJPJ4qyBpU3EyxQa4EkV8I4f8VrDePcGCPe4O/hd0BPS7v9OgjIQob6Ap8VDz9G+mGTKazE45/95w==",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.2.40",
+        "@vue/shared": "3.2.40"
+      },
+      "peerDependencies": {
+        "vue": "3.2.40"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.40.tgz",
+      "integrity": "sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ=="
+    },
+    "node_modules/c-scrollbar": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmmirror.com/c-scrollbar/-/c-scrollbar-0.1.7.tgz",
+      "integrity": "sha512-xD0VLJOmZ9MFhO6dGEF+Vr7zEk5QpH/oPmdONuWvWV14XbHiFd4A8A67rg+Nxcs5qjPIHunflbe+ZUHTvUdN8g==",
+      "dependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/core-js": {
+      "version": "3.25.5",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.25.5.tgz",
+      "integrity": "sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw==",
+      "hasInstallScript": true
+    },
+    "node_modules/csstype": {
+      "version": "2.6.21",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz",
+      "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "node_modules/lodash.clamp": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz",
+      "integrity": "sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg=="
+    },
+    "node_modules/lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+    },
+    "node_modules/magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "dependencies": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz",
+      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "node_modules/postcss": {
+      "version": "8.4.17",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.17.tgz",
+      "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==",
+      "dependencies": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/smooth-scrollbar": {
+      "version": "8.8.1",
+      "resolved": "https://registry.npmmirror.com/smooth-scrollbar/-/smooth-scrollbar-8.8.1.tgz",
+      "integrity": "sha512-FQDRtdLTRye8LdRHohNAxh0hyo7gl8+APfA+8Qu5S38MBqR8/WqOoRVzjizH6FTdbU1qGsB7gs8LhMeFJ4Jr8g==",
+      "dependencies": {
+        "core-js": "^3.6.4",
+        "lodash.clamp": "^4.0.3",
+        "lodash.debounce": "^4.0.8",
+        "tslib": "^1.10.0"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+    },
+    "node_modules/tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+    },
+    "node_modules/vue": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.40.tgz",
+      "integrity": "sha512-1mGHulzUbl2Nk3pfvI5aXYYyJUs1nm4kyvuz38u4xlQkLUn1i2R7nDbI4TufECmY8v1qNBHYy62bCaM+3cHP2A==",
+      "dependencies": {
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/compiler-sfc": "3.2.40",
+        "@vue/runtime-dom": "3.2.40",
+        "@vue/server-renderer": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "node_modules/vue-cropper": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/vue-cropper/-/vue-cropper-1.0.5.tgz",
+      "integrity": "sha512-D4XXdqWmMWRLOIV9LIh7/mkH6OBOMQDFbRjwntkxmAtxOtwpC9U5ZZ6lSXw5F5cbd4g8znDjk6MuCwIL+fZSrA=="
+    },
+    "node_modules/vue3-smooth-scrollbar": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/vue3-smooth-scrollbar/-/vue3-smooth-scrollbar-1.0.2.tgz",
+      "integrity": "sha512-TfO0WGbA5KzAosHMmIa4UfB5LcSR3YefNgRbTBZrKw4A5F58vIMALqwXeSCoLtsywdLInN+7u8Fq9cRDiT9EXg==",
+      "dependencies": {
+        "core-js": "^3.8.3",
+        "lodash": "^4.17.21",
+        "smooth-scrollbar": "^8.6.2",
+        "vue": "^3.0.4"
+      },
+      "peerDependencies": {
+        "smooth-scrollbar": "^8.6.2"
+      }
+    }
+  },
+  "dependencies": {
+    "@babel/parser": {
+      "version": "7.19.3",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.19.3.tgz",
+      "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ=="
+    },
+    "@vue/compiler-core": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.2.40.tgz",
+      "integrity": "sha512-2Dc3Stk0J/VyQ4OUr2yEC53kU28614lZS+bnrCbFSAIftBJ40g/2yQzf4mPBiFuqguMB7hyHaujdgZAQ67kZYA==",
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "source-map": "^0.6.1"
+      }
+    },
+    "@vue/compiler-dom": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.2.40.tgz",
+      "integrity": "sha512-OZCNyYVC2LQJy4H7h0o28rtk+4v+HMQygRTpmibGoG9wZyomQiS5otU7qo3Wlq5UfHDw2RFwxb9BJgKjVpjrQw==",
+      "requires": {
+        "@vue/compiler-core": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "@vue/compiler-sfc": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.2.40.tgz",
+      "integrity": "sha512-tzqwniIN1fu1PDHC3CpqY/dPCfN/RN1thpBC+g69kJcrl7mbGiHKNwbA6kJ3XKKy8R6JLKqcpVugqN4HkeBFFg==",
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.40",
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/compiler-ssr": "3.2.40",
+        "@vue/reactivity-transform": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7",
+        "postcss": "^8.1.10",
+        "source-map": "^0.6.1"
+      }
+    },
+    "@vue/compiler-ssr": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.2.40.tgz",
+      "integrity": "sha512-80cQcgasKjrPPuKcxwuCx7feq+wC6oFl5YaKSee9pV3DNq+6fmCVwEEC3vvkf/E2aI76rIJSOYHsWSEIxK74oQ==",
+      "requires": {
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "@vue/reactivity": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.2.40.tgz",
+      "integrity": "sha512-N9qgGLlZmtUBMHF9xDT4EkD9RdXde1Xbveb+niWMXuHVWQP5BzgRmE3SFyUBBcyayG4y1lhoz+lphGRRxxK4RA==",
+      "requires": {
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "@vue/reactivity-transform": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.2.40.tgz",
+      "integrity": "sha512-HQUCVwEaacq6fGEsg2NUuGKIhUveMCjOk8jGHqLXPI2w6zFoPrlQhwWEaINTv5kkZDXKEnCijAp+4gNEHG03yw==",
+      "requires": {
+        "@babel/parser": "^7.16.4",
+        "@vue/compiler-core": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.25.7"
+      }
+    },
+    "@vue/runtime-core": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.2.40.tgz",
+      "integrity": "sha512-U1+rWf0H8xK8aBUZhnrN97yoZfHbjgw/bGUzfgKPJl69/mXDuSg8CbdBYBn6VVQdR947vWneQBFzdhasyzMUKg==",
+      "requires": {
+        "@vue/reactivity": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "@vue/runtime-dom": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.2.40.tgz",
+      "integrity": "sha512-AO2HMQ+0s2+MCec8hXAhxMgWhFhOPJ/CyRXnmTJ6XIOnJFLrH5Iq3TNwvVcODGR295jy77I6dWPj+wvFoSYaww==",
+      "requires": {
+        "@vue/runtime-core": "3.2.40",
+        "@vue/shared": "3.2.40",
+        "csstype": "^2.6.8"
+      }
+    },
+    "@vue/server-renderer": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.2.40.tgz",
+      "integrity": "sha512-gtUcpRwrXOJPJ4qyBpU3EyxQa4EkV8I4f8VrDePcGCPe4O/hd0BPS7v9OgjIQob6Ap8VDz9G+mGTKazE45/95w==",
+      "requires": {
+        "@vue/compiler-ssr": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "@vue/shared": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.40.tgz",
+      "integrity": "sha512-0PLQ6RUtZM0vO3teRfzGi4ltLUO5aO+kLgwh4Um3THSR03rpQWLTuRCkuO5A41ITzwdWeKdPHtSARuPkoo5pCQ=="
+    },
+    "c-scrollbar": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmmirror.com/c-scrollbar/-/c-scrollbar-0.1.7.tgz",
+      "integrity": "sha512-xD0VLJOmZ9MFhO6dGEF+Vr7zEk5QpH/oPmdONuWvWV14XbHiFd4A8A67rg+Nxcs5qjPIHunflbe+ZUHTvUdN8g==",
+      "requires": {
+        "vue": "^3.0.0"
+      }
+    },
+    "core-js": {
+      "version": "3.25.5",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.25.5.tgz",
+      "integrity": "sha512-nbm6eZSjm+ZuBQxCUPQKQCoUEfFOXjUZ8dTTyikyKaWrTYmAVbykQfwsKE5dBK88u3QCkCrzsx/PPlKfhsvgpw=="
+    },
+    "csstype": {
+      "version": "2.6.21",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-2.6.21.tgz",
+      "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
+    },
+    "estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+    },
+    "lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+    },
+    "lodash.clamp": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz",
+      "integrity": "sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg=="
+    },
+    "lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+    },
+    "magic-string": {
+      "version": "0.25.9",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.25.9.tgz",
+      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
+      "requires": {
+        "sourcemap-codec": "^1.4.8"
+      }
+    },
+    "nanoid": {
+      "version": "3.3.4",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz",
+      "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
+    },
+    "picocolors": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
+      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+    },
+    "postcss": {
+      "version": "8.4.17",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.17.tgz",
+      "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==",
+      "requires": {
+        "nanoid": "^3.3.4",
+        "picocolors": "^1.0.0",
+        "source-map-js": "^1.0.2"
+      }
+    },
+    "smooth-scrollbar": {
+      "version": "8.8.1",
+      "resolved": "https://registry.npmmirror.com/smooth-scrollbar/-/smooth-scrollbar-8.8.1.tgz",
+      "integrity": "sha512-FQDRtdLTRye8LdRHohNAxh0hyo7gl8+APfA+8Qu5S38MBqR8/WqOoRVzjizH6FTdbU1qGsB7gs8LhMeFJ4Jr8g==",
+      "requires": {
+        "core-js": "^3.6.4",
+        "lodash.clamp": "^4.0.3",
+        "lodash.debounce": "^4.0.8",
+        "tslib": "^1.10.0"
+      }
+    },
+    "source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+    },
+    "source-map-js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz",
+      "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
+    },
+    "sourcemap-codec": {
+      "version": "1.4.8",
+      "resolved": "https://registry.npmmirror.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
+      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+    },
+    "tslib": {
+      "version": "1.14.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz",
+      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+    },
+    "vue": {
+      "version": "3.2.40",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.2.40.tgz",
+      "integrity": "sha512-1mGHulzUbl2Nk3pfvI5aXYYyJUs1nm4kyvuz38u4xlQkLUn1i2R7nDbI4TufECmY8v1qNBHYy62bCaM+3cHP2A==",
+      "requires": {
+        "@vue/compiler-dom": "3.2.40",
+        "@vue/compiler-sfc": "3.2.40",
+        "@vue/runtime-dom": "3.2.40",
+        "@vue/server-renderer": "3.2.40",
+        "@vue/shared": "3.2.40"
+      }
+    },
+    "vue-cropper": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/vue-cropper/-/vue-cropper-1.0.5.tgz",
+      "integrity": "sha512-D4XXdqWmMWRLOIV9LIh7/mkH6OBOMQDFbRjwntkxmAtxOtwpC9U5ZZ6lSXw5F5cbd4g8znDjk6MuCwIL+fZSrA=="
+    },
+    "vue3-smooth-scrollbar": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/vue3-smooth-scrollbar/-/vue3-smooth-scrollbar-1.0.2.tgz",
+      "integrity": "sha512-TfO0WGbA5KzAosHMmIa4UfB5LcSR3YefNgRbTBZrKw4A5F58vIMALqwXeSCoLtsywdLInN+7u8Fq9cRDiT9EXg==",
+      "requires": {
+        "core-js": "^3.8.3",
+        "lodash": "^4.17.21",
+        "smooth-scrollbar": "^8.6.2",
+        "vue": "^3.0.4"
+      }
+    }
+  }
+}

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

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

Datei-Diff unterdrückt, da er zu groß ist
+ 2217 - 2209
packages/qjkankan-kankan-view/package-lock.json


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

@@ -14,6 +14,7 @@
     "axios": "^0.21.1",
     "clipboard": "^2.0.8",
     "vue-i18n": "9",
+    "vue-router": "4.0.12",
     "vuex": "^4.0.2"
   },
   "devDependencies": {

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

@@ -8,7 +8,7 @@
         <link rel="stylesheet" href="<%= BASE_URL %><%= VUE_APP_STATIC_DIR %>/static/lib/iconfont/iconfont.css" />
         <!-- <link rel="stylesheet" href="<%= BASE_URL %><%= VUE_APP_STATIC_DIR %>/static/lib/animate/animate.min.css" /> -->
         <script src="<%= BASE_URL %><%= VUE_APP_STATIC_DIR %>/static/lib/mobile-detect.js"></script>
-        <title></title>
+        <title>全景看看</title>
     </head>
 
     <body>

+ 539 - 0
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/demo.css

@@ -0,0 +1,539 @@
+/* Logo 字体 */
+@font-face {
+  font-family: "iconfont logo";
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
+  src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
+    url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
+}
+
+.logo {
+  font-family: "iconfont logo";
+  font-size: 160px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+/* tabs */
+.nav-tabs {
+  position: relative;
+}
+
+.nav-tabs .nav-more {
+  position: absolute;
+  right: 0;
+  bottom: 0;
+  height: 42px;
+  line-height: 42px;
+  color: #666;
+}
+
+#tabs {
+  border-bottom: 1px solid #eee;
+}
+
+#tabs li {
+  cursor: pointer;
+  width: 100px;
+  height: 40px;
+  line-height: 40px;
+  text-align: center;
+  font-size: 16px;
+  border-bottom: 2px solid transparent;
+  position: relative;
+  z-index: 1;
+  margin-bottom: -1px;
+  color: #666;
+}
+
+
+#tabs .active {
+  border-bottom-color: #f00;
+  color: #222;
+}
+
+.tab-container .content {
+  display: none;
+}
+
+/* 页面布局 */
+.main {
+  padding: 30px 100px;
+  width: 960px;
+  margin: 0 auto;
+}
+
+.main .logo {
+  color: #333;
+  text-align: left;
+  margin-bottom: 30px;
+  line-height: 1;
+  height: 110px;
+  margin-top: -50px;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.main .logo a {
+  font-size: 160px;
+  color: #333;
+}
+
+.helps {
+  margin-top: 40px;
+}
+
+.helps pre {
+  padding: 20px;
+  margin: 10px 0;
+  border: solid 1px #e7e1cd;
+  background-color: #fffdef;
+  overflow: auto;
+}
+
+.icon_lists {
+  width: 100% !important;
+  overflow: hidden;
+  *zoom: 1;
+}
+
+.icon_lists li {
+  width: 100px;
+  margin-bottom: 10px;
+  margin-right: 20px;
+  text-align: center;
+  list-style: none !important;
+  cursor: default;
+}
+
+.icon_lists li .code-name {
+  line-height: 1.2;
+}
+
+.icon_lists .icon {
+  display: block;
+  height: 100px;
+  line-height: 100px;
+  font-size: 42px;
+  margin: 10px auto;
+  color: #333;
+  -webkit-transition: font-size 0.25s linear, width 0.25s linear;
+  -moz-transition: font-size 0.25s linear, width 0.25s linear;
+  transition: font-size 0.25s linear, width 0.25s linear;
+}
+
+.icon_lists .icon:hover {
+  font-size: 100px;
+}
+
+.icon_lists .svg-icon {
+  /* 通过设置 font-size 来改变图标大小 */
+  width: 1em;
+  /* 图标和文字相邻时,垂直对齐 */
+  vertical-align: -0.15em;
+  /* 通过设置 color 来改变 SVG 的颜色/fill */
+  fill: currentColor;
+  /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
+      normalize.css 中也包含这行 */
+  overflow: hidden;
+}
+
+.icon_lists li .name,
+.icon_lists li .code-name {
+  color: #666;
+}
+
+/* markdown 样式 */
+.markdown {
+  color: #666;
+  font-size: 14px;
+  line-height: 1.8;
+}
+
+.highlight {
+  line-height: 1.5;
+}
+
+.markdown img {
+  vertical-align: middle;
+  max-width: 100%;
+}
+
+.markdown h1 {
+  color: #404040;
+  font-weight: 500;
+  line-height: 40px;
+  margin-bottom: 24px;
+}
+
+.markdown h2,
+.markdown h3,
+.markdown h4,
+.markdown h5,
+.markdown h6 {
+  color: #404040;
+  margin: 1.6em 0 0.6em 0;
+  font-weight: 500;
+  clear: both;
+}
+
+.markdown h1 {
+  font-size: 28px;
+}
+
+.markdown h2 {
+  font-size: 22px;
+}
+
+.markdown h3 {
+  font-size: 16px;
+}
+
+.markdown h4 {
+  font-size: 14px;
+}
+
+.markdown h5 {
+  font-size: 12px;
+}
+
+.markdown h6 {
+  font-size: 12px;
+}
+
+.markdown hr {
+  height: 1px;
+  border: 0;
+  background: #e9e9e9;
+  margin: 16px 0;
+  clear: both;
+}
+
+.markdown p {
+  margin: 1em 0;
+}
+
+.markdown>p,
+.markdown>blockquote,
+.markdown>.highlight,
+.markdown>ol,
+.markdown>ul {
+  width: 80%;
+}
+
+.markdown ul>li {
+  list-style: circle;
+}
+
+.markdown>ul li,
+.markdown blockquote ul>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown>ul li p,
+.markdown>ol li p {
+  margin: 0.6em 0;
+}
+
+.markdown ol>li {
+  list-style: decimal;
+}
+
+.markdown>ol li,
+.markdown blockquote ol>li {
+  margin-left: 20px;
+  padding-left: 4px;
+}
+
+.markdown code {
+  margin: 0 3px;
+  padding: 0 5px;
+  background: #eee;
+  border-radius: 3px;
+}
+
+.markdown strong,
+.markdown b {
+  font-weight: 600;
+}
+
+.markdown>table {
+  border-collapse: collapse;
+  border-spacing: 0px;
+  empty-cells: show;
+  border: 1px solid #e9e9e9;
+  width: 95%;
+  margin-bottom: 24px;
+}
+
+.markdown>table th {
+  white-space: nowrap;
+  color: #333;
+  font-weight: 600;
+}
+
+.markdown>table th,
+.markdown>table td {
+  border: 1px solid #e9e9e9;
+  padding: 8px 16px;
+  text-align: left;
+}
+
+.markdown>table th {
+  background: #F7F7F7;
+}
+
+.markdown blockquote {
+  font-size: 90%;
+  color: #999;
+  border-left: 4px solid #e9e9e9;
+  padding-left: 0.8em;
+  margin: 1em 0;
+}
+
+.markdown blockquote p {
+  margin: 0;
+}
+
+.markdown .anchor {
+  opacity: 0;
+  transition: opacity 0.3s ease;
+  margin-left: 8px;
+}
+
+.markdown .waiting {
+  color: #ccc;
+}
+
+.markdown h1:hover .anchor,
+.markdown h2:hover .anchor,
+.markdown h3:hover .anchor,
+.markdown h4:hover .anchor,
+.markdown h5:hover .anchor,
+.markdown h6:hover .anchor {
+  opacity: 1;
+  display: inline-block;
+}
+
+.markdown>br,
+.markdown>p>br {
+  clear: both;
+}
+
+
+.hljs {
+  display: block;
+  background: white;
+  padding: 0.5em;
+  color: #333333;
+  overflow-x: auto;
+}
+
+.hljs-comment,
+.hljs-meta {
+  color: #969896;
+}
+
+.hljs-string,
+.hljs-variable,
+.hljs-template-variable,
+.hljs-strong,
+.hljs-emphasis,
+.hljs-quote {
+  color: #df5000;
+}
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-type {
+  color: #a71d5d;
+}
+
+.hljs-literal,
+.hljs-symbol,
+.hljs-bullet,
+.hljs-attribute {
+  color: #0086b3;
+}
+
+.hljs-section,
+.hljs-name {
+  color: #63a35c;
+}
+
+.hljs-tag {
+  color: #333333;
+}
+
+.hljs-title,
+.hljs-attr,
+.hljs-selector-id,
+.hljs-selector-class,
+.hljs-selector-attr,
+.hljs-selector-pseudo {
+  color: #795da3;
+}
+
+.hljs-addition {
+  color: #55a532;
+  background-color: #eaffea;
+}
+
+.hljs-deletion {
+  color: #bd2c00;
+  background-color: #ffecec;
+}
+
+.hljs-link {
+  text-decoration: underline;
+}
+
+/* 代码高亮 */
+/* PrismJS 1.15.0
+https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+code[class*="language-"],
+pre[class*="language-"] {
+  color: black;
+  background: none;
+  text-shadow: 0 1px white;
+  font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+  text-align: left;
+  white-space: pre;
+  word-spacing: normal;
+  word-break: normal;
+  word-wrap: normal;
+  line-height: 1.5;
+
+  -moz-tab-size: 4;
+  -o-tab-size: 4;
+  tab-size: 4;
+
+  -webkit-hyphens: none;
+  -moz-hyphens: none;
+  -ms-hyphens: none;
+  hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection,
+pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection,
+code[class*="language-"] ::-moz-selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection,
+pre[class*="language-"] ::selection,
+code[class*="language-"]::selection,
+code[class*="language-"] ::selection {
+  text-shadow: none;
+  background: #b3d4fc;
+}
+
+@media print {
+
+  code[class*="language-"],
+  pre[class*="language-"] {
+    text-shadow: none;
+  }
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+  padding: 1em;
+  margin: .5em 0;
+  overflow: auto;
+}
+
+:not(pre)>code[class*="language-"],
+pre[class*="language-"] {
+  background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre)>code[class*="language-"] {
+  padding: .1em;
+  border-radius: .3em;
+  white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+  color: slategray;
+}
+
+.token.punctuation {
+  color: #999;
+}
+
+.namespace {
+  opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+  color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+  color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+  color: #9a6e3a;
+  background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+  color: #07a;
+}
+
+.token.function,
+.token.class-name {
+  color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+  color: #e90;
+}
+
+.token.important,
+.token.bold {
+  font-weight: bold;
+}
+
+.token.italic {
+  font-style: italic;
+}
+
+.token.entity {
+  cursor: help;
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 3385 - 0
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/demo_index.html


+ 571 - 0
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.css

@@ -0,0 +1,571 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2596172 */
+  src: url('iconfont.woff2?t=1659061669448') format('woff2'),
+       url('iconfont.woff?t=1659061669448') format('woff'),
+       url('iconfont.ttf?t=1659061669448') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-show_share:before {
+  content: "\e690";
+}
+
+.icon-show_more_ruler:before {
+  content: "\e67b";
+}
+
+.icon-transparency:before {
+  content: "\e6d7";
+}
+
+.icon-mosaic_e:before {
+  content: "\e6d2";
+}
+
+.icon-eraser:before {
+  content: "\e6d3";
+}
+
+.icon-video2:before {
+  content: "\e6d4";
+}
+
+.icon-down:before {
+  content: "\e6d5";
+}
+
+.icon-qingkong-copy-copy:before {
+  content: "\e68f";
+}
+
+.icon-_qq:before {
+  content: "\e64b";
+}
+
+.icon-_friend:before {
+  content: "\e64c";
+}
+
+.icon-link1:before {
+  content: "\e6ff";
+}
+
+.icon-icon_share_facebook:before {
+  content: "\e745";
+}
+
+.icon-icon_share_whatsapp:before {
+  content: "\e746";
+}
+
+.icon-_wechat:before {
+  content: "\e64a";
+}
+
+.icon-watermark:before {
+  content: "\e6cb";
+}
+
+.icon-camera_h:before {
+  content: "\e6c7";
+}
+
+.icon-a-1V1:before {
+  content: "\e6c8";
+}
+
+.icon-hengbiaoEN:before {
+  content: "\e6b9";
+}
+
+.icon-hot_spot:before {
+  content: "\e6b8";
+}
+
+.icon-foot:before {
+  content: "\e6ba";
+}
+
+.icon-music-t:before {
+  content: "\e6b7";
+}
+
+.icon-yes:before {
+  content: "\e6b5";
+}
+
+.icon-no:before {
+  content: "\e6b6";
+}
+
+.icon-floor_rename:before {
+  content: "\e75b";
+}
+
+.icon-play_stop:before {
+  content: "\e6b4";
+}
+
+.icon-scene_auto:before {
+  content: "\e721";
+}
+
+.icon-compass:before {
+  content: "\e6b3";
+}
+
+.icon-h-d:before {
+  content: "\e6b2";
+}
+
+.icon-scene_screen:before {
+  content: "\e717";
+}
+
+.icon-scene_full:before {
+  content: "\e712";
+}
+
+.icon-scene_window:before {
+  content: "\e713";
+}
+
+.icon-_back:before {
+  content: "\e609";
+}
+
+.icon-show_back:before {
+  content: "\e678";
+}
+
+.icon-show_more_share:before {
+  content: "\e680";
+}
+
+.icon-show_more_finish:before {
+  content: "\e67a";
+}
+
+.icon-show_more_music:before {
+  content: "\e67c";
+}
+
+.icon-show_map_collect:before {
+  content: "\e679";
+}
+
+.icon-data-j:before {
+  content: "\e6b1";
+}
+
+.icon-cancel:before {
+  content: "\e688";
+}
+
+.icon-affirm:before {
+  content: "\e689";
+}
+
+.icon-checkbox_p:before {
+  content: "\e6b0";
+}
+
+.icon-left:before {
+  content: "\e6ae";
+}
+
+.icon-right:before {
+  content: "\e6af";
+}
+
+.icon-_loading_:before {
+  content: "\e627";
+}
+
+.icon-show_function_collect:before {
+  content: "\e687";
+}
+
+.icon-show_more:before {
+  content: "\e67e";
+}
+
+.icon-d-r:before {
+  content: "\e68d";
+}
+
+.icon-up-a:before {
+  content: "\e68e";
+}
+
+.icon-fanzhuan:before {
+  content: "\e6fa";
+}
+
+.icon-cad-neiqiang:before {
+  content: "\e698";
+}
+
+.icon-cad-waiqiang:before {
+  content: "\e69a";
+}
+
+.icon-cad-shuangkaimen:before {
+  content: "\e69b";
+}
+
+.icon-cad-zimumen:before {
+  content: "\e69c";
+}
+
+.icon-cad-men:before {
+  content: "\e69d";
+}
+
+.icon-cad-yimen:before {
+  content: "\e69e";
+}
+
+.icon-cad-zhediemen:before {
+  content: "\e69f";
+}
+
+.icon-cad-luodichuang:before {
+  content: "\e6a0";
+}
+
+.icon-cad-chuang:before {
+  content: "\e6a1";
+}
+
+.icon-cad-piaochuang:before {
+  content: "\e6a2";
+}
+
+.icon-cad-uxingchuang:before {
+  content: "\e6a4";
+}
+
+.icon-cad-lxingchuang:before {
+  content: "\e6a5";
+}
+
+.icon-cad-lpiaochuang:before {
+  content: "\e6a6";
+}
+
+.icon-cad-upiaochuang:before {
+  content: "\e6a7";
+}
+
+.icon-cad-liang:before {
+  content: "\e6a8";
+}
+
+.icon-cad-yandao:before {
+  content: "\e6a9";
+}
+
+.icon-cad-zhuzi:before {
+  content: "\e6aa";
+}
+
+.icon-cad-dianti:before {
+  content: "\e6ab";
+}
+
+.icon-cad-loudao:before {
+  content: "\e6ac";
+}
+
+.icon-cad-dange:before {
+  content: "\e6ad";
+}
+
+.icon-cad-yakou:before {
+  content: "\e699";
+}
+
+.icon-more:before {
+  content: "\e600";
+}
+
+.icon-mosaic1:before {
+  content: "\e697";
+}
+
+.icon-hengbiaoCN:before {
+  content: "\e6a3";
+}
+
+.icon-nor:before {
+  content: "\e696";
+}
+
+.icon-checkbox1:before {
+  content: "\e65d";
+}
+
+.icon-rotate:before {
+  content: "\e695";
+}
+
+.icon-adapt:before {
+  content: "\e692";
+}
+
+.icon-recover:before {
+  content: "\e693";
+}
+
+.icon-repeal:before {
+  content: "\e694";
+}
+
+.icon-reset:before {
+  content: "\e65a";
+}
+
+.icon-course1:before {
+  content: "\e68c";
+}
+
+.icon-publish:before {
+  content: "\e68a";
+}
+
+.icon-save:before {
+  content: "\e68b";
+}
+
+.icon-checkbox:before {
+  content: "\e649";
+}
+
+.icon-mosaic:before {
+  content: "\e646";
+}
+
+.icon-media:before {
+  content: "\e647";
+}
+
+.icon-pic:before {
+  content: "\e648";
+}
+
+.icon-eye_f:before {
+  content: "\e644";
+}
+
+.icon-eye_c:before {
+  content: "\e645";
+}
+
+.icon-size-o:before {
+  content: "\e640";
+}
+
+.icon-size-f:before {
+  content: "\e641";
+}
+
+.icon-magnify:before {
+  content: "\e642";
+}
+
+.icon-reduce:before {
+  content: "\e643";
+}
+
+.icon-video1:before {
+  content: "\e63b";
+}
+
+.icon-uploading_s:before {
+  content: "\e63c";
+}
+
+.icon-path:before {
+  content: "\e63d";
+}
+
+.icon-record:before {
+  content: "\e63e";
+}
+
+.icon-clear:before {
+  content: "\e63f";
+}
+
+.icon-pause:before {
+  content: "\e636";
+}
+
+.icon-preview:before {
+  content: "\e63a";
+}
+
+.icon-full:before {
+  content: "\e638";
+}
+
+.icon-add:before {
+  content: "\e631";
+}
+
+.icon-del:before {
+  content: "\e632";
+}
+
+.icon-close:before {
+  content: "\e633";
+}
+
+.icon-web:before {
+  content: "\e635";
+}
+
+.icon-music:before {
+  content: "\e637";
+}
+
+.icon-uploading1:before {
+  content: "\e639";
+}
+
+.icon-state_e:before {
+  content: "\e624";
+}
+
+.icon-state_f:before {
+  content: "\e625";
+}
+
+.icon-state_s:before {
+  content: "\e626";
+}
+
+.icon-vip_uploading:before {
+  content: "\e623";
+}
+
+.icon-eye-n:before {
+  content: "\e621";
+}
+
+.icon-eye-s:before {
+  content: "\e622";
+}
+
+.icon-course:before {
+  content: "\e620";
+}
+
+.icon-edit:before {
+  content: "\e61f";
+}
+
+.icon-help:before {
+  content: "\e615";
+}
+
+.icon-rule:before {
+  content: "\e617";
+}
+
+.icon-link:before {
+  content: "\e618";
+}
+
+.icon-uploading:before {
+  content: "\e619";
+}
+
+.icon-vr:before {
+  content: "\e61a";
+}
+
+.icon-complete:before {
+  content: "\e61b";
+}
+
+.icon-download:before {
+  content: "\e61c";
+}
+
+.icon-pull-down:before {
+  content: "\e61d";
+}
+
+.icon-pull-up:before {
+  content: "\e61e";
+}
+
+.icon-updown:before {
+  content: "\e613";
+}
+
+.icon-scene:before {
+  content: "\e614";
+}
+
+.icon-message:before {
+  content: "\e60c";
+}
+
+.icon-basic:before {
+  content: "\e60d";
+}
+
+.icon-hotspot:before {
+  content: "\e60e";
+}
+
+.icon-guide:before {
+  content: "\e60f";
+}
+
+.icon-wander:before {
+  content: "\e610";
+}
+
+.icon-house:before {
+  content: "\e611";
+}
+
+.icon-video:before {
+  content: "\e612";
+}
+
+.icon-show_3d_normal:before {
+  content: "\e677";
+}
+
+.icon-show_plane_normal:before {
+  content: "\e67d";
+}
+
+.icon-show_roaming_selected:before {
+  content: "\e682";
+}
+
+.icon-show_plane_selected:before {
+  content: "\e684";
+}
+
+.icon-show_3d_selected:before {
+  content: "\e685";
+}
+
+.icon-show_roaming_normal:before {
+  content: "\e686";
+}
+

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.js


+ 982 - 0
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.json

@@ -0,0 +1,982 @@
+{
+  "id": "2596172",
+  "name": "四维看看编辑器V4",
+  "font_family": "iconfont",
+  "css_prefix_text": "icon-",
+  "description": "四维看看编辑器设计优化",
+  "glyphs": [
+    {
+      "icon_id": "20600368",
+      "name": "show_share",
+      "font_class": "show_share",
+      "unicode": "e690",
+      "unicode_decimal": 59024
+    },
+    {
+      "icon_id": "19543928",
+      "name": "show_more_ruler",
+      "font_class": "show_more_ruler",
+      "unicode": "e67b",
+      "unicode_decimal": 59003
+    },
+    {
+      "icon_id": "30499411",
+      "name": "transparency",
+      "font_class": "transparency",
+      "unicode": "e6d7",
+      "unicode_decimal": 59095
+    },
+    {
+      "icon_id": "30490892",
+      "name": "mosaic_e",
+      "font_class": "mosaic_e",
+      "unicode": "e6d2",
+      "unicode_decimal": 59090
+    },
+    {
+      "icon_id": "30490893",
+      "name": "eraser",
+      "font_class": "eraser",
+      "unicode": "e6d3",
+      "unicode_decimal": 59091
+    },
+    {
+      "icon_id": "30490894",
+      "name": "video",
+      "font_class": "video2",
+      "unicode": "e6d4",
+      "unicode_decimal": 59092
+    },
+    {
+      "icon_id": "30490946",
+      "name": "down",
+      "font_class": "down",
+      "unicode": "e6d5",
+      "unicode_decimal": 59093
+    },
+    {
+      "icon_id": "3141534",
+      "name": "清空",
+      "font_class": "qingkong-copy-copy",
+      "unicode": "e68f",
+      "unicode_decimal": 59023
+    },
+    {
+      "icon_id": "7878582",
+      "name": "QQ",
+      "font_class": "_qq",
+      "unicode": "e64b",
+      "unicode_decimal": 58955
+    },
+    {
+      "icon_id": "7878584",
+      "name": "朋友",
+      "font_class": "_friend",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "14887802",
+      "name": "link",
+      "font_class": "link1",
+      "unicode": "e6ff",
+      "unicode_decimal": 59135
+    },
+    {
+      "icon_id": "26296900",
+      "name": "icon_share_facebook",
+      "font_class": "icon_share_facebook",
+      "unicode": "e745",
+      "unicode_decimal": 59205
+    },
+    {
+      "icon_id": "26296901",
+      "name": "icon_share_whatsapp",
+      "font_class": "icon_share_whatsapp",
+      "unicode": "e746",
+      "unicode_decimal": 59206
+    },
+    {
+      "icon_id": "7878583",
+      "name": "微信",
+      "font_class": "_wechat",
+      "unicode": "e64a",
+      "unicode_decimal": 58954
+    },
+    {
+      "icon_id": "30230568",
+      "name": "watermark",
+      "font_class": "watermark",
+      "unicode": "e6cb",
+      "unicode_decimal": 59083
+    },
+    {
+      "icon_id": "30230353",
+      "name": "camera_h",
+      "font_class": "camera_h",
+      "unicode": "e6c7",
+      "unicode_decimal": 59079
+    },
+    {
+      "icon_id": "30230374",
+      "name": "1V1",
+      "font_class": "a-1V1",
+      "unicode": "e6c8",
+      "unicode_decimal": 59080
+    },
+    {
+      "icon_id": "12324810",
+      "name": "横标EN",
+      "font_class": "hengbiaoEN",
+      "unicode": "e6b9",
+      "unicode_decimal": 59065
+    },
+    {
+      "icon_id": "22788718",
+      "name": "hot_spot",
+      "font_class": "hot_spot",
+      "unicode": "e6b8",
+      "unicode_decimal": 59064
+    },
+    {
+      "icon_id": "29982018",
+      "name": "foot",
+      "font_class": "foot",
+      "unicode": "e6ba",
+      "unicode_decimal": 59066
+    },
+    {
+      "icon_id": "29365471",
+      "name": "music-t",
+      "font_class": "music-t",
+      "unicode": "e6b7",
+      "unicode_decimal": 59063
+    },
+    {
+      "icon_id": "29346730",
+      "name": "yes",
+      "font_class": "yes",
+      "unicode": "e6b5",
+      "unicode_decimal": 59061
+    },
+    {
+      "icon_id": "29346731",
+      "name": "no",
+      "font_class": "no",
+      "unicode": "e6b6",
+      "unicode_decimal": 59062
+    },
+    {
+      "icon_id": "20764383",
+      "name": "floor_rename",
+      "font_class": "floor_rename",
+      "unicode": "e75b",
+      "unicode_decimal": 59227
+    },
+    {
+      "icon_id": "29255507",
+      "name": "play_stop",
+      "font_class": "play_stop",
+      "unicode": "e6b4",
+      "unicode_decimal": 59060
+    },
+    {
+      "icon_id": "16303117",
+      "name": "scene_auto",
+      "font_class": "scene_auto",
+      "unicode": "e721",
+      "unicode_decimal": 59169
+    },
+    {
+      "icon_id": "28895680",
+      "name": "compass",
+      "font_class": "compass",
+      "unicode": "e6b3",
+      "unicode_decimal": 59059
+    },
+    {
+      "icon_id": "28351771",
+      "name": "h-d",
+      "font_class": "h-d",
+      "unicode": "e6b2",
+      "unicode_decimal": 59058
+    },
+    {
+      "icon_id": "16270567",
+      "name": "scene_screen",
+      "font_class": "scene_screen",
+      "unicode": "e717",
+      "unicode_decimal": 59159
+    },
+    {
+      "icon_id": "15936377",
+      "name": "scene_full",
+      "font_class": "scene_full",
+      "unicode": "e712",
+      "unicode_decimal": 59154
+    },
+    {
+      "icon_id": "15936378",
+      "name": "scene_window",
+      "font_class": "scene_window",
+      "unicode": "e713",
+      "unicode_decimal": 59155
+    },
+    {
+      "icon_id": "7857935",
+      "name": "返回",
+      "font_class": "_back",
+      "unicode": "e609",
+      "unicode_decimal": 58889
+    },
+    {
+      "icon_id": "20066553",
+      "name": "show_back",
+      "font_class": "show_back",
+      "unicode": "e678",
+      "unicode_decimal": 59000
+    },
+    {
+      "icon_id": "20066555",
+      "name": "show_more_share",
+      "font_class": "show_more_share",
+      "unicode": "e680",
+      "unicode_decimal": 59008
+    },
+    {
+      "icon_id": "19543927",
+      "name": "show_more_finish",
+      "font_class": "show_more_finish",
+      "unicode": "e67a",
+      "unicode_decimal": 59002
+    },
+    {
+      "icon_id": "19543929",
+      "name": "show_more_music",
+      "font_class": "show_more_music",
+      "unicode": "e67c",
+      "unicode_decimal": 59004
+    },
+    {
+      "icon_id": "19543926",
+      "name": "show_map_collect",
+      "font_class": "show_map_collect",
+      "unicode": "e679",
+      "unicode_decimal": 59001
+    },
+    {
+      "icon_id": "27985200",
+      "name": "data-j",
+      "font_class": "data-j",
+      "unicode": "e6b1",
+      "unicode_decimal": 59057
+    },
+    {
+      "icon_id": "26690641",
+      "name": "cancel",
+      "font_class": "cancel",
+      "unicode": "e688",
+      "unicode_decimal": 59016
+    },
+    {
+      "icon_id": "26690677",
+      "name": "affirm",
+      "font_class": "affirm",
+      "unicode": "e689",
+      "unicode_decimal": 59017
+    },
+    {
+      "icon_id": "27896904",
+      "name": "checkbox_p",
+      "font_class": "checkbox_p",
+      "unicode": "e6b0",
+      "unicode_decimal": 59056
+    },
+    {
+      "icon_id": "27765016",
+      "name": "left",
+      "font_class": "left",
+      "unicode": "e6ae",
+      "unicode_decimal": 59054
+    },
+    {
+      "icon_id": "27765017",
+      "name": "right",
+      "font_class": "right",
+      "unicode": "e6af",
+      "unicode_decimal": 59055
+    },
+    {
+      "icon_id": "7858065",
+      "name": "loading",
+      "font_class": "_loading_",
+      "unicode": "e627",
+      "unicode_decimal": 58919
+    },
+    {
+      "icon_id": "20066572",
+      "name": "show_function_collect",
+      "font_class": "show_function_collect",
+      "unicode": "e687",
+      "unicode_decimal": 59015
+    },
+    {
+      "icon_id": "19543931",
+      "name": "show_more",
+      "font_class": "show_more",
+      "unicode": "e67e",
+      "unicode_decimal": 59006
+    },
+    {
+      "icon_id": "26914809",
+      "name": "d-r",
+      "font_class": "d-r",
+      "unicode": "e68d",
+      "unicode_decimal": 59021
+    },
+    {
+      "icon_id": "26914810",
+      "name": "up-a",
+      "font_class": "up-a",
+      "unicode": "e68e",
+      "unicode_decimal": 59022
+    },
+    {
+      "icon_id": "14510564",
+      "name": "edit_mirror",
+      "font_class": "fanzhuan",
+      "unicode": "e6fa",
+      "unicode_decimal": 59130
+    },
+    {
+      "icon_id": "27294582",
+      "name": "neiqiang",
+      "font_class": "cad-neiqiang",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    },
+    {
+      "icon_id": "27294583",
+      "name": "waiqiang",
+      "font_class": "cad-waiqiang",
+      "unicode": "e69a",
+      "unicode_decimal": 59034
+    },
+    {
+      "icon_id": "27294616",
+      "name": "shuangkaimen",
+      "font_class": "cad-shuangkaimen",
+      "unicode": "e69b",
+      "unicode_decimal": 59035
+    },
+    {
+      "icon_id": "27294617",
+      "name": "zimumen",
+      "font_class": "cad-zimumen",
+      "unicode": "e69c",
+      "unicode_decimal": 59036
+    },
+    {
+      "icon_id": "27294618",
+      "name": "men",
+      "font_class": "cad-men",
+      "unicode": "e69d",
+      "unicode_decimal": 59037
+    },
+    {
+      "icon_id": "27294620",
+      "name": "yimen",
+      "font_class": "cad-yimen",
+      "unicode": "e69e",
+      "unicode_decimal": 59038
+    },
+    {
+      "icon_id": "27294621",
+      "name": "zhediemen",
+      "font_class": "cad-zhediemen",
+      "unicode": "e69f",
+      "unicode_decimal": 59039
+    },
+    {
+      "icon_id": "27294699",
+      "name": "luodichuang",
+      "font_class": "cad-luodichuang",
+      "unicode": "e6a0",
+      "unicode_decimal": 59040
+    },
+    {
+      "icon_id": "27294700",
+      "name": "chuang",
+      "font_class": "cad-chuang",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "27294701",
+      "name": "piaochuang",
+      "font_class": "cad-piaochuang",
+      "unicode": "e6a2",
+      "unicode_decimal": 59042
+    },
+    {
+      "icon_id": "27294702",
+      "name": "uxingchuang",
+      "font_class": "cad-uxingchuang",
+      "unicode": "e6a4",
+      "unicode_decimal": 59044
+    },
+    {
+      "icon_id": "27294703",
+      "name": "lxingchuang",
+      "font_class": "cad-lxingchuang",
+      "unicode": "e6a5",
+      "unicode_decimal": 59045
+    },
+    {
+      "icon_id": "27294704",
+      "name": "lpiaochuang",
+      "font_class": "cad-lpiaochuang",
+      "unicode": "e6a6",
+      "unicode_decimal": 59046
+    },
+    {
+      "icon_id": "27294705",
+      "name": "upiaochuang",
+      "font_class": "cad-upiaochuang",
+      "unicode": "e6a7",
+      "unicode_decimal": 59047
+    },
+    {
+      "icon_id": "27294743",
+      "name": "liang",
+      "font_class": "cad-liang",
+      "unicode": "e6a8",
+      "unicode_decimal": 59048
+    },
+    {
+      "icon_id": "27294744",
+      "name": "yandao",
+      "font_class": "cad-yandao",
+      "unicode": "e6a9",
+      "unicode_decimal": 59049
+    },
+    {
+      "icon_id": "27294745",
+      "name": "zhuzi",
+      "font_class": "cad-zhuzi",
+      "unicode": "e6aa",
+      "unicode_decimal": 59050
+    },
+    {
+      "icon_id": "27294746",
+      "name": "dianti",
+      "font_class": "cad-dianti",
+      "unicode": "e6ab",
+      "unicode_decimal": 59051
+    },
+    {
+      "icon_id": "27294747",
+      "name": "loudao",
+      "font_class": "cad-loudao",
+      "unicode": "e6ac",
+      "unicode_decimal": 59052
+    },
+    {
+      "icon_id": "27297593",
+      "name": "dange",
+      "font_class": "cad-dange",
+      "unicode": "e6ad",
+      "unicode_decimal": 59053
+    },
+    {
+      "icon_id": "27294584",
+      "name": "yakou",
+      "font_class": "cad-yakou",
+      "unicode": "e699",
+      "unicode_decimal": 59033
+    },
+    {
+      "icon_id": "11304931",
+      "name": "more read",
+      "font_class": "more",
+      "unicode": "e600",
+      "unicode_decimal": 58880
+    },
+    {
+      "icon_id": "27264933",
+      "name": "mosaic",
+      "font_class": "mosaic1",
+      "unicode": "e697",
+      "unicode_decimal": 59031
+    },
+    {
+      "icon_id": "12324809",
+      "name": "横标CN",
+      "font_class": "hengbiaoCN",
+      "unicode": "e6a3",
+      "unicode_decimal": 59043
+    },
+    {
+      "icon_id": "27200779",
+      "name": "nor",
+      "font_class": "nor",
+      "unicode": "e696",
+      "unicode_decimal": 59030
+    },
+    {
+      "icon_id": "25671886",
+      "name": "checkbox",
+      "font_class": "checkbox1",
+      "unicode": "e65d",
+      "unicode_decimal": 58973
+    },
+    {
+      "icon_id": "27198807",
+      "name": "rotate",
+      "font_class": "rotate",
+      "unicode": "e695",
+      "unicode_decimal": 59029
+    },
+    {
+      "icon_id": "27198774",
+      "name": "adapt",
+      "font_class": "adapt",
+      "unicode": "e692",
+      "unicode_decimal": 59026
+    },
+    {
+      "icon_id": "27198776",
+      "name": "recover",
+      "font_class": "recover",
+      "unicode": "e693",
+      "unicode_decimal": 59027
+    },
+    {
+      "icon_id": "27198777",
+      "name": "repeal",
+      "font_class": "repeal",
+      "unicode": "e694",
+      "unicode_decimal": 59028
+    },
+    {
+      "icon_id": "25654903",
+      "name": "reset",
+      "font_class": "reset",
+      "unicode": "e65a",
+      "unicode_decimal": 58970
+    },
+    {
+      "icon_id": "26971297",
+      "name": "course",
+      "font_class": "course1",
+      "unicode": "e68c",
+      "unicode_decimal": 59020
+    },
+    {
+      "icon_id": "26950708",
+      "name": "publish",
+      "font_class": "publish",
+      "unicode": "e68a",
+      "unicode_decimal": 59018
+    },
+    {
+      "icon_id": "26950711",
+      "name": "save",
+      "font_class": "save",
+      "unicode": "e68b",
+      "unicode_decimal": 59019
+    },
+    {
+      "icon_id": "23842269",
+      "name": "sel",
+      "font_class": "checkbox",
+      "unicode": "e649",
+      "unicode_decimal": 58953
+    },
+    {
+      "icon_id": "23786361",
+      "name": "mosaic",
+      "font_class": "mosaic",
+      "unicode": "e646",
+      "unicode_decimal": 58950
+    },
+    {
+      "icon_id": "23786362",
+      "name": "media",
+      "font_class": "media",
+      "unicode": "e647",
+      "unicode_decimal": 58951
+    },
+    {
+      "icon_id": "23786363",
+      "name": "pic",
+      "font_class": "pic",
+      "unicode": "e648",
+      "unicode_decimal": 58952
+    },
+    {
+      "icon_id": "23783948",
+      "name": "eye_f",
+      "font_class": "eye_f",
+      "unicode": "e644",
+      "unicode_decimal": 58948
+    },
+    {
+      "icon_id": "23783949",
+      "name": "eye_c",
+      "font_class": "eye_c",
+      "unicode": "e645",
+      "unicode_decimal": 58949
+    },
+    {
+      "icon_id": "23783512",
+      "name": "size-o",
+      "font_class": "size-o",
+      "unicode": "e640",
+      "unicode_decimal": 58944
+    },
+    {
+      "icon_id": "23783513",
+      "name": "size-f",
+      "font_class": "size-f",
+      "unicode": "e641",
+      "unicode_decimal": 58945
+    },
+    {
+      "icon_id": "23783514",
+      "name": "magnify",
+      "font_class": "magnify",
+      "unicode": "e642",
+      "unicode_decimal": 58946
+    },
+    {
+      "icon_id": "23783515",
+      "name": "reduce",
+      "font_class": "reduce",
+      "unicode": "e643",
+      "unicode_decimal": 58947
+    },
+    {
+      "icon_id": "23781429",
+      "name": "video",
+      "font_class": "video1",
+      "unicode": "e63b",
+      "unicode_decimal": 58939
+    },
+    {
+      "icon_id": "23781430",
+      "name": "uploading_s",
+      "font_class": "uploading_s",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    },
+    {
+      "icon_id": "23781431",
+      "name": "path",
+      "font_class": "path",
+      "unicode": "e63d",
+      "unicode_decimal": 58941
+    },
+    {
+      "icon_id": "23781432",
+      "name": "record",
+      "font_class": "record",
+      "unicode": "e63e",
+      "unicode_decimal": 58942
+    },
+    {
+      "icon_id": "23781433",
+      "name": "clear",
+      "font_class": "clear",
+      "unicode": "e63f",
+      "unicode_decimal": 58943
+    },
+    {
+      "icon_id": "23773343",
+      "name": "pause",
+      "font_class": "pause",
+      "unicode": "e636",
+      "unicode_decimal": 58934
+    },
+    {
+      "icon_id": "23773344",
+      "name": "preview",
+      "font_class": "preview",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "23773141",
+      "name": "full",
+      "font_class": "full",
+      "unicode": "e638",
+      "unicode_decimal": 58936
+    },
+    {
+      "icon_id": "23773068",
+      "name": "add",
+      "font_class": "add",
+      "unicode": "e631",
+      "unicode_decimal": 58929
+    },
+    {
+      "icon_id": "23773069",
+      "name": "del",
+      "font_class": "del",
+      "unicode": "e632",
+      "unicode_decimal": 58930
+    },
+    {
+      "icon_id": "23773070",
+      "name": "close",
+      "font_class": "close",
+      "unicode": "e633",
+      "unicode_decimal": 58931
+    },
+    {
+      "icon_id": "23773072",
+      "name": "web",
+      "font_class": "web",
+      "unicode": "e635",
+      "unicode_decimal": 58933
+    },
+    {
+      "icon_id": "23773074",
+      "name": "music",
+      "font_class": "music",
+      "unicode": "e637",
+      "unicode_decimal": 58935
+    },
+    {
+      "icon_id": "23773076",
+      "name": "uploading",
+      "font_class": "uploading1",
+      "unicode": "e639",
+      "unicode_decimal": 58937
+    },
+    {
+      "icon_id": "22132762",
+      "name": "state_e",
+      "font_class": "state_e",
+      "unicode": "e624",
+      "unicode_decimal": 58916
+    },
+    {
+      "icon_id": "22132763",
+      "name": "state_f",
+      "font_class": "state_f",
+      "unicode": "e625",
+      "unicode_decimal": 58917
+    },
+    {
+      "icon_id": "22132764",
+      "name": "state_s",
+      "font_class": "state_s",
+      "unicode": "e626",
+      "unicode_decimal": 58918
+    },
+    {
+      "icon_id": "22130256",
+      "name": "vip_uploading",
+      "font_class": "vip_uploading",
+      "unicode": "e623",
+      "unicode_decimal": 58915
+    },
+    {
+      "icon_id": "22099675",
+      "name": "eye-n",
+      "font_class": "eye-n",
+      "unicode": "e621",
+      "unicode_decimal": 58913
+    },
+    {
+      "icon_id": "22099676",
+      "name": "eye-s",
+      "font_class": "eye-s",
+      "unicode": "e622",
+      "unicode_decimal": 58914
+    },
+    {
+      "icon_id": "22099634",
+      "name": "course",
+      "font_class": "course",
+      "unicode": "e620",
+      "unicode_decimal": 58912
+    },
+    {
+      "icon_id": "22099525",
+      "name": "edit",
+      "font_class": "edit",
+      "unicode": "e61f",
+      "unicode_decimal": 58911
+    },
+    {
+      "icon_id": "22099475",
+      "name": "help",
+      "font_class": "help",
+      "unicode": "e615",
+      "unicode_decimal": 58901
+    },
+    {
+      "icon_id": "22099478",
+      "name": "rule",
+      "font_class": "rule",
+      "unicode": "e617",
+      "unicode_decimal": 58903
+    },
+    {
+      "icon_id": "22099479",
+      "name": "link",
+      "font_class": "link",
+      "unicode": "e618",
+      "unicode_decimal": 58904
+    },
+    {
+      "icon_id": "22099480",
+      "name": "uploading",
+      "font_class": "uploading",
+      "unicode": "e619",
+      "unicode_decimal": 58905
+    },
+    {
+      "icon_id": "22099481",
+      "name": "vr",
+      "font_class": "vr",
+      "unicode": "e61a",
+      "unicode_decimal": 58906
+    },
+    {
+      "icon_id": "22099484",
+      "name": "complete",
+      "font_class": "complete",
+      "unicode": "e61b",
+      "unicode_decimal": 58907
+    },
+    {
+      "icon_id": "22099499",
+      "name": "download",
+      "font_class": "download",
+      "unicode": "e61c",
+      "unicode_decimal": 58908
+    },
+    {
+      "icon_id": "22099518",
+      "name": "pull-down",
+      "font_class": "pull-down",
+      "unicode": "e61d",
+      "unicode_decimal": 58909
+    },
+    {
+      "icon_id": "22099519",
+      "name": "pull-up",
+      "font_class": "pull-up",
+      "unicode": "e61e",
+      "unicode_decimal": 58910
+    },
+    {
+      "icon_id": "22099070",
+      "name": "updown",
+      "font_class": "updown",
+      "unicode": "e613",
+      "unicode_decimal": 58899
+    },
+    {
+      "icon_id": "22099071",
+      "name": "scene",
+      "font_class": "scene",
+      "unicode": "e614",
+      "unicode_decimal": 58900
+    },
+    {
+      "icon_id": "22099025",
+      "name": "message",
+      "font_class": "message",
+      "unicode": "e60c",
+      "unicode_decimal": 58892
+    },
+    {
+      "icon_id": "22099028",
+      "name": "basic",
+      "font_class": "basic",
+      "unicode": "e60d",
+      "unicode_decimal": 58893
+    },
+    {
+      "icon_id": "22099032",
+      "name": "hotspot",
+      "font_class": "hotspot",
+      "unicode": "e60e",
+      "unicode_decimal": 58894
+    },
+    {
+      "icon_id": "22099035",
+      "name": "guide",
+      "font_class": "guide",
+      "unicode": "e60f",
+      "unicode_decimal": 58895
+    },
+    {
+      "icon_id": "22099060",
+      "name": "wander",
+      "font_class": "wander",
+      "unicode": "e610",
+      "unicode_decimal": 58896
+    },
+    {
+      "icon_id": "22099068",
+      "name": "house",
+      "font_class": "house",
+      "unicode": "e611",
+      "unicode_decimal": 58897
+    },
+    {
+      "icon_id": "22099069",
+      "name": "video",
+      "font_class": "video",
+      "unicode": "e612",
+      "unicode_decimal": 58898
+    },
+    {
+      "icon_id": "20066551",
+      "name": "show_3d_normal",
+      "font_class": "show_3d_normal",
+      "unicode": "e677",
+      "unicode_decimal": 58999
+    },
+    {
+      "icon_id": "20066554",
+      "name": "show_plane_normal",
+      "font_class": "show_plane_normal",
+      "unicode": "e67d",
+      "unicode_decimal": 59005
+    },
+    {
+      "icon_id": "20066556",
+      "name": "show_roaming_selected",
+      "font_class": "show_roaming_selected",
+      "unicode": "e682",
+      "unicode_decimal": 59010
+    },
+    {
+      "icon_id": "20066557",
+      "name": "show_plane_selected",
+      "font_class": "show_plane_selected",
+      "unicode": "e684",
+      "unicode_decimal": 59012
+    },
+    {
+      "icon_id": "20066558",
+      "name": "show_3d_selected",
+      "font_class": "show_3d_selected",
+      "unicode": "e685",
+      "unicode_decimal": 59013
+    },
+    {
+      "icon_id": "20066559",
+      "name": "show_roaming_normal",
+      "font_class": "show_roaming_normal",
+      "unicode": "e686",
+      "unicode_decimal": 59014
+    }
+  ]
+}

BIN
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.ttf


BIN
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.woff


BIN
packages/qjkankan-kankan-view/public/viewer/static/lib/iconfont/iconfont.woff2


+ 24 - 2
packages/qjkankan-kankan-view/src/app.js

@@ -2,20 +2,42 @@ let _app
 let _num
 let deferred = KanKan.Deferred()
 
-export function createApp(opitons = {}) {
+export function createApp(opitons = {}, forceNew = false) {
     if (_app) {
         return
     }
+    opitons.deploy = process.env.VUE_APP_DEPLOY
     opitons.region = process.env.VUE_APP_REGION_URL
     opitons.resource = process.env.VUE_APP_RESOURCE_URL
     _num = opitons.num
     _app = new KanKan(opitons)
     deferred.resolve(_app)
     window.__sdk = _app
-    document.body.setAttribute('is-mobile', true)
+    if (opitons.mobile) {
+        document.body.setAttribute('is-mobile', true)
+    }
     return _app
 }
 
+export function createAppSingle(opitons = {}) {
+    opitons.deploy = process.env.VUE_APP_DEPLOY
+    opitons.region = process.env.VUE_APP_REGION_URL
+    opitons.resource = process.env.VUE_APP_RESOURCE_URL
+    if (opitons.mobile) {
+        document.body.setAttribute('is-mobile', true)
+    }
+
+    var app = new KanKan(opitons)
+
+    if (!_app) {
+        _app = app
+        deferred.resolve(_app)
+        window.__sdk = _app
+    }
+
+    return app
+}
+
 export function useApp() {
     if (_app) {
         return Promise.resolve(_app)

+ 0 - 485
packages/qjkankan-kankan-view/src/app.vue

@@ -1,485 +0,0 @@
-<template>
-  <Password />
-  <LoadingLogo :thumb="true" />
-  <Guide />
-  <div class="ui-view-layout" :class="{ show: show }" is-mobile="true">
-    <div class="scene" ref="scene$"></div>
-    <template v-if="dataLoaded">
-      <Information />
-      <Control />
-      <teleport v-if="refMiniMap && player.showWidgets" :to="refMiniMap">
-        <span class="button-switch" @click.stop="toggleMap">
-          <ui-icon type="show_map_collect"></ui-icon>
-        </span>
-
-        <p class="change" v-if="controls.showDollhouse" @click="changeMode('dollhouse')">
-          <ui-icon type="show_3d_normal"></ui-icon>
-          3D模型
-        </p>
-      </teleport>
-      <template v-if="refMiniMap">
-        <div :class="{ disabled: flying }" v-show="mode != 'panorama'" v-if="controls.showFloorplan && controls.showDollhouse" class="tab-layer">
-          <div class="tabs" v-if="controls.showMap">
-            <span :class="{ active: mode === 'floorplan' }" ref="floorplan_ref" @click="changeMode('floorplan', $event)">
-              <ui-icon :type="mode == 'floorplan' ? 'show_plane_selected' : 'show_plane_normal'"></ui-icon>
-              二维
-            </span>
-            <span :class="{ active: mode === 'dollhouse' }" ref="dollhouse_ref" @click="changeMode('dollhouse', $event)">
-              <ui-icon :type="mode == 'dollhouse' ? 'show_3d_selected' : 'show_3d_normal'"></ui-icon>
-
-              三维
-            </span>
-            <div class="background" ref="background"></div>
-          </div>
-        </div>
-      </template>
-    </template>
-    <UiTags />
-  </div>
-</template>
-
-<script setup>
-import { useMusicPlayer } from "@/utils/sound";
-import UiTags from "@/components/Tags";
-
-import Information from "@/components/Information";
-import Control from "@/components/Controls/Control.Mobile.vue";
-import LoadingLogo from "@/components/shared/Loading.vue";
-import OpenVideo from "@/components/openVideo/";
-import Guide from "@/components/shared/Guide.vue";
-import Password from "@/components/shared/Password.vue";
-
-import { createApp } from "@/app";
-import { ref, onMounted, computed, nextTick, watch } from "vue";
-import { useStore } from "vuex";
-import browser from "@/utils/browser";
-import { useApp, getApp } from "@/app";
-
-const musicPlayer = useMusicPlayer();
-
-let app = null;
-
-const closetagtype = () => {
-  store.commit("tag/setTagClickType", {
-    type: "",
-    data: {},
-  });
-};
-
-const store = useStore();
-const tags = computed(() => {
-  return store.getters["tag/tags"] || [];
-});
-const player = computed(() => store.getters["player"]);
-const flying = computed(() => store.getters["flying"]);
-const metadata = computed(() => store.getters["scene/metadata"]);
-const controls = computed(() => {
-  return metadata.value.controls;
-});
-const mode = computed(() => store.getters["mode"]);
-const showNavigations = computed(() => store.getters["showNavigations"]);
-const scene$ = ref(null);
-const show = ref(false);
-const dataLoaded = ref(false);
-const refMiniMap = ref(null);
-const isCollapse = ref(false);
-const background = ref(null);
-const resize = () => {
-  if (this.$refs.background && (this.mode == "floorplan" || this.mode == "dollhouse")) {
-    this.$nextTick(() => {
-      let $active = $(this.$el).find(".tabs .active");
-      background.value.style.width = $active[0].getBoundingClientRect().width + "px";
-      background.value.style.left = $active.position().left + "px";
-    });
-  }
-};
-
-watch(
-  () => player.value.showMap,
-  (val, old) => {
-    if (!isCollapse.value) {
-      let $minmap = document.querySelector("[xui_min_map]");
-      if ($minmap) {
-        if (val) {
-          $minmap.classList.remove("collapse");
-        } else {
-          $minmap.classList.add("collapse");
-        }
-      }
-    }
-  },
-  {
-    deep: true,
-  }
-);
-watch(
-  () => player.value.showWidgets,
-  (val, old) => {
-    let $minmap = document.querySelector("[xui_min_map]");
-    if ($minmap) {
-      if (val) {
-        $minmap.classList.remove("collapse");
-      } else {
-        $minmap.classList.add("collapse");
-      }
-    }
-  },
-  {
-    deep: true,
-  }
-);
-
-watch(
-  () => mode.value,
-  (val, old) => {
-    console.log(val);
-    let timer = setTimeout(() => {
-      clearTimeout(timer);
-      if (val == "floorplan") {
-        if (floorplan_ref.value && floorplan_ref.value) {
-          background.value.style.width = floorplan_ref.value.getBoundingClientRect().width + "px";
-          background.value.style.left = floorplan_ref.value.offsetLeft + "px";
-        }
-      } else if (val == "dollhouse") {
-        if (dollhouse_ref.value && dollhouse_ref.value) {
-          background.value.style.width = dollhouse_ref.value.getBoundingClientRect().width + "px";
-          background.value.style.left = dollhouse_ref.value.offsetLeft + "px";
-        }
-      }
-    }, 0);
-  },
-  {
-    deep: true,
-  }
-);
-
-const floorplan_ref = ref(null);
-const dollhouse_ref = ref(null);
-const changeMode = (name, e) => {
-  if (e) {
-    if (!flying.value) {
-      // background.value.style.width = e.srcElement.getBoundingClientRect().width + 'px'
-      // background.value.style.left = e.srcElement.offsetLeft + 'px'
-      store.commit("setMode", name);
-    }
-  } else {
-    // let t = setTimeout(() => {
-    // background.value.style.width = dollhouse_ref.value.getBoundingClientRect().width + 'px'
-    // background.value.style.left = dollhouse_ref.value.offsetLeft + 'px'
-    store.commit("setMode", name);
-    // }, 0)
-  }
-};
-// console.dir(document.querySelector(".tabs>span:last-of-type"));
-const toggleMap = () => {
-  isCollapse.value = !isCollapse.value;
-  let $minmap = document.querySelector("[xui_min_map]");
-  if ($minmap) {
-    if (!isCollapse.value) {
-      $minmap.classList.remove("collapse");
-    } else {
-      $minmap.classList.add("collapse");
-    }
-  }
-};
-
-const onClickTagInfo = (el) => {
-  el.stopPropagation();
-  let item = tags.value.find((item) => item.sid == el.target.dataset.id);
-  if (item.type == "commodity") {
-    store.commit("tag/setTagClickType", {
-      type: "goodlist",
-      data: item,
-    });
-  }
-};
-
-onMounted(() => {
-  const app = createApp({
-    num: browser.getURLParam("m"),
-    dom: scene$.value,
-    mobile: true,
-  });
-  app.Scene.lock();
-  app.use("MinMap", { theme: { camera_fillStyle: "#0076f6" } });
-  app.use("Tag");
-  app.use("TourPlayer");
-  app.Scene.on("ready", () => {
-    show.value = true;
-  });
-  app.Scene.on("error", (data) => {
-    console.error(data);
-    switch (data.code) {
-      case 5033:
-        window.location.replace(`/5033.html?m=` + browser.getURLParam("m"));
-        break;
-      case 5034:
-        window.location.replace(`/5034.html?m=` + browser.getURLParam("m"));
-        break;
-      case 5009:
-        window.location.replace(`/5034.html?m=` + browser.getURLParam("m"));
-        break;
-      case 5005:
-        window.location.replace(`/#/404.html?m=` + browser.getURLParam("m"));
-        break;
-    }
-  });
-  app.Scene.on("loaded", (pano) => {
-    refMiniMap.value = "[xui_min_map]";
-    store.commit("setFloorId", pano.floorIndex);
-    useMusicPlayer();
-  });
-  app.Scene.on("panorama.videorenderer.resumerender", () => {
-    musicPlayer.pause(true);
-  });
-
-  app.Scene.on("panorama.videorenderer.suspendrender", async () => {
-    let player = await getApp().TourManager.player;
-    if (!player.isPlaying) {
-      musicPlayer.resume();
-    }
-  });
-  app.store.on("metadata", (metadata) => {
-    let div = document.createElement("div");
-    div.innerHTML = metadata.description;
-    store.commit("scene/load", metadata);
-    if (!metadata.controls.showMap) {
-      app.MinMap.hide(true);
-    }
-    dataLoaded.value = true;
-  });
-  app.store.on("tags", (tags) => {
-    store.commit("tag/load", tags);
-  });
-  app.Camera.on("mode.beforeChange", ({ fromMode, toMode, floorIndex }) => {
-    if (fromMode) {
-      store.commit("setFlying", true);
-    }
-  });
-  app.Camera.on("mode.afterChange", ({ toMode, floorIndex }) => {
-    store.commit("setFlying", false);
-  });
-  app.Camera.on("flying.started", (pano) => {
-    store.commit("setFlying", true);
-  });
-  app.Camera.on("flying.ended", ({ targetPano }) => {
-    store.commit("setFlying", false);
-    store.commit("setPanoId", targetPano.id);
-  });
-  app.store.on("tour", async (tour) => {
-    app.TourManager.load(tour);
-    store.commit("tour/setData", {
-      tours: JSON.parse(
-        JSON.stringify(app.TourManager.tours, (key, val) => {
-          if (key === "audio") {
-            return null;
-          } else {
-            return val;
-          }
-        })
-      ),
-    });
-    store.commit("tour/setBackUp", {
-      tours: JSON.parse(
-        JSON.stringify(app.TourManager.tours, (key, val) => {
-          if (key === "audio") {
-            return null;
-          } else {
-            return val;
-          }
-        })
-      ),
-    });
-  });
-  app.store.on("floorcad", (floor) => store.commit("scene/loadFloorData", floor));
-
-  app.render();
-});
-</script>
-
-<style lang="scss">
-.tab-layer {
-  width: 100%;
-  text-align: center;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  z-index: 10;
-  position: fixed;
-  left: 50%;
-  transform: translateX(-50%);
-  top: 2.3rem;
-  pointer-events: none;
-}
-.tabs {
-  pointer-events: auto;
-  position: relative;
-  display: flex;
-  background: #222222;
-  border-radius: 6px;
-  padding: 2px;
-  justify-content: center;
-  align-items: center;
-  border: 1px solid rgba(255, 255, 255, 0.1);
-  box-shadow: inset 0px 0px 6px 0px rgba(0, 0, 0, 0.5);
-  .background {
-    position: absolute;
-    left: 2px;
-    top: 2px;
-    bottom: 2px;
-    width: 50%;
-    border-radius: 4px;
-    background: #444444;
-    box-shadow: 2px 0px 4px 0px rgba(0, 0, 0, 0.3);
-    z-index: 0;
-    transition: left 0.3s;
-  }
-  span {
-    flex: 1;
-    color: #fff;
-    opacity: 0.5;
-    border-radius: 6px;
-    height: 0.94737rem;
-    font-size: 0.36842rem;
-    transition: all 0.3s ease;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    padding-left: 10px;
-    padding-right: 10px;
-    white-space: nowrap;
-    z-index: 1;
-    i {
-      font-size: 0.47368rem;
-      margin-right: 4px;
-      pointer-events: none;
-    }
-  }
-
-  span.active {
-    opacity: 1;
-  }
-}
-
-[xui_tags_view] {
-  .tag-body {
-    /* display: none; */
-    position: absolute;
-    left: 50%;
-    bottom: 50px;
-    transform: translateX(-50%) scale(0);
-    transform-origin: bottom;
-    transition: all 0.3s cubic-bezier(0.35, 0.32, 0.65, 0.63);
-    // pointer-events: none;
-    .tag-commodity {
-      min-width: 230px;
-      height: 76px;
-      background: rgba(255, 255, 255, 0.8);
-      box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.16);
-      border-radius: 2px;
-      position: relative;
-      margin-bottom: 30px;
-      &::before {
-        content: "";
-        display: inline-block;
-        left: 50%;
-        transform: translateX(-50%);
-        width: 2px;
-        height: 28px;
-        bottom: -30px;
-        background: linear-gradient(145deg, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0));
-        position: absolute;
-      }
-      .tag-avatar {
-        position: absolute;
-        z-index: 99;
-        width: 80px;
-        height: 80px;
-        background: #ffffff;
-        box-shadow: 0px 3px 6px 0px rgb(0 0 0 / 16%);
-        border-radius: 2px;
-        top: -14px;
-        left: -12px;
-        background-size: cover;
-        pointer-events: none;
-      }
-      > p {
-        color: #131d34;
-        font-size: 16px;
-        pointer-events: none;
-      }
-      .tag-title {
-        padding: 10px 10px 10px 76px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        width: 240px;
-      }
-      .tag-info {
-        padding: 0 20px 0 76px;
-        font-size: 12px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-      }
-    }
-    &.show {
-      transform: translateX(-50%) scale(1);
-    }
-  }
-
-  .coupon {
-    width: 64px !important;
-    height: 64px !important;
-    &::after {
-      content: "發現好禮";
-      width: 100%;
-      color: #ed5d18;
-      position: absolute;
-      bottom: -24px;
-      text-align: center;
-      font-size: 14px;
-    }
-  }
-
-  .waterfall {
-    width: 70px !important;
-    height: 70px !important;
-  }
-
-  .applet_link {
-    width: 64px !important;
-    height: 64px !important;
-    border-radius: 50%;
-    background-color: #fff;
-    border: 1px solid #ed5d18;
-    position: relative;
-    overflow: hidden;
-    &::after {
-      content: "直播中";
-      width: 100%;
-      height: 20px;
-      background: #ed5d18;
-      position: absolute;
-      bottom: 0;
-      text-align: center;
-      line-height: 1.2;
-      font-size: 12px;
-      border-radius: 26%;
-    }
-  }
-}
-
-@media (orientation: landscape) {
-  .tab-layer {
-    top: 1.2rem;
-    .tabs {
-      height: 0.7rem;
-      > span {
-        height: 0.7rem;
-        font-size: 0.25rem;
-      }
-    }
-  }
-}
-</style>

BIN
packages/qjkankan-kankan-view/src/assets/images/browser/browser_Chrome.png


BIN
packages/qjkankan-kankan-view/src/assets/images/browser/browser_Edge.png


BIN
packages/qjkankan-kankan-view/src/assets/images/browser/browser_Firefox.png


BIN
packages/qjkankan-kankan-view/src/assets/images/browser/browser_Safari.png


BIN
packages/qjkankan-kankan-view/src/assets/images/browser/pic_update.png


+ 9 - 4
packages/qjkankan-kankan-view/src/components/Controls/BottomControl.vue

@@ -1,22 +1,27 @@
 <template>
-    <div class="bottom-controls" :class="{ hidden: isHidden }" :style="{ bottom }">
+    <div class="bottom-controls" :class="{ hidden: isHidden }" :style="{ bottom }" v-show="show">
         <FloorSwitch />
-        <LeftButtons />
-        <RightButtons />
+        <tours />
+        <!-- <RightButtons /> -->
     </div>
 </template>
 <script setup>
 import { computed } from 'vue'
 import { useStore } from 'vuex'
 import { ref } from 'vue'
+import { useApp, getApp } from '@/app'
 import FloorSwitch from './FloorSwitch'
-import LeftButtons from './LeftButtons'
+import tours from './tours'
 import RightButtons from './RightButtons'
 const store = useStore()
+const show = ref(false)
 const isHidden = ref(false)
 const bottom = computed(() => {
     return store.getters.controlsBottom
 })
+useApp().then(app => {
+    app.Scene.on('loaded', () => (show.value = true))
+})
 </script>
 <style lang="scss" scoped>
 .bottom-controls {

+ 3 - 1
packages/qjkankan-kankan-view/src/components/Controls/FloorSwitch.vue

@@ -1,7 +1,9 @@
 <template>
     <div class="floor-switch" :class="{ disable: flying, showTours: showTours }" v-if="floors.length > 1 && mode != 'panorama'">
         <ul>
-            <li v-if="mode != 'floorplan'" :class="{ active: 'all' == floorId }" @click.stop="onGotoFloor('all')"><b></b><span>全部</span></li>
+            <li v-if="mode != 'floorplan'" :class="{ active: 'all' == floorId }" @click.stop="onGotoFloor('all')">
+                <b></b><span>{{ $t('common.all') }}</span>
+            </li>
             <li v-for="item in floors" :key="item.id" :class="{ active: item.id == floorId }" @click.stop="onGotoFloor(item.id)">
                 <b></b><span>{{ item.name }}</span>
             </li>

+ 5 - 5
packages/qjkankan-kankan-view/src/components/Controls/LeftButtons.vue

@@ -10,19 +10,19 @@
         </div> -->
         <div class="buttons mode" :class="{ disabled: isPlay || flying }">
             <div v-if="controls.showPanorama" :class="{ active: viewmode == 'panorama' }" @click="onModeChange('panorama')">
-                <ui-icon :tip="$t('mode.panorama')" tipV="top" :type="viewmode == 'panorama' ? 'show_roaming_selected' : 'show_roaming_normal'"></ui-icon>
+                <ui-icon tipV="top" :type="viewmode == 'panorama' ? 'show_roaming_selected' : 'show_roaming_normal'"></ui-icon>
             </div>
             <div v-if="controls.showFloorplan" :class="{ active: viewmode == 'floorplan' }" @click="onModeChange('floorplan')">
-                <ui-icon :tip="$t('mode.floorplan')" tipV="top" :type="viewmode == 'floorplan' ? 'show_plane_selected' : 'show_plane_normal'"></ui-icon>
+                <ui-icon tipV="top" :type="viewmode == 'floorplan' ? 'show_plane_selected' : 'show_plane_normal'"></ui-icon>
             </div>
             <div v-if="controls.showDollhouse" :class="{ active: viewmode == 'dollhouse' }" @click="onModeChange('dollhouse')">
-                <ui-icon :tip="$t('mode.dollhouse')" tipV="top" :type="viewmode == 'dollhouse' ? 'show_3d_selected' : 'show_3d_normal'"></ui-icon>
+                <ui-icon tipV="top" :type="viewmode == 'dollhouse' ? 'show_3d_selected' : 'show_3d_normal'"></ui-icon>
             </div>
         </div>
         <!-- <div class="play-control" v-if="tours.length > 0" :class="{ disabled: flying || isSelect }"> -->
         <div class="play-control" v-if="tours.length > 0">
             <div class="play-btn tour-btn" @click="playTour">
-                <ui-icon :tip="isPlay ? $t('common.pauseTour') : $t('common.playTour')" tipV="top" :type="isPlay ? 'pause' : 'preview'"></ui-icon>
+                <ui-icon tipV="top" :type="isPlay ? 'pause' : 'preview'"></ui-icon>
             </div>
 
             <div class="tour-btn bor" @click="openTours">
@@ -67,7 +67,7 @@
 </template>
 <script setup>
 import { computed, defineProps, onMounted, ref, nextTick } from 'vue'
-import { Scrollbar, Dialog } from '@/global_components/'
+import { Scrollbar, Dialog } from '@/global_components'
 import { useApp, getApp } from '@/app'
 import { useStore } from 'vuex'
 import common from '@/utils/common'

+ 27 - 1
packages/qjkankan-kankan-view/src/components/Controls/RightButtons.vue

@@ -6,17 +6,25 @@
         <div :class="{ playing: showMusicPlaying }" v-if="showMusic" @click="onMusicClick">
             <ui-icon type="music" :tip="showMusicPlaying ? '' : $t('mode.music')" tipV="top"></ui-icon>
         </div>
+        <div v-if="controls.showRule" class="rule" @click="onRuleClick">
+            <ui-icon :tip="$t('mode.rule')" tipV="top" type="show_more_ruler"></ui-icon>
+        </div>
         <div @click="onFullScreen">
             <ui-icon :type="isFullscreen ? 'scene_window' : 'full'" :tip="isFullscreen ? $t('mode.exitFullScene') : $t('mode.fullScene')" tipV="top"></ui-icon>
             <!-- <i class="iconfont" :class="isFullscreen ? 'icon-scene_window' : 'icon-full'"></i> -->
         </div>
     </div>
+    <teleport to="body">
+        <Rules v-if="showRules" @close="closeRules" />
+    </teleport>
 </template>
 <script setup>
 import { computed, ref, onMounted } from 'vue'
 import { useStore } from 'vuex'
 import { useMusicPlayer } from '@/utils/sound'
-import { Dialog } from '@/global_components/'
+import { Dialog } from '@/global_components'
+import { useApp, getApp, getNum } from '@/app'
+import Rules from './rules'
 import { useI18n } from '@/i18n'
 const { t } = useI18n({ useScope: 'global' })
 const store = useStore()
@@ -25,12 +33,24 @@ const showMusic = computed(() => store.getters['scene/metadata'].music)
 const showMusicPlaying = ref(false)
 const musicPlayer = useMusicPlayer()
 const isFullscreen = ref(false)
+const showRules = ref(false)
 const onVRClick = () => {
     Dialog.toast(t('limit.viewInVr'))
 }
 const isPlay = computed(() => {
     return store.getters['tour/isPlay']
 })
+const closeRules = () => {
+    showRules.value = false
+    getApp().TagManager.cancelMeasure()
+    store.commit('SetOptions', { sceneUI: true })
+}
+const onRuleClick = () => {
+    showRules.value = true
+    getApp().MinMap.hide()
+    getApp().TagManager.startMeasure()
+    store.commit('SetOptions', { sceneUI: false })
+}
 const onMusicClick = () => {
     showMusicPlaying.value ? musicPlayer.pause() : musicPlayer.play()
 }
@@ -67,6 +87,12 @@ onMounted(() => {
             isFullscreen.value = !isFullscreen.value
         })
     })
+
+    useApp().then(app => {
+        app.TagManager.on('tagManager.firstMarkTagPosB', () => {
+            Dialog.toast(t('toast.clickLeft'))
+        })
+    })
 })
 musicPlayer.on('play', () => (showMusicPlaying.value = true))
 musicPlayer.on('pause', () => (showMusicPlaying.value = false))

+ 64 - 0
packages/qjkankan-kankan-view/src/components/Controls/rules/index.vue

@@ -0,0 +1,64 @@
+<!--  -->
+<template>
+    <div class="rules-box">
+        <ui-button :class="{ disabled: !next }" type="primary" @click="confirmRules"
+            >{{ $t('common.confirm') }}{{ rulesIndex >= 2 ? $t('common.endPoint') : $t('common.startPoint') }}({{ rulesIndex }}/2)</ui-button
+        >
+        <ui-button type="cancel" @click="cancelRules">{{ $t('common.cancel') }}</ui-button>
+    </div>
+</template>
+
+<script setup>
+import { reactive, toRefs, onBeforeMount, onMounted, ref, defineEmits } from 'vue'
+import { useApp, getApp, getNum } from '@/app'
+import { Dialog } from '@/global_components'
+import { useI18n } from '@/i18n'
+const { t } = useI18n({ useScope: 'global' })
+const rulesIndex = ref(1)
+const emits = defineEmits(['close'])
+const confirmRules = () => {
+    getApp().MinMap.show()
+    next.value = false
+    getApp().TagManager.confirmMeasure(rulesIndex.value)
+    if (rulesIndex.value < 2) {
+        Dialog.toast({
+            content: t('toast.ruleConfirmTips'),
+        })
+        rulesIndex.value++
+    } else {
+        cancelRules()
+    }
+}
+const cancelRules = () => {
+    getApp().MinMap.show()
+    emits('close')
+    rulesIndex.value = 1
+}
+const next = ref(false)
+onMounted(() => {
+    getApp().TagManager.on('tagManager.markTagPos', res => {
+        next.value = true
+    })
+})
+</script>
+<style lang="scss" scoped>
+.rules-box {
+    position: fixed;
+    z-index: 1000;
+    bottom: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    min-width: 150px;
+    .ui-button {
+        margin-bottom: 10px;
+        &:last-of-type {
+            margin-bottom: 0;
+        }
+        &.cancel {
+            background: rgba(92, 92, 92, 0.51) !important;
+            color: #fff !important;
+            border: none !important;
+        }
+    }
+}
+</style>

+ 411 - 0
packages/qjkankan-kankan-view/src/components/Controls/tours.vue

@@ -0,0 +1,411 @@
+<template>
+  <div class="tour-list" v-if="tours.length > 0" :class="{ ban: flying || isSelect,barshow: showTours }">
+    <div class="part-content" ref="tourScroll">
+      <!-- 多个片段 -->
+      <ul class="part-list" v-if="tours.length>1">
+        <li class="part-item" v-for="(item, index) in tours" :key="index"
+         @click="changeFrame(1, index)"
+          :class="{ 
+            active: partId == index && progressNum > 0,
+            loopspan: item.name.length > spanlength && partId == index,
+            disabled: isPlay && partId != index }" 
+          :name="index">
+          <span v-if="partId == index">{{item.name}}</span>
+          <span v-else>{{ item.name.length > spanlength ? item.name.slice(0, spanlength) : item.name }}</span>
+          <div v-if="partId == index && progressNum > 0" class="tourbar">
+            <div :style="`width:${progressNum}%;`" class="tourline"></div>
+          </div>
+        </li>
+      </ul>
+      <!-- 只有一个片段 -->
+      <ul class="part-list" v-else>
+        <li class="part-item" v-for="(item, index) in tours[0].list" :key="index" 
+        @click="changeFrame(2, index)"
+          :class="{ 
+            active: frameId == index && progressNum > 0,
+            disabled: isPlay && frameId != index }"
+           :name="index">
+          <span>片段</span>
+          <div v-if="frameId == index && progressNum > 0" class="tourbar">
+            <div :style="`width:${progressNum}%;`" class="tourline"></div>
+          </div>
+        </li>
+      </ul>
+
+    </div>
+  </div>
+</template>
+<script setup>
+import { computed, inject, onMounted,watch, ref, nextTick } from 'vue'
+import { Scrollbar, Dialog } from '@/global_components'
+import { useApp, getApp } from '@/app'
+import { useStore } from 'vuex'
+import common from '@/utils/common'
+import { useMusicPlayer } from '@/utils/sound'
+const musicPlayer = useMusicPlayer()
+
+
+const spanlength = ref(5)
+
+const triggerTour = inject("triggerTour");
+const isOpenTours = inject("isOpenTours");
+
+let timer = null
+const isSelect = ref(false)
+const store = useStore()
+const tourScroll = ref(null)
+const flying = computed(() => store.getters['flying'])
+const controls = computed(() => store.getters['scene/metadata'].controls || {})
+const showTours = computed(() => store.getters['tour/showTours'])
+const partId = computed(() => {
+  let id = store.getters['tour/partId']
+  if (isPlay.value) {
+    slideScroll()
+  }
+  return id
+})
+
+const frameId = computed(() => {
+  let id = store.getters['tour/frameId']
+  if (isPlay.value) {
+    slideScroll()
+  }
+  return id
+})
+const progressNum = ref(0)
+const isPlay = computed(() => {
+  let status = store.getters['tour/isPlay']
+  let map = document.querySelector('.kankan-app div[xui_min_map]')
+  if (map) {
+    if (status) {
+      map.classList.add('disabled')
+    } else {
+      map.classList.remove('disabled')
+    }
+  }
+  return status
+})
+const isInit = ref(false)
+const tours = computed(() => {
+  let tours = store.getters['tour/tours']
+  if (tours.length > 0) {
+    if (tourScroll.value && !isInit.value) {
+      isInit.value = true
+      new Scrollbar(tourScroll.value, { onlyHorizontal: true })
+    }
+  }
+  return tours
+})
+const onModeChange = name => {
+  store.commit('setMode', name)
+}
+
+const playTour = async () => {
+  let player = await getApp().TourManager.player
+  if (isPlay.value) {
+    store.commit('tour/setData', { isPlay: true })
+    player.pause()
+  } else {
+    store.commit('tour/setData', { isPlay: true })
+    player.play(partId.value)
+  }
+}
+
+
+
+
+const hanlderTourPartPlay = time => {
+  if (!timer) {
+    timer = KanKan.Animate.transitions.start(progress => {
+      progressNum.value = progress * 100
+    }, time)
+  }
+}
+const cancelTimer = () => {
+  if (timer) {
+    KanKan.Animate.transitions.cancel(timer)
+    timer = null
+  }
+}
+const slideScroll = () => {
+  nextTick(() => {
+    let t = setTimeout(() => {
+      clearTimeout(t)
+      let id = tours.value.length > 1 ? partId.value : frameId.value
+      let item = document.querySelector(`.part-item[name="${id}"]`)
+      item.scrollIntoView({ block: 'center', behavior: 'smooth', inline: 'center' })
+    }, 100)
+  })
+}
+const hanlderTour = async () => {
+  let player = await getApp().TourManager.player
+  player.on('play', data => {
+    musicPlayer.pause(true)
+  })
+  player.on('pause', tours => {
+    console.log('pause', player)
+    musicPlayer.resume()
+
+    progressNum.value = 0
+    cancelTimer()
+    store.commit('tour/setData', { isPlay: false })
+  })
+  player.on('end', tours => {
+    musicPlayer.resume()
+    progressNum.value = 100
+    slideScroll()
+    store.commit('tour/setData', { isPlay: false })
+    cancelTimer()
+  })
+
+  let currPartId = null
+  let currProgress = 0
+  let currFrames = 0
+
+  player.on('progress', data => {
+    if (tours.value.length == 1) {
+      progressNum.value = data.progress * 100
+    } else {
+      if (currPartId != data.partId) {
+        currPartId = data.partId
+        currFrames = tours.value[data.partId].list.length
+        currProgress = 0
+      } else {
+        currProgress += data.progress / currFrames
+        if (currProgress >= 100) {
+          currProgress = 100
+        }
+
+        progressNum.value = currProgress
+      }
+    }
+    store.commit('tour/setData', { partId: data.partId, frameId: data.frameId, isPlay: true })
+  })
+
+}
+const getPartTime = partId => {
+  cancelTimer()
+  let time = 0
+  for (let i = 0; i < tours.value[partId].list.length; i++) {
+    if (!tours.value[partId].list[i]._end) {
+      time += tours.value[partId].list[i].time - 0
+      if (!tours.value[partId].list[i]._notrans) {
+        time += 1000
+      }
+    }
+  }
+  return time
+}
+
+const openTours = () => {
+  // showTours.value = !showTours.value
+  store.commit('tour/setData', { showTours: !showTours.value })
+ 
+  nextTick(() => {
+    if (isPlay.value) {
+      slideScroll()
+    }
+  })
+}
+const changeFrame = async (type, id) => {
+  progressNum.value = 0
+  // recorder.selectFrame(id)
+  let player = await getApp().TourManager.player
+  // player.selectFrame(id)
+  isSelect.value = true
+  if (type == 1) {
+    player.selectPart(id)
+    console.log(tours.value[id].frameId)
+    let f_id = 0
+    if (tours.value[id].frameId) {
+      f_id = tours.value[id].frameId
+    }
+    player.selectFrame(f_id).then(() => {
+      isSelect.value = false
+    })
+    store.commit('tour/setData', {
+      frameId: f_id,
+      partId: id,
+    })
+  } else {
+    player.selectFrame(id).then(() => {
+      isSelect.value = false
+    })
+    store.commit('tour/setData', {
+      frameId: id,
+    })
+  }
+
+  slideScroll()
+}
+const onClickHandler = async () => {
+  if (isPlay.value) {
+    let player = await getApp().TourManager.player
+    player.pause()
+    musicPlayer.resume()
+  }
+}
+
+
+watch(triggerTour,()=>{
+  playTour()
+})
+
+watch(isOpenTours,()=>{
+  openTours()
+})
+
+watch(isPlay,()=>{
+  window.parent.postMessage(
+            {
+            source: "qjkankan",
+            event: "isPlayTours",
+            params: {
+              isPlay:isPlay.value,
+            },
+        },
+        "*"
+    );
+})
+
+
+onMounted(() => {
+  useApp().then(async sdk => {
+    hanlderTour()
+  })
+
+  nextTick(() => {
+    let player = document.querySelector('.player[name="main"]')
+    player.addEventListener('click', onClickHandler)
+  })
+})
+</script>
+
+<style lang="scss" scoped>
+$width: 1150px;
+
+.controls-left-buttons {
+  margin-left: 20px;
+  margin-bottom: 20px;
+  display: flex;
+}
+
+.buttons.tour {
+  margin-right: 10px;
+
+  >div {
+    margin-left: 0px;
+    margin-right: 0px;
+    padding: 0 10px;
+
+    &.show-list {
+      border-left: solid 1px var(--editor-font-color);
+    }
+
+    .icon-pull-down {
+      font-size: 12px;
+    }
+
+    span {
+      right: -10px;
+    }
+  }
+}
+
+.tour-list {
+  position: fixed;
+  bottom: 68px;
+  left: 50%;
+  transform: translateX(-50%);
+  text-align: center;
+  max-width: $width;
+  overflow: hidden;
+  max-height: 0;
+  transition: .3s all ease;
+  z-index: 9;
+
+  &.ban {
+    pointer-events: none;
+  }
+
+  .part-content {
+    display: flex;
+    flex-direction: row;
+    overflow: hidden;
+    padding: 10px 30px;
+    min-width: 400px;
+    background: linear-gradient(268deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.5) 8%, rgba(0, 0, 0, 0.5) 92%, rgba(0, 0, 0, 0) 100%);
+
+    .part-list {
+      display: flex;
+
+      >li {
+        width: 90px;
+        height: 40px;
+        background: rgba(24, 24, 24, .5);
+        line-height: 40px;
+        margin: 0 6px;
+        cursor: pointer;
+
+        >span,
+        >div>span {
+          cursor: pointer;
+          display: inline-block;
+          color: rgba(255, 255, 255, 0.8);
+        }
+
+        &.loopspan {
+
+          >span,
+          >div>span {
+            animation: 5s wordsLoop linear infinite normal;
+          }
+        }
+
+        &.active {
+          position: relative;
+
+          .tourbar {
+            position: absolute;
+            width: 78px;
+            left: 6px;
+            right: 6px;
+            bottom: 4px;
+            height: 2px;
+            border-radius: 2px;
+            background: #000;
+            overflow: hidden;
+
+            .tourline {
+              width: 50%;
+              height: 100%;
+              background: var(--colors-primary-base);
+            }
+          }
+        }
+
+        &:hover {
+          opacity: 0.7;
+        }
+      }
+    }
+  }
+}
+
+.barshow {
+  max-height: 62px;
+}
+
+
+@keyframes wordsLoop {
+  0% {
+    transform: translateX(100%);
+    -webkit-transform: translateX(100%);
+  }
+
+  100% {
+    transform: translateX(-100%);
+    -webkit-transform: translateX(-100%);
+  }
+}
+</style>

+ 12 - 11
packages/qjkankan-kankan-view/src/components/Information/View.Pc.vue

@@ -1,8 +1,5 @@
 <template>
-    <div class="title" @click="onShowDescription" :class="{ 'pull-up': showDescription, collapse: !showTitle }">
-        <div class="back-btn" @click.stop="showTitle = !showTitle">
-            <i class="iconfont icon-_back"></i>
-        </div>
+    <div class="title" @click="onShowDescription" :class="{ 'pull-up': showDescription, }">
         <div class="text">
             <div>{{ metadata.title }}</div>
         </div>
@@ -19,10 +16,10 @@
 import { ref, computed } from 'vue'
 
 import { useStore } from 'vuex'
-const showTitle = ref(true)
 const store = useStore()
 const metadata = computed(() => store.getters['scene/metadata'])
 const showDescription = ref(false)
+const showTitle = ref(true)
 
 const onShowDescription = () => {
     showDescription.value = !showDescription.value
@@ -33,11 +30,11 @@ const onShowDescription = () => {
 .title {
     display: flex;
     align-items: center;
-    padding-right: 30px;
-    width: 100%;
+    justify-content: center;
     height: 100%;
     cursor: pointer;
     transition: all 0.1s;
+    background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.3) 50%, rgba(0,0,0,0) 100%);
     &.collapse {
         // width: 34px;
         padding-right: 0;
@@ -78,9 +75,10 @@ const onShowDescription = () => {
     }
     .text {
         // width: 190px;
-        width: 240px;
-        padding-left: 20px;
+        min-width: 240px;
         transition: width 0.3s;
+        padding: 0 20px;
+
         > div {
             width: 100%;
             overflow: hidden;
@@ -95,6 +93,8 @@ const onShowDescription = () => {
     }
 
     &.pull-up {
+        background: rgba($color: #000000, $alpha: 0.5);
+        border-radius: 17px;
         // .text {
         //     width: 240px;
         //     padding-left: 20px;
@@ -117,9 +117,10 @@ const onShowDescription = () => {
 .description {
     display: none;
     position: absolute;
-    left: 10px;
+    left: 50%;
+    transform: translateX(-50%);
     top: calc(100% + 10px);
-    background: rgba(15, 15, 15, 0.3);
+    background: rgba(15, 15, 15, 0.5);
     border-radius: 10px;
     &.show {
         display: block;

+ 7 - 6
packages/qjkankan-kankan-view/src/components/Information/index.vue

@@ -7,8 +7,8 @@
 </template>
 
 <script setup>
-import ViewMobile from './View.Mobile.vue'
 import ViewPc from './View.Pc.vue'
+import ViewMobile from './View.Mobile.vue'
 import { ref, markRaw, onMounted, computed, watch } from 'vue'
 import { useApp } from '@/app'
 import { useStore } from 'vuex'
@@ -27,19 +27,20 @@ useApp().then(app => {
 <style lang="scss" scoped>
 .information {
     position: absolute;
-    left: 0;
-    top: 20px;
+    left: 50%;
+    transform: translateX(-50%);
+    top: 30px;
     height: 34px;
     border-radius: 0 34px 34px 0;
-    background: rgba(0, 0, 0, 0.3);
     pointer-events: all;
     color: rgba(255, 255, 255, 0.88);
     z-index: 100;
     &.mobile {
         position: absolute;
         top: 0;
-        left: 50%;
-        transform: translateX(-50%);
+        left: 0;
+        // left: 50%;
+        transform: none;
         width: 100%;
         background: none;
         height: 0;

+ 44 - 36
packages/qjkankan-kankan-view/src/components/Tags/constant.js

@@ -1,37 +1,45 @@
-export const custom = {
-    image: {
-        icon: 'pic',
-        upload: true,
-        uploadPlace: `上传图片`,
-        accept: `.jpg,.png`,
-        multiple: true,
-        name: '图片',
-        maxSize: 5 * 1024 * 1024,
-        maxNum: 9,
-        othPlaceholder: '支持JPG、PNG图片格式,单张不超过5MB,最多支持上传9张。',
-    },
-    video: {
-        icon: 'video',
-        upload: true,
-        uploadPlace: `上传视频`,
-        accept: `.mp4, .mov`,
-        multiple: false,
-        name: '视频',
-        maxSize: 20 * 1024 * 1024,
-        othPlaceholder: '支持MP4、MOV视频格式,码率小于2Mbps,不超过20MB',
-    },
-    audio: {
-        icon: 'music',
-        upload: true,
-        uploadPlace: `上传音频`,
-        accept: '.mp3, .wav',
-        multiple: false,
-        name: '音频',
-        maxSize: 5 * 1024 * 1024,
-        othPlaceholder: '支持MP3、WAV格式,不超过5MB',
-    },
-    link: {
-        icon: 'web',
-        name: '链接',
-    },
+import i18n from '@/i18n'
+const { t } = i18n.global
+
+export const custom = () => {
+    return {
+        image: {
+            icon: 'pic',
+            upload: true,
+            uploadPlace: t('common.upload') + t('common.image'),
+            accept: `.jpg,.png`,
+            multiple: true,
+            name: t('common.image'),
+            maxSize: 5 * 1024 * 1024,
+            maxNum: 9,
+            // othPlaceholder: '支持JPG、PNG图片格式,单张不超过5MB,最多支持上传9张。',
+            othPlaceholder: t('tag.toolbox.metaImageTips', { form: 'jpg/png', size: '5MB', maxlength: '9' }),
+        },
+        video: {
+            icon: 'video',
+            upload: true,
+            uploadPlace: t('common.upload') + t('common.video'),
+            accept: `.mp4, .mov`,
+            multiple: false,
+            name: t('common.video'),
+            maxSize: 20 * 1024 * 1024,
+            // othPlaceholder: '支持MP4、MOV视频格式,码率小于2Mbps,不超过20MB',
+            othPlaceholder: t('tag.toolbox.metaVideoTips', { form: 'mp4/mov', size: '20MB', bit: '2Mbps' }),
+        },
+        audio: {
+            icon: 'music',
+            upload: true,
+            uploadPlace: t('common.upload') + t('common.audio'),
+            accept: '.mp3, .wav',
+            multiple: false,
+            name: t('common.audio'),
+            maxSize: 5 * 1024 * 1024,
+            // othPlaceholder: '支持MP3、WAV格式,不超过5MB',
+            othPlaceholder: t('tag.toolbox.metaAudioTips', { form: 'mp3/wav', size: '5MB' }),
+        },
+        link: {
+            icon: 'web',
+            name: t('common.link'),
+        },
+    }
 }

+ 0 - 353
packages/qjkankan-kankan-view/src/components/Tags/goods-list.vue

@@ -1,353 +0,0 @@
-<template>
-  <transition mode="out-in" appear>
-    <div class="goodlist" v-show="tagclick.type == 'goodlist'">
-      <div class="head-pages">
-        <div>
-          <span>{{ current + 1 }}</span
-          ><span>/{{ tagclick.data.products ? tagclick.data.products.length : "-" }}</span>
-        </div>
-        <ui-icon @click.stop="emit('close')" type="state_f"></ui-icon>
-      </div>
-      <div class="swiper-container" id="goodlist">
-        <ul class="swiper-wrapper">
-          <li class="swiper-slide" v-for="(i, index) in tagclick.data.products" :key="index">
-            <viewimg :list="i.pics" :keyid="`viewimg_${index+1}`"/>
-            
-            <div class="info">
-              <p>{{ i.name }}</p>
-              <div v-if="i.skus">
-                <span>{{ i.price[0].symbol }}</span
-                ><span>{{ i.currentSku.price }}</span>
-              </div>
-              <ul>
-                <li>
-                  <span>規格:</span>
-                  <ul>
-                    <li @click.stop="onClickSku(item)" :class="{ active: item.id == i.currentSku.id }" v-for="(item, idx) in i.skus" :key="idx">
-                      <span v-if="item.properties[0]">
-                        {{ item.properties[0].value }}
-                      </span>
-                    </li>
-                  </ul>
-                </li>
-                <li>
-                  <span>數量:</span>
-                  <div class="number">
-                    <ui-icon
-                      @click="
-                        () => {
-                          i.cartnum--;
-                          i.cartnum = Math.max(i.cartnum, 0);
-                        }
-                      "
-                      type="cad-neiqiang"
-                    ></ui-icon>
-                    <input maxlength="5" v-model="i.cartnum" type="number" />
-                    <ui-icon
-                      @click="
-                        () => {
-                          i.cartnum++;
-                          i.cartnum = Math.min(i.cartnum, 9999);
-                        }
-                      "
-                      type="add"
-                    ></ui-icon>
-                  </div>
-                </li>
-              </ul>
-            </div>
-            <div class="goods-button">
-              <div @click.stop="viewDetail(i)">查看詳情</div>
-              <div @click.stop="addCart(i)">加入購物車</div>
-            </div>
-          </li>
-        </ul>
-      </div>
-    </div>
-  </transition>
-</template>
-
-<script setup>
-import { onMounted, watch, toRaw, computed, defineEmits, ref, defineProps, nextTick } from "vue";
-import { useApp, getApp } from "@/app";
-import { useStore } from "vuex";
-import * as apis from "@/apis/index.js";
-import { Loading,Dialog } from "@/global_components/";
-import browser from "@/utils/browser";
-import viewimg from "@/views/viewimg";
-
-
-// get_product_info
-const store = useStore();
-
-const tagclick = computed(() => store.getters["tag/tagClickType"]);
-
-const emit = defineEmits(["close"]);
-
-const current = ref(0);
-
-const viewDetail = (item) => {
-    apis.burying_point({type:3});
-    browser.openLink(`/pages/item/item?productId=${item.id}`,`https://m.cdfmembers.com/shop/600667208/item?productId=${item.id}`)
-};
-
-const onClickSku = (item) => {
-  let tempData = toRaw(tagclick.value.data);
-
-  tempData.products[current.value] = {
-    ...tempData.products[current.value],
-    currentSku: { ...item },
-  };
-
-  store.commit("tag/setTagClickType", {
-    type: tagclick.value.type,
-    data: tempData,
-  });
-};
-
-const addCart = async (item) => {
-  Loading.show();
-
-  let result = await apis.inCat({
-    accessToken: browser.getURLParam("AccessToken"),
-    skuId: item.currentSku.id,
-    num: item.cartnum,
-  });
-
-
-  Loading.hide();
-  if (result.data.status==200) {
-   return Dialog.toast({ content: `添加成功`, type: 'success' })
-  } else{
-   Dialog.toast({ content: `登录状态失效,请重新登录`, type: 'error' })
-   setTimeout(() => {
-    browser.openLink(`/pages/login/login`)
-   }, 700);
-   return
-  }
-  
-};
-
-const updateProductsById = async (idx) => {
-  Loading.show();
-  let res = await apis.get_product_info({
-    // productId: 'p15677829'
-    productId: tagclick.value.data.products[idx].id,
-  });
-
-  let tempData = toRaw(tagclick.value.data);
-
-  tempData.products[idx] = {
-    ...tempData.products[idx],
-    ...res.data,
-    currentSku: res.data.skus[0] || {
-      price: "",
-      id: "",
-    },
-    cartnum: 1,
-  };
-
-  store.commit("tag/setTagClickType", {
-    type: tagclick.value.type,
-    data: tempData,
-  });
-  Loading.hide();
-};
-
-watch(
-  () => tagclick.value.type,
-  (val, old) => {
-    if (val === "goodlist") {
-      updateProductsById(current.value);
-    }
-  }
-);
-
-const brandScroll = () => {
-  nextTick(() => {
-    let t = setTimeout(() => {
-      clearTimeout(t);
-      new Swiper("#goodlist", {
-        effect: "coverflow",
-        grabCursor: true,
-        centeredSlides: true,
-        slidesPerView: "auto",
-        coverflowEffect: {
-          rotate: 0,
-          stretch: -40,
-          depth: 100,
-          modifier: 1,
-          slideShadows: false,
-        },
-        on: {
-          touchMove(swiper, e) {
-            e.stopPropagation();
-            e.preventDefault();
-          },
-          slideChange() {
-            current.value = this.activeIndex;
-            updateProductsById(current.value);
-          },
-        },
-      });
-    }, 100);
-  });
-};
-
-onMounted(() => {
-  brandScroll();
-});
-</script>
-
-<style lang="scss" scoped>
-.goodlist {
-  position: fixed;
-  width: 100%;
-  height: 100%;
-  left: 0;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  margin: 0 auto;
-  max-width: 500px;
-  z-index: 101;
-  background: rgba(0, 0, 0, 0.2);
-  display: flex;
-  align-items: center;
-  flex-direction: column;
-  justify-content: center;
-  .head-pages {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    margin-bottom: 10px;
-    width: 76%;
-    > div {
-      span {
-        font-size: 14px;
-        &:last-of-type {
-          color: rgba(255, 255, 255, 0.5);
-        }
-      }
-    }
-    > i {
-      color: rgba(0, 0, 0, 1);
-      font-size: 20px;
-    }
-  }
-  #goodlist {
-    width: 100%;
-    overflow: hidden;
-    padding-right: 2px;
-    position: relative;
-    > ul {
-      > li {
-        width: 76%;
-        border-radius: 2px;
-        position: relative;
-        font-size: 0;
-        overflow: hidden;
-        background: #fff;
-        padding-bottom: 14px;
-        
-      
-        .info {
-          font-size: 14px;
-          color: #131d34;
-          padding: 16px 20px;
-          > p {
-            font-size: 16px;
-            width: 100%;
-            line-height: 1.5;
-          }
-          > div {
-            color: var(--editor-main-color);
-            padding: 8px 0px 10px;
-            border-bottom: 1px solid #ebebeb;
-            > span {
-              font-size: 16px;
-              &:first-of-type {
-                font-size: 12px;
-                margin-right: 4px;
-              }
-            }
-          }
-          > ul {
-            padding: 12px 0;
-            border-bottom: 1px solid #ebebeb;
-
-            > li {
-              margin: 10px 0;
-              color: #909090;
-              &:last-of-type {
-                display: flex;
-                justify-content: space-between;
-                align-items: center;
-              }
-              > span {
-                font-size: 12px;
-              }
-              > ul {
-                display: block;
-                > li {
-                  display: inline-block;
-                  > span {
-                    display: inline-block;
-                    border: 1px solid #ebebeb;
-                    padding: 2px 4px;
-                    min-width: 73px;
-                    height: 30px;
-                    line-height: 30px;
-                    margin: 8px 8px 0 0;
-                    text-align: center;
-                    border-radius: 4px;
-                    font-size: 12px;
-                  }
-                  &.active {
-                    > span {
-                      border: solid 1px var(--editor-main-color);
-                      color: var(--editor-main-color);
-                    }
-                  }
-                }
-              }
-              .number {
-                display: flex;
-                i {
-                  font-size: 12px;
-                  border: 1px solid #ebebeb;
-                  padding: 2px 8px;
-                  border-radius: 15px;
-                }
-                input {
-                  max-width: 40px;
-                  text-align: center;
-                  color: #131d34;
-                }
-              }
-            }
-          }
-        }
-        .goods-button {
-          display: flex;
-          justify-content: space-between;
-          font-size: 16px;
-          padding: 0 20px;
-
-          > div {
-            height: 42px;
-            background: #ff8e24;
-            border-radius: 4px;
-            width: 48%;
-            text-align: center;
-            line-height: 42px;
-            &:last-of-type {
-              background: var(--editor-main-color);
-            }
-          }
-        }
-      }
-    }
-  }
-}
-</style>

+ 170 - 172
packages/qjkankan-kankan-view/src/components/Tags/index.vue

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

+ 0 - 130
packages/qjkankan-kankan-view/src/components/Tags/link-manage.vue

@@ -1,130 +0,0 @@
-<!--  -->
-<template>
-    <div class="link-manage">
-        <div class="header">
-            <div class="header-title">{{ $t('tag.toolbox.addLink') }}</div>
-        </div>
-        <div class="link-content">
-            <ui-input width="100%" @input="onInput('text')" :placeholder="$t('tag.toolbox.linkTitleTips')" type="text" v-model="text" require :error="error.text" :maxlength="40" />
-            <ui-input width="100%" type="text" v-model="link" @input="onInput('link')" :error="error.link" require :placeholder="$t('tag.toolbox.linkUrlTips')" />
-        </div>
-        <div class="btn">
-            <ui-button class="cancel" @click="emit('close')">{{ $t('common.cancel') }}</ui-button>
-            <ui-button type="primary" @click="confirm">{{ $t('common.add') }}</ui-button>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import { reactive, toRefs, onBeforeMount, onMounted, defineEmits, defineProps, ref } from 'vue'
-// 注册事件
-const emit = defineEmits(['close', 'confirm'])
-const text = ref('')
-const link = ref('')
-const error = ref({
-    text: '',
-    link: '',
-})
-const onInput = type => {
-    if (type == 'text') {
-        if (text.value == '') {
-            error.value.text = `${t('tag.toolbox.linkTitleTips')}`
-        } else {
-            error.value.text = ''
-        }
-    } else if (type == 'link') {
-        if (link.value == '') {
-            error.value.link = `${t('tag.toolbox.linkUrlTips')}`
-        } else {
-            error.value.link = ''
-        }
-    }
-}
-
-const confirm = () => {
-    if (text.value == '') {
-        error.value.text = `${t('tag.toolbox.linkTitleTips')}`
-    } else {
-        error.value.text = ''
-    }
-    if (link.value == '') {
-        error.value.link = `${t('tag.toolbox.linkUrlTips')}`
-    } else {
-        error.value.link = ''
-    }
-
-    if (text.value == '' || link.value == '') {
-        return
-    }
-    emit('confirm', { text, link })
-}
-</script>
-<style lang="scss" scoped>
-.link-manage {
-    position: absolute;
-    width: 400px;
-    // height: 310px;
-    background: rgba(27, 27, 28, 0.9);
-    box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
-    border: 1px solid #000000;
-    backdrop-filter: blur(4px);
-    left: -22px;
-    top: 100%;
-    margin-top: 5px;
-    z-index: 100;
-    &::after {
-        position: absolute;
-        content: '';
-        left: 29px;
-        top: -10px;
-        width: 0;
-        height: 0;
-        border-left: 6px solid transparent;
-        border-right: 6px solid transparent;
-        border-bottom: 10px solid rgba(27, 27, 28, 0.8);
-    }
-    .link-content {
-        border-bottom: 1px solid rgba(255, 255, 255, 0.16);
-        padding: 40px 20px;
-        .ui-input {
-            margin-bottom: 30px;
-            &:last-of-type {
-                margin-bottom: 0;
-            }
-        }
-    }
-    .header {
-        height: 60px;
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        padding: 0 20px;
-        box-sizing: border-box;
-        color: #999;
-        border-bottom: 1px solid rgba(255, 255, 255, 0.16);
-        .header-title {
-            font-size: 16px;
-            font-weight: bold;
-        }
-    }
-    .btn {
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        padding: 0 85px;
-        height: 60px;
-        .cancel {
-            color: #00c8af;
-            border: 1px solid #00c8af;
-            &:hover {
-                opacity: 0.9;
-            }
-        }
-        button {
-            &:first-of-type {
-                margin-right: 10px;
-            }
-        }
-    }
-}
-</style>

+ 0 - 104
packages/qjkankan-kankan-view/src/components/Tags/metas-upload.vue

@@ -1,104 +0,0 @@
-<!--  -->
-<template>
-    <div class="metas-upload">
-        <ui-input
-            type="file"
-            v-if="type != 'link'"
-            v-show="hotData.media[type].length <= 0"
-            :class="{ hide: audioInfo.length > 0 && type == 'audio' }"
-            :placeholder="custom[type].uploadPlace"
-            :disable="custom[type].upload"
-            :scale="custom[type].scale"
-            :accept="custom[type].accept"
-            :multiple="custom[type].multiple"
-            :maxSize="custom[type].maxSize"
-            :maxLen="custom[type].maxNum"
-            :othPlaceholder="custom[type].othPlaceholder"
-            @update:modelValue="data => hanlderFiles(data)"
-        >
-        </ui-input>
-        <metasWeb v-else />
-        <metasImage v-if="imageList.length > 0 && type == 'image'" />
-        <metasVideo v-if="videoSrc.length > 0 && type == 'video'" />
-        <metasAudio v-if="audioInfo.length > 0 && type == 'audio'" />
-    </div>
-</template>
-
-<script setup>
-import { reactive, toRefs, onBeforeMount, onMounted, ref, defineProps, computed, watch } from 'vue'
-import { useStore } from 'vuex'
-import { Loading, Dialog } from '@/global_components/'
-import { custom } from './constant.js'
-import metasImage from './metas/metas-image'
-import metasVideo from './metas/metas-video'
-import metasAudio from './metas/metas-audio'
-import metasWeb from './metas/metas-web'
-const store = useStore()
-const imageNum = ref(0)
-const props = defineProps({
-    type: {
-        type: String,
-        default: null,
-    },
-})
-const hotData = computed(() => store.getters['tag/hotData'])
-const imageList = computed(() => {
-    return hotData.value.media.image || []
-})
-const videoSrc = computed(() => {
-    return hotData.value.media.video || []
-})
-const audioInfo = computed(() => {
-    return hotData.value.media.audio || []
-})
-
-const hanlderFiles = data => {
-    switch (props.type) {
-        case 'image':
-            // store.commit('tag/setImageList', data[0])
-            setImageList(data[0])
-            break
-        case 'video':
-            store.commit('tag/setVideo', data)
-            break
-        case 'audio':
-            store.commit('tag/setAudio', data)
-            break
-    }
-}
-const setImageList = data => {
-    let picLength = 0
-    let list = JSON.parse(JSON.stringify(imageList.value))
-    if (list.length > 0) {
-        picLength = list.length
-    }
-    for (let i = 0; i < data.length; i++) {
-        if (list.length < custom['image'].maxNum) {
-            list.push('')
-            var index = i + picLength
-            list[index] = { src: URL.createObjectURL(data[i]), file: data[i] }
-        } else {
-            Dialog.toast({
-                type: 'error',
-                content: `${t('limit.maxLengthFile', { length: custom['image'].maxNum })}`,
-            })
-            break
-        }
-    }
-    store.commit('tag/setImageList', list)
-}
-</script>
-<style lang="scss" scoped>
-.hide {
-    display: none;
-}
-.metas-upload {
-    width: 100%;
-    height: 100%;
-    position: relative;
-    .ui-input {
-        width: 100%;
-        height: 100%;
-    }
-}
-</style>

+ 154 - 0
packages/qjkankan-kankan-view/src/components/Tags/metas/image-view.vue

@@ -0,0 +1,154 @@
+<!--  -->
+<template>
+    <div class="image-view">
+        <div class="swiper mySwiper">
+            <div class="swiper-wrapper">
+                <div class="swiper-slide" v-for="(i, index) in imageList">
+                    <div class="swiper-zoom-container">
+                        <div :id="`vmRef_${index}`" class="swiper-zoom-target" :style="`background-image: url(${common.changeUrl(i.src)})`"></div>
+                    </div>
+                </div>
+            </div>
+            <div class="swiper-pagination"></div>
+            <!-- <div class="swiper-button-next"></div>
+      <div class="swiper-button-prev"></div> -->
+        </div>
+    </div>
+</template>
+
+<script setup>
+// import Swiper from './swiper/swiper.js'
+// import './swiper/swiper.css'
+// import './scale/previewImage.min'
+// import { zoomElement } from './scale/index.js'
+import { reactive, toRefs, onBeforeMount, onMounted, computed, ref, nextTick } from 'vue'
+import { useStore } from 'vuex'
+import common from '@/utils/common'
+const store = useStore()
+const hotData = computed(() => store.getters['tag/hotData'])
+const imageList = computed(() => {
+    let list = hotData.value.media.image
+
+    return list
+})
+const vmZoom = ref([])
+const zoomList = []
+onMounted(() => {
+    let urls = []
+    var swiper = new Swiper('.mySwiper', {
+        zoom: {
+            toggle: false,
+            maxRatio: 5,
+        },
+        pagination: {
+            el: '.swiper-pagination',
+        },
+        on: {
+            init: function (swiper) {
+                // for (let i = 0; i < imageList.value.length; i++) {
+                //     vmZoom.value[i] = document.getElementById(`vmRef_${i}`)
+                //     zoomElement(vmZoom.value[i])
+                // }
+            },
+            transitionStart: function (swiper) {
+                // alert(swiper.previousIndex)
+                // console.log(vmZoom.value[swiper.previousIndex].style.transform)
+                // let scale = getTransform(vmZoom.value[swiper.previousIndex])
+            },
+
+            touchStart: function (swiper, event) {
+                // console.log(swiper.previousIndex)
+            },
+        },
+        navigation: {
+            nextEl: '.swiper-button-next',
+            prevEl: '.swiper-button-prev',
+        },
+    })
+    // const getTransform = el => {
+    //     var st = window.getComputedStyle(el, null)
+    //     var tr =
+    //         st.getPropertyValue('-webkit-transform') ||
+    //         st.getPropertyValue('-moz-transform') ||
+    //         st.getPropertyValue('-ms-transform') ||
+    //         st.getPropertyValue('-o-transform') ||
+    //         st.getPropertyValue('transform') ||
+    //         'FAIL'
+
+    //     var values = tr.split('(')[1].split(')')[0].split(',')
+    //     var a = values[0]
+    //     var b = values[1]
+
+    //     var scale = Math.sqrt(a * a + b * b)
+    //     console.log('Scale: ' + scale)
+    //     return scale
+    //     // var angle = Math.round(Math.atan2(b, a) * (180 / Math.PI))
+    //     // console.log('Rotate: ' + angle + 'deg')
+    // }
+    nextTick(() => {
+        for (let i = 0; i < imageList.value.length; i++) {
+            // console.log(vmZoom.value[i])
+            // zoomElement(vmZoom.value[i])
+        }
+    })
+    // for (let i = 0; i < imageList.value.length; i++) {
+    //     urls.push(common.changeUrl(imageList.value[i].src))
+    // }
+    // var obj = {
+    //     urls,
+    //     current: urls[0],
+    // }
+    // console.log(previewImage)
+    // previewImage.start(obj)
+})
+</script>
+
+<style lang="scss" scoped>
+.image-view {
+    width: 100%;
+    height: 100%;
+    // position: fixed;
+    // top: 0;
+    // left: 0;
+    // transform: translate3d(0, 0, 0);
+    // overflow: hidden;
+
+    .swiper {
+        width: 100%;
+        height: 100%;
+
+        .swiper-slide {
+            transform: translate3d(0, 0, 0);
+            overflow: hidden;
+        }
+        .swiper-zoom-container {
+            width: 100%;
+            height: 100%;
+            transform: translate3d(0, 0, 0);
+            // overflow: hidden;
+            .swiper-zoom-target {
+                width: 100%;
+                height: 100%;
+                background-position: center;
+                background-size: contain;
+                margin: 0 auto;
+                transform: translate3d(0, 0, 0);
+                // img {
+                //     width: 100%;
+                //     height: 100%;
+                // }
+            }
+        }
+    }
+}
+</style>
+<style lang="scss">
+.image-view {
+    .swiper-pagination-bullet {
+        background: #f2f2f2;
+    }
+    .swiper-pagination-bullet-active {
+        background: var(--editor-main-color);
+    }
+}
+</style>

+ 1 - 1
packages/qjkankan-kankan-view/src/components/Tags/metas/metas-audio.vue

@@ -13,7 +13,7 @@
 <script setup>
 import { reactive, toRefs, onBeforeMount, onMounted, ref, computed } from 'vue'
 import { useStore } from 'vuex'
-import { Cropper, Loading, Dialog } from '@/global_components/'
+import { Cropper, Loading, Dialog } from '@/global_components'
 import { custom } from '../constant.js'
 import common from '@/utils/common'
 const store = useStore()

+ 149 - 42
packages/qjkankan-kankan-view/src/components/Tags/metas/metas-image.vue

@@ -12,7 +12,12 @@
         </div>
         <div class="over-box">
             <div v-show="!loading" class="image-list" :style="`transform:translateX(${-100 * imageNum}%);`">
-                <div :style="`transform:translateX(${100 * index}%);background-image:url(${common.changeUrl(i.src)});`" class="image-item" v-for="(i, index) in imageList"></div>
+                <div
+                    @click="openScale(i.src)"
+                    :style="`transform:translateX(${100 * index}%);background-image:url(${common.changeUrl(i.src)});`"
+                    class="image-item"
+                    v-for="(i, index) in imageList"
+                ></div>
                 <!-- <div v-else :style="`transform:translateX(${100 * index}%);`" class="image-item" v-for="(i, index) in imageList">
                     <img @error="filesError(index)" :src="common.changeUrl(i.src)" alt="" />
                 </div> -->
@@ -25,49 +30,62 @@
         </div>
         <div class="continue" v-if="(!isEdit && imageList.length > 1) || isEdit">
             <ui-input
-                v-if="imageList.length < custom[type].maxNum && isEdit"
+                v-if="imageList.length < customer[type].maxNum && isEdit"
                 type="file"
-                :placeholder="custom[type].uploadPlace"
-                :disable="custom[type].upload"
-                :scale="custom[type].scale"
-                :accept="custom[type].accept"
-                :multiple="custom[type].multiple"
-                :maxSize="custom[type].maxSize"
-                :maxLen="custom[type].maxNum"
-                :othPlaceholder="custom[type].othPlaceholder"
+                :placeholder="customer[type].uploadPlace"
+                :disable="customer[type].upload"
+                :scale="customer[type].scale"
+                :accept="customer[type].accept"
+                :multiple="customer[type].multiple"
+                :maxSize="customer[type].maxSize"
+                :maxLen="customer[type].maxNum"
+                :othPlaceholder="customer[type].othPlaceholder"
                 @update:modelValue="data => hanlderFiles(data)"
             >
                 <template v-slot:replace>
-                    <span class="continue-tips">继续添加</span>
-                    <span class="edit-pic-num">
-                        <span class="cur">{{ imageList.length }}</span>
-                        <span> / {{ custom[type].maxNum }}</span>
-                    </span>
+                    <span class="continue-tips">{{ $t('tag.toolbox.continueAdd') }}</span>
                 </template>
             </ui-input>
-            <!-- <span v-if="isEdit" class="pic-num">
+            <span v-if="isEdit" class="pic-num">
                 <span class="cur">{{ imageList.length }}</span>
-                <span> / {{ custom[type].maxNum }}</span>
-            </span> -->
-            <span v-if="!isEdit" class="pic-num">
+                <span> / {{ customer[type].maxNum }}</span>
+            </span>
+            <span v-else class="pic-num">
                 <span class="cur">{{ imageNum + 1 }}</span>
                 <span><span>&nbsp;</span>/<span>&nbsp;</span></span>
                 <span>{{ imageList.length }}</span>
             </span>
         </div>
+        <!-- 移动端缩放 -->
+        <!-- swiper新增后,此功能无用 -->
+        <!-- <teleport to="body">
+            <div class="showPicBox" v-if="zoomInImg">
+                <span class="close" @click="closePhoto">
+                    <ui-icon type="close"></ui-icon>
+                </span>
+                <ui-icon v-show="loading" class="loading-icon" type="_loading_"></ui-icon>
+                <div @click="closePhoto" class="imgbox" ref="topology" :style="`background-image:url(${zoomInImg});`"></div>
+            </div>
+        </teleport> -->
     </div>
 </template>
 
 <script setup>
-import { reactive, toRefs, onBeforeMount, onMounted, nextTick, ref, computed, defineProps } from 'vue'
+import { reactive, toRefs, onBeforeMount, onMounted, nextTick, ref, computed, defineProps, defineEmits } from 'vue'
 import { useStore } from 'vuex'
 import common from '@/utils/common'
 import { custom } from '../constant.js'
+const customer = custom()
 import { getApp, useApp } from '@/app'
-import { Dialog } from '@/global_components/'
+import { Dialog } from '@/global_components'
+import { useI18n } from '../../../i18n'
+const { t } = useI18n({ useScope: 'global' })
+// import { zoomElement } from './scale/index.js'
+// import Hammer from 'hammerjs' // 引用hammerjs
 const isMobile = ref(false)
 const store = useStore()
 const type = ref('image')
+const emit = defineEmits(['close'])
 const props = defineProps({
     metasHeight: {
         type: Number,
@@ -77,9 +95,14 @@ const props = defineProps({
         type: Boolean,
         default: false,
     },
+    scale: {
+        type: Boolean,
+        default: false,
+    },
 })
 const isEdit = computed(() => store.getters['tag/isEdit'])
 const hotData = computed(() => store.getters['tag/hotData'])
+const topology = ref(null)
 const imageList = computed(() => {
     return hotData.value.media.image
 })
@@ -116,21 +139,20 @@ const setImageList = data => {
         picLength = list.length
     }
     for (let i = 0; i < data.length; i++) {
-        if (list.length < custom['image'].maxNum) {
+        if (list.length < customer['image'].maxNum) {
             list.push('')
             var index = i + picLength
             list[index] = { src: URL.createObjectURL(data[i]), file: data[i] }
         } else {
             Dialog.toast({
                 type: 'error',
-                content: `${t('limit.maxLengthFile', { length: custom['image'].maxNum })}`,
+                content: `${t('limit.maxLengthFile', { length: customer['image'].maxNum })}`,
             })
             break
         }
     }
     store.commit('tag/setImageList', list)
 }
-
 onMounted(async () => {
     const app = await useApp()
     isMobile.value = app.config.mobile
@@ -141,13 +163,106 @@ onMounted(async () => {
             loading.value = false
         }
         img.src = common.changeUrl(imageList.value[0].src)
+        // if (imageList.value.length > 1) {
+        //     //监听移动端手势
+        //     if (props.scale) {
+        //         var el = document.getElementById('image-list')
+        //         // var hammer = new Hammer(square)
+        //         var mc = new Hammer.Manager(el)
+        //         mc.add(new Hammer.Pinch({ threshold: 0 }))
+        //         mc.on('pinchstart', ev => {
+        //             // 双指缩放
+        //             console.log('双指缩放')
+        //             openScale(imageList.value[imageNum.value].src)
+        //         })
+        //     }
+        // }
+        if (props.scale) {
+            if (imageList.value.length == 1) {
+                openScale(imageList.value[0].src)
+            }
+        }
     })
 })
 const filesError = index => {
     loading.value = false
 }
+const zoomInImg = ref(null)
+const closePhoto = () => {
+    if (imageList.value.length == 1) {
+        emit('close')
+    } else {
+        zoomInImg.value = null
+    }
+    // $('#tag-billboards').css({ 'z-index': '101', 'pointer-events': 'none' });
+}
+const openScale = src => {
+    if (isMobile.value) {
+        zoomInImg.value = common.changeUrl(src)
+
+        let img = new Image()
+        img.onload = () => {
+            loading.value = false
+        }
+        img.src = zoomInImg.value
+        // nextTick(() => {
+        //     zoomElement(topology.value)
+        // })
+    }
+}
 </script>
 <style lang="scss" scoped>
+.showPicBox {
+    width: 100%;
+    height: 100%;
+    position: fixed;
+    z-index: 10000;
+    background: rgb(24, 22, 22);
+    top: 0;
+    left: 0;
+    .close {
+        position: absolute;
+        top: 10px;
+        right: 10px;
+        width: 20px;
+        height: 20px;
+        z-index: 100;
+        color: #fff;
+        .iconfont {
+            font-size: 20px;
+        }
+    }
+    .loading {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+    }
+    .imgbox {
+        width: 100%;
+        height: 100%;
+        background-repeat: no-repeat;
+        background-size: contain;
+        background-position: center center;
+        #eleImg {
+            // position: absolute;
+
+            // top: 50%;
+            // left: 50%;
+            // transform: translate(-50%, -50%);
+            margin: 0 auto;
+            display: block;
+            &.s {
+                height: 100%;
+                width: auto;
+            }
+            &.h {
+                height: auto;
+                width: 100%;
+            }
+        }
+    }
+}
 .del-btn {
     width: 24px;
     height: 24px;
@@ -162,6 +277,15 @@ const filesError = index => {
     align-items: center;
     justify-content: center;
 }
+.loading-icon {
+    color: var(--editor-main-color);
+    animation: rotate 2s infinite linear;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+    font-size: 30px;
+}
 .pic-box {
     width: 100%;
     height: 100%;
@@ -171,15 +295,7 @@ const filesError = index => {
     top: 0;
     left: 0;
     z-index: 10;
-    .loading-icon {
-        color: var(--editor-main-color);
-        animation: rotate 2s infinite linear;
-        position: absolute;
-        top: 50%;
-        left: 50%;
-        transform: translate(-50%, -50%);
-        font-size: 30px;
-    }
+
     @keyframes rotate {
         0% {
             transform: translate(-50%, -50%) rotate(0deg);
@@ -207,15 +323,6 @@ const filesError = index => {
         }
         .continue-tips {
             font-size: 12px;
-            margin-right: 5px;
-        }
-        .edit-pic-num {
-            // position: absolute;
-            // right: 10px;
-            font-size: 12px;
-            .cur {
-                color: var(--editor-main-color);
-            }
         }
         .pic-num {
             position: absolute;

+ 5 - 5
packages/qjkankan-kankan-view/src/components/Tags/metas/metas-video.vue

@@ -31,7 +31,7 @@ import { useStore } from 'vuex'
 import { custom } from '../constant.js'
 import { getApp, useApp } from '@/app'
 import common from '@/utils/common'
-import { Dialog } from '@/global_components/'
+import { Dialog } from '@/global_components'
 const videoNum = ref(0)
 const store = useStore()
 const type = ref('video')
@@ -39,12 +39,12 @@ const hotData = computed(() => store.getters['tag/hotData'])
 const props = defineProps({
     controls: {
         type: Boolean,
-        default: true
+        default: true,
     },
     metasHeight: {
         type: Number,
-        default: null
-    }
+        default: null,
+    },
 })
 const loading = ref(true)
 
@@ -70,7 +70,7 @@ const filesError = file => {
 onMounted(() => {
     nextTick(() => {
         let myVideo = document.getElementById('video')
-        myVideo.oncanplay = function() {
+        myVideo.oncanplay = function () {
             loading.value = false
         }
     })

+ 1 - 1
packages/qjkankan-kankan-view/src/components/Tags/metas/metas-web.vue

@@ -22,7 +22,7 @@
 <script setup>
 import { reactive, toRefs, onBeforeMount, onMounted, ref, computed, defineProps } from 'vue'
 import { useStore } from 'vuex'
-import { Cropper, Loading, Dialog } from '@/global_components/'
+import { Cropper, Loading, Dialog } from '@/global_components'
 import { custom } from '../constant.js'
 const store = useStore()
 const linkNum = ref(0)

+ 145 - 0
packages/qjkankan-kankan-view/src/components/Tags/metas/scale/index.js

@@ -0,0 +1,145 @@
+import Hammer from 'hammerjs' // 引用hammerjs
+// 定义缩放方法,接收一个element参数:使用export暴露该方法
+export function zoomElement(el) {
+    function point2D(x, y) {
+        return { x: x, y: y }
+    }
+    // 判断 正数,负数,不是数字
+    function checkNumType(num) {
+        var reg = new RegExp('^-?[0-9]*.?[0-9]*$')
+        if (reg.test(num)) {
+            // 用于检测一个字符串是否匹配某个模式
+            var absVal = Math.abs(num) // 如果参数是非负数,则返回该参数;如果参数是负数,则返回该参数的相反数。
+            return num == absVal ? true : false
+        } else {
+            console.log('this is not number')
+        }
+    }
+    function exChangeNum(num, reNum) {
+        let flag = checkNumType(num)
+        let reFlag = checkNumType(reNum)
+        let realNum = 0
+        if (!flag && reFlag) {
+            realNum = Number('-' + reNum)
+        } else {
+            realNum = Number(reNum)
+        }
+        return realNum
+    }
+    var reqAnimationFrame = (function () {
+        return (
+            window[Hammer.prefixed(window, 'requestAnimationFrame')] ||
+            function (callback) {
+                window.setTimeout(callback, 1000 / 60)
+            }
+        )
+    })()
+    var ticking = false
+    var tMatrix = [1, 0, 0, 1, 0, 0] //x缩放,无,无,y缩放,x平移,y平移
+    var initScale = 1 //初始化scale
+    el.addEventListener('touchmove', function (e) {
+        e.preventDefault()
+    })
+    var mc = new Hammer.Manager(el)
+    var nowScale = 0
+    var poscenter = point2D(0, 0) // 缓存双指的中心坐标
+    var duration = '' // 设置过渡效果,用于双击缩放效果
+    var lastTranslate = point2D(0, 0) // 记录上次的偏移值
+    var lastcenter = point2D(el.offsetWidth / 2, el.offsetHeight / 2) // 图像的中心点,用于对比双指中心点
+    var center = lastcenter // 初始化为图片中心点
+    // 添加缩放事件
+    mc.add(new Hammer.Pan({ threshold: 0, pointers: 1 }))
+    mc.add(new Hammer.Pinch({ threshold: 0 }))
+    mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2 }))
+    mc.on('pinchstart', onPinchStart) // 双指缩放
+    mc.on('pinchmove', onPinch) // 双指移动
+    mc.on('panmove', onPan)
+    mc.on('panstart', onPanStart)
+    // 缩放开始
+    function onPinchStart(ev) {
+        duration = ''
+        lastTranslate = point2D(tMatrix[4], tMatrix[5]) //记录上一次的偏移值 0 0
+        initScale = tMatrix[0] || 1
+        // 手势中心点
+        poscenter = point2D(ev.center.x, ev.center.y)
+        // 图像中心点  = 初始化图像中心点  + 上一次偏移量的中心点
+        lastcenter = point2D(center.x + lastTranslate.x, center.y + lastTranslate.y) //重新计算放大后的中心坐标
+        // 手势中心点 = 缩放中心点 - 图像中心点
+        poscenter = point2D(ev.center.x - lastcenter.x, ev.center.y - lastcenter.y)
+        requestElementUpdate('onpinchStart')
+    }
+    // 缩放途中
+    function onPinch(ev) {
+        // 缩放倍数 这里的缩放倍数
+        nowScale = initScale * ev.scale
+        // 如果倍数小于1 则等于1
+        if (nowScale < 1) {
+            nowScale = 1
+        }
+        // 缩放倍数
+        tMatrix[0] = tMatrix[3] = nowScale
+        let x = Number((1 - ev.scale) * poscenter.x + lastTranslate.x)
+        let y = Number((1 - ev.scale) * poscenter.y + lastTranslate.y)
+        let tempPosX = el.getBoundingClientRect().width / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).x
+        let tempPosY = el.getBoundingClientRect().height / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).y
+        if (Math.abs(x) > Math.abs(tempPosX)) {
+            x = exChangeNum(x, tempPosX)
+        }
+
+        if (Math.abs(y) > Math.abs(tempPosY)) {
+            y = exChangeNum(y, tempPosY)
+        }
+        tMatrix[4] = x
+        tMatrix[5] = y
+        requestElementUpdate('onpinch')
+    }
+    // 开始拖动
+    function onPanStart() {
+        lastTranslate = point2D(tMatrix[4], tMatrix[5]) // 缓存上一次的偏移值
+    }
+    // 拖动过程
+    function onPan(ev) {
+        tMatrix[0] = tMatrix[3] = nowScale || initScale
+        // 拖动的动画 1.6
+        duration = '1.6'
+        let x = Number(lastTranslate.x + ev.deltaX)
+        let y = Number(lastTranslate.y + ev.deltaY)
+        let tempPosX = el.getBoundingClientRect().width / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).x
+        let tempPosY = el.getBoundingClientRect().height / 2 - point2D(el.offsetWidth / 2, el.offsetHeight / 2).y
+        if (Math.abs(x) > Math.abs(tempPosX)) {
+            x = exChangeNum(x, tempPosX)
+        }
+        if (Math.abs(y) > Math.abs(tempPosY)) {
+            y = exChangeNum(y, tempPosY)
+        }
+        tMatrix[4] = x
+        tMatrix[5] = y
+        requestElementUpdate('onpan')
+    }
+
+    // 每次都会·更新 因为是在移动端 所以都采用rem 否则可以直接用matrix
+    function updateElementTransform() {
+        el.style.transition = duration
+        let x = tMatrix[4] + 'px'
+        let y = tMatrix[5] + 'px'
+        el.style.transform = 'translate(' + x + ',' + y + ') ' + 'scale(' + tMatrix[0] + ',' + tMatrix[3] + ')'
+        el.style.WebkitTransform = 'translate(' + x + ',' + y + ') ' + 'scale(' + tMatrix[0] + ',' + tMatrix[3] + ')'
+        el.style.msTransform = 'translate(' + x + ',' + y + ') ' + 'scale(' + tMatrix[0] + ',' + tMatrix[3] + ')'
+        // var tmp = tMatrix.join(',')
+        // el.style.transform = 'matrix(' + tmp + ')'
+        // el.style.WebkitTransform = 'matrix(' + tmp + ')'
+        // el.style.msTransform = 'matrix(' + tmp + ')'
+        ticking = false
+    }
+    function requestElementUpdate() {
+        if (!ticking) {
+            reqAnimationFrame(updateElementTransform)
+            ticking = true
+        }
+    }
+    /**
+  初始化设置
+  */
+
+    requestElementUpdate()
+}

+ 8 - 10
packages/qjkankan-kankan-view/src/components/Tags/show-tag.vue

@@ -15,9 +15,9 @@
             <metasVideo v-if="hotData.type == 'video'" />
             <metasWeb v-if="hotData.type == 'link'" />
         </div>
-        <div class="edit-btn" v-if="routerName && routerName == 'tag' && !editModule">
+        <!-- <div class="edit-btn" v-if="routerName && routerName == 'tag' && !editModule">
             <span @click="edit()"><ui-icon type="edit"></ui-icon> 修改</span>
-        </div>
+        </div> -->
     </div>
 </template>
 
@@ -29,10 +29,8 @@ import metasAudio from './metas/metas-audio'
 import metasWeb from './metas/metas-web'
 import common from '@/utils/common'
 import { useStore } from 'vuex'
-// import { useRouter } from 'vue-router'
 import { useMusicPlayer } from '@/utils/sound'
 const musicPlayer = useMusicPlayer()
-// const router = useRouter()
 const editModule = computed(() => store.getters['editModule'])
 const store = useStore()
 const emit = defineEmits(['open'])
@@ -40,7 +38,6 @@ const hotData = computed(() => {
     let data = store.getters['tag/hotData']
     if (data.type == 'audio' || data.type == 'video') {
         musicPlayer.pause(true)
-        // console.log('pause(true)')
     }
     return data
 })
@@ -64,10 +61,10 @@ const open = () => {
         emit('open')
     }
 }
-const edit = () => {
-    store.commit('tag/edit')
-    store.commit('tag/gotoTag', hotData.value)
-}
+// const edit = () => {
+//     store.commit('tag/edit')
+//     store.commit('tag/gotoTag', hotData.value)
+// }
 onMounted(() => {})
 </script>
 <style lang="scss" scoped>
@@ -121,7 +118,7 @@ onMounted(() => {})
         h2 {
             font-size: 20px;
             // margin-bottom: 10px;
-            line-height: 20px;
+            line-height: 30px;
             color: #ffffff;
             position: relative;
             .ui-audio {
@@ -191,6 +188,7 @@ onMounted(() => {})
         .tag-title {
             h2 {
                 font-size: 0.5333rem;
+                line-height: 0.8rem;
                 color: #ffffff;
                 position: relative;
                 .ui-audio {

+ 0 - 332
packages/qjkankan-kankan-view/src/components/Tags/style-icon.vue

@@ -1,332 +0,0 @@
-<!--  -->
-<template>
-    <div class="style-icon">
-        <div class="style-list">
-            <div class="upload-btn" v-if="icons && icons.length < 19">
-                <ui-button class="add">
-                    <ui-input v-vip:vip="auth.isVip" v-vip:expired="auth.isExpired" class="input" preview accept=".jpg, .jpeg, .png" @update:modelValue="iconUpload" type="file">
-                        <template v-slot:replace>
-                            <ui-icon type="add" class="icon" />
-                        </template>
-                    </ui-input>
-                </ui-button>
-                <div class="vip-tag"></div>
-            </div>
-            <div class="style-item default" @click="changeLogo('')" :style="`background-image:url(${defaultLogo});`" :class="{ active: icon == '' }"></div>
-            <template v-for="(i, index) in showList">
-                <!-- <div class="style-item" @click="changeLogo(i.id, index)" v-if="index < 3" :style="`background:${i.name};`" :class="{ active: icon == i.id }"></div> -->
-                <div class="style-item" @click="changeLogo(i.name, i.sid)" v-if="index < 4" :style="`background-image:url(${common.changeUrl(i.name)});`" :class="{ active: iconId == i.sid }">
-                    <div class="close-btn" @click.stop="delIcon(i)">
-                        <ui-icon type="close"></ui-icon>
-                    </div>
-                </div>
-            </template>
-            <div class="more" v-if="icons && icons.length > 4">
-                <ui-button @click.stop="showMore = !showMore">
-                    <ui-icon :class="{ active: showMore }" type="pull-down"></ui-icon>
-                </ui-button>
-                <div class="tagLogo-box" :class="{ active: showMore }">
-                    <template v-for="(i, index) in hideList">
-                        <div @click="insertLogo(i)" class="tagLogo-item" :style="`background-image:url(${common.changeUrl(i.name)});`">
-                            <div class="close-btn">
-                                <ui-icon type="close" @click.stop="delIcon(i)"></ui-icon>
-                            </div>
-                        </div>
-                    </template>
-                </div>
-            </div>
-        </div>
-        <!-- <span class="more">更多></span> -->
-    </div>
-</template>
-
-<script setup>
-import { reactive, toRefs, onBeforeMount, onMounted, onUnmounted, ref, computed } from 'vue'
-import { Cropper, Loading, Dialog } from '@/global_components/'
-import common from '@/utils/common'
-import { useStore } from 'vuex'
-import { getApp } from '@/app'
-const store = useStore()
-const showMore = ref(false)
-const defaultLogo = ref('')
-defaultLogo.value = getApp().resource.getAppURL('images/tag_icon_default.svg')
-const chooseItem = ref(null)
-const hotData = computed(() => store.getters['tag/hotData'])
-const icons = computed(() => {
-    console.log(store.getters['tag/icons'])
-    return store.getters['tag/icons'] || []
-})
-const auth = computed(() => store.getters['scene/auth'])
-const iconId = computed(() => store.getters['tag/iconId'])
-const icon = computed(() => {
-    return hotData.value.icon
-})
-
-const showList = computed(() => {
-    for (let i = 0; i < icons.value.length; i++) {
-        if (icons.value[i].sid == iconId.value) {
-            chooseItem.value = icons.value[i]
-        }
-    }
-    const styles = icons.value.slice(0, icons.value.length > 4 ? (icons.value.length < 19 ? 3 : 4) : 4)
-    if (chooseItem.value && !styles.includes(chooseItem.value)) {
-        let index = icons.value.length < 19 ? 2 : 3
-        styles[index] = chooseItem.value
-    }
-    return styles
-})
-const hideList = computed(() => {
-    let res = icons.value.filter(style => {
-        return !showList.value.includes(style)
-    })
-    return res
-})
-
-// let fristIndex = null
-const iconUpload = item => {
-    let sid = common.getRandomSid()
-    let src = URL.createObjectURL(item.file)
-    let pramas = { img: src, fixedNumber: [1, 1] }
-    let suffix = item.file.type.split('/')[1]
-    let fileName = sid + '.' + suffix
-    Cropper.open(pramas).then(res => {
-        if (res) {
-            let data = {
-                sid: sid,
-                name: res[1],
-                fileName: fileName,
-            }
-            store.commit('tag/pushIcon', { ...data })
-            store.commit('tag/changeIcon', { ...data })
-        }
-    })
-}
-const changeLogo = (name, sid) => {
-    store.commit('tag/changeIcon', { name: name, sid: sid })
-    showMore.value = false
-}
-const insertLogo = item => {
-    chooseItem.value = item
-    store.commit('tag/changeIcon', item)
-    showMore.value = false
-}
-const delIcon = item => {
-    chooseItem.value = null
-    store.commit('tag/deleteIcon', item)
-    if (item.sid == iconId.value) {
-        store.commit('tag/changeIcon', { name: '', sid: '' })
-    }
-}
-const closeMore = () => {
-    showMore.value = false
-}
-onMounted(() => {
-    window.addEventListener('click', closeMore, false)
-})
-onUnmounted(() => {
-    window.removeEventListener('click', closeMore, false)
-})
-</script>
-<style lang="scss" scoped>
-.style-icon {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    margin: 0 0 24px;
-    // .more {
-    //     color: var(--editor-main-color);
-    //     cursor: pointer;
-    // }
-    .style-list {
-        display: flex;
-        align-items: center;
-        justify-content: flex-start;
-        > div {
-            margin-right: 20px;
-            &:last-of-type {
-                margin-right: 0;
-            }
-        }
-        .upload-btn {
-            position: relative;
-            cursor: pointer;
-            .ui-input {
-                position: relative;
-                z-index: 11;
-            }
-        }
-
-        .add {
-            width: 40px;
-            height: 40px;
-            border-radius: 0;
-            cursor: pointer;
-            // margin-right: 20px;
-            border: 1px solid #fde1b0;
-            color: #fde1b0;
-            position: relative;
-            border-radius: 4px;
-            transition: none;
-        }
-        .style-item {
-            width: 40px;
-            height: 40px;
-            box-sizing: border-box;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            cursor: pointer;
-            // background: #f2f2f2;
-            background-repeat: no-repeat;
-            background-size: cover;
-            position: relative;
-            border-radius: 4px;
-            border: 1px solid transparent;
-            &.default {
-            }
-            &.active {
-                border: 1px solid var(--editor-main-color);
-            }
-            .close-btn {
-                width: 16px;
-                height: 16px;
-                border-radius: 50%;
-                position: absolute;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                background: rgba(250, 63, 72, 1);
-                opacity: 0.6;
-                right: -6px;
-                top: -6px;
-                z-index: 101;
-                display: none;
-                &:hover {
-                    opacity: 1;
-                }
-                > i {
-                    font-size: 12px;
-                    color: #fff;
-                    transform: scale(0.8);
-                }
-            }
-            &:hover {
-                .close-btn {
-                    display: flex;
-                }
-            }
-        }
-        .more {
-            width: 40px;
-            height: 40px;
-            box-sizing: border-box;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            cursor: pointer;
-            // border-radius: 4px;
-            // border: 1px solid rgba(255, 255, 255, 0.2);
-            box-sizing: border-box;
-            position: relative;
-            z-index: 100;
-            button {
-                width: 100%;
-                height: 100%;
-                position: relative;
-                .iconfont {
-                    transition: all 0.3s;
-                    position: absolute;
-                    margin-top: -7px;
-                    margin-left: -7px;
-
-                    &.active {
-                        transform: rotate(180deg);
-                    }
-                }
-            }
-            .tagLogo-box {
-                position: absolute;
-                width: 380px;
-                // height: 200px;
-                background: rgba(27, 27, 28, 0.9);
-                box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
-                border: 1px solid #000000;
-                backdrop-filter: blur(4px);
-                z-index: 10;
-                right: -20px;
-                top: 100%;
-                margin-top: 12px;
-                display: flex;
-                flex-wrap: wrap;
-                align-items: center;
-                justify-content: flex-start;
-                padding: 0 18px 20px 18px;
-                transform: scale(0);
-                transform-origin: 90% top;
-                transition: all 0.3s;
-                &.active {
-                    transform: scale(1);
-                    transform-origin: 90% top;
-                }
-                &::after {
-                    position: absolute;
-                    content: '';
-                    right: 32px;
-                    top: -10px;
-                    width: 0;
-                    height: 0;
-                    border-left: 6px solid transparent;
-                    border-right: 6px solid transparent;
-                    border-bottom: 10px solid rgba(27, 27, 28, 0.8);
-                }
-                .tagLogo-item {
-                    width: 40px;
-                    height: 40px;
-                    border-radius: 4px;
-                    background: #fff;
-                    margin-right: 20px;
-                    margin-top: 20px;
-                    position: relative;
-                    border: 1px solid transparent;
-                    background-size: cover;
-
-                    &.active {
-                        border: 1px solid var(--editor-main-color);
-                    }
-                    &:nth-of-type(6n) {
-                        margin-right: 0;
-                    }
-                    .close-btn {
-                        width: 16px;
-                        height: 16px;
-                        border-radius: 50%;
-                        position: absolute;
-                        display: flex;
-                        align-items: center;
-                        justify-content: center;
-                        background: rgba(250, 63, 72, 1);
-                        opacity: 0.6;
-                        right: -6px;
-                        top: -6px;
-                        z-index: 101;
-                        display: none;
-                        &:hover {
-                            opacity: 1;
-                        }
-                        > i {
-                            font-size: 12px;
-                            color: #fff;
-                            transform: scale(0.8);
-                        }
-                    }
-                    &:hover {
-                        .close-btn {
-                            display: flex;
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-</style>

+ 0 - 230
packages/qjkankan-kankan-view/src/components/Tags/tag-info.vue

@@ -1,230 +0,0 @@
-<!--  -->
-<template>
-    <div class="hot-editor" :id="`tagBox_${hotData.sid}`">
-        <div class="header">
-            <div class="header-title">{{ $t('tag.toolbox.hotspot') }}</div>
-            <!-- <ui-icon class="close" type="close"></ui-icon> -->
-        </div>
-        <div class="hot-content">
-            <StyleIcon />
-            <ui-input
-                require
-                class="input"
-                width="100%"
-                :placeholder="$t('tag.toolbox.hotspotTitleTips')"
-                type="text"
-                :modelValue="title"
-                @update:modelValue="value => (title = value)"
-                maxlength="30"
-            />
-
-            <div class="desc-box" :class="{ border: showBorder }">
-                <div class="edit-box">
-                   
-                </div>
-                <div class="desc-link">
-                    <!-- <LinkManage :show="!!(inInsertLink && maxTextLen)" :textlen="maxTextLen" @close="inInsertLink = false" @add="insertel" /> -->
-                    <LinkManage v-if="showLink" @close="closeLink" @confirm="insertText" />
-                    <ui-icon type="link" class="icon" @click="showLink = true" />
-
-                    <span>
-                        <span class="theme-color">{{ descriptionLength }}</span>
-                        /
-                        <span>{{ descriptionMax }}</span>
-                    </span>
-                </div>
-            </div>
-
-            <div class="tag-metas">
-                <MetasUpload :type="info.type" />
-            </div>
-            <div class="submit-ctrl">
-                <div class="radio-group">
-                    <ui-input
-                        v-for="(item, type) in custom"
-                        :key="type"
-                        class="radio"
-                        type="radio"
-                        :modelValue="info.type === type"
-                        @update:modelValue="changeType(type)"
-                        :tip="item.name"
-                        :icon="item.icon"
-                    />
-                </div>
-            </div>
-        </div>
-    </div>
-</template>
-
-<script setup>
-import { reactive, toRefs, ref, onBeforeMount, onMounted, defineProps, computed, nextTick } from 'vue'
-import { useStore } from 'vuex'
-const store = useStore()
-import MetasUpload from './metas-upload.vue'
-import StyleIcon from './style-icon.vue'
-import LinkManage from './link-manage.vue'
-import { custom } from './constant.js'
-
-const editor$ = ref(null)
-const descriptionMax = 200
-const descriptionLength = ref(0)
-const showLink = ref(false)
-const hotData = computed(() => store.getters['tag/hotData'])
-const info = computed(() => {
-    let data = {
-        type: hotData.value.type || 'image',
-    }
-    return data
-})
-const title = computed({
-    get() {
-        if (hotData.value.title && hotData.value.title != void 0) {
-            return hotData.value.title
-        }
-        return hotData.value.title || ''
-    },
-    set(value) {
-        store.commit('tag/setTitle', value)
-    },
-})
-const content = computed({
-    get() {
-        if (editor$.value) {
-            descriptionLength.value = editor$.value.getLength()
-            if (hotData.value.content && hotData.value.content != void 0) {
-                return hotData.value.content
-            } else {
-                editor$.value.setHtml(hotData.value.content)
-            }
-        }
-        return hotData.value.content || ''
-    },
-    set(value) {
-        // console.log(value)
-        store.commit('tag/setContent', { value })
-    },
-})
-
-const closeLink = () => {
-    showLink.value = false
-}
-const insertText = data => {
-    editor$.value.insertLink(data.text.value, data.link.value)
-    nextTick(() => {
-        store.commit('tag/update', { content: editor$.value.getHtml() })
-    })
-    closeLink()
-}
-const onDescriptionChange = ({ length, html, init }) => {
-    // // alert(1)
-    // console.log(length, html, init)
-    // if (init) {
-    //     return (descriptionLength.value = length)
-    // }
-
-    content.value = html
-    descriptionLength.value = length
-}
-const showBorder = ref(false)
-const onEditDescription = () => {
-    showBorder.value = false
-}
-
-const changeType = type => {
-    console.log(type)
-    info.value.type = type
-    store.commit('tag/setMetaType', type)
-}
-const maxContentLen = ref(10)
-</script>
-<style lang="scss" scoped>
-.hot-editor {
-    background: rgba(27, 27, 28, 0.8);
-    border-radius: 4px;
-    pointer-events: auto;
-    backdrop-filter: blur(4px);
-    // min-width: 400px;
-    .hot-content {
-        width: 100%;
-        padding: 30px 20px;
-        .submit-ctrl {
-            margin-top: 20px;
-            display: flex;
-
-            .radio-group {
-                flex: 1;
-                display: inline-flex;
-
-                > .radio {
-                    margin-right: 22px;
-                }
-            }
-
-            .submit {
-                flex: none;
-                cursor: pointer;
-            }
-        }
-        .desc-box {
-            width: 100%;
-            height: 158px;
-            background: rgba(255, 255, 255, 0.1);
-            border-radius: 4px;
-            border: 1px solid rgba(255, 255, 255, 0.2);
-            margin-bottom: 10px;
-            &.border {
-                border: 1px solid var(--editor-main-color);
-            }
-            .edit-box {
-                height: 128px;
-                padding: 10px;
-                box-sizing: border-box;
-            }
-        }
-        .tag-metas {
-            width: 100%;
-            height: 225px;
-            background: rgba(255, 255, 255, 0.1);
-            border-radius: 4px;
-            overflow: hidden;
-        }
-        .desc-link {
-            position: relative;
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            background: rgba(255, 255, 255, 0.1);
-            border-radius: 0px 0px 4px 4px;
-            height: 30px;
-            padding: 0 10px;
-            .iconfont {
-                font-size: 16px;
-                cursor: pointer;
-            }
-            span {
-                font-size: 12px;
-            }
-        }
-        .input {
-            margin-bottom: 10px;
-        }
-    }
-    .header {
-        height: 60px;
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        padding: 0 20px;
-        box-sizing: border-box;
-        color: #999;
-        border-bottom: 1px solid rgba(255, 255, 255, 0.16);
-        .header-title {
-            font-size: 16px;
-            font-weight: bold;
-        }
-        .close {
-            cursor: pointer;
-        }
-    }
-}
-</style>

+ 20 - 7
packages/qjkankan-kankan-view/src/components/Tags/tag-view.vue

@@ -1,11 +1,12 @@
 <!--  -->
 <template>
     <teleport to="body">
-        <div class="tag-layer" @click.stop="" :class="{ mobile: isMobile }">
+        <div class="tag-layer" @click.stop="" :class="{ mobile: isMobile, full: hotData.type == 'image' }">
             <div class="tag-info" @click.stop="" id="tag-info">
                 <ui-icon class="close-btn" @click.stop="close" type="close"></ui-icon>
                 <div class="tag-metas" v-if="hotData.media[hotData.type].length > 0 && hotData.type != 'audio'">
-                    <metasImage :viewer="true" v-if="hotData.type == 'image'" />
+                    <metasImage @close="close" :scale="true" :viewer="true" v-if="hotData.type == 'image' && !isMobile" />
+                    <imageView v-if="hotData.type == 'image' && isMobile"></imageView>
                     <metasWeb v-if="hotData.type == 'link'" />
                 </div>
             </div>
@@ -15,10 +16,10 @@
 
 <script setup>
 import { reactive, defineEmits, onBeforeMount, onMounted, ref, watchEffect, computed, watch, nextTick } from 'vue'
-import { Dialog } from '@/global_components/'
+import { Dialog } from '@/global_components'
 import metasImage from './metas/metas-image'
-// import metasVideo from './metas/metas-video'
-// import metasAudio from './metas/metas-audio'
+import imageView from './metas/image-view'
+
 import metasWeb from './metas/metas-web'
 import common from '@/utils/common'
 import { useStore } from 'vuex'
@@ -28,7 +29,6 @@ const metasHeight = ref(0)
 onMounted(async () => {
     const app = await useApp()
     isMobile.value = app.config.mobile
-
     nextTick(() => {
         let Layer = document.getElementById('tag-info')
         let layerHeight = Layer.getBoundingClientRect().height
@@ -127,7 +127,6 @@ onMounted(() => {})
 [is-mobile] {
     .tag-layer {
         .tag-info {
-            // padding: 20px;
             .close-btn {
                 position: absolute;
                 right: 20px;
@@ -136,6 +135,20 @@ onMounted(() => {})
                 cursor: pointer;
             }
         }
+        &.full {
+            background-color: #141414;
+            .tag-info {
+                height: 100%;
+                top: 0;
+                .close-btn {
+                    position: absolute;
+                    right: 20px;
+                    top: 20px;
+                    font-size: 18px;
+                    cursor: pointer;
+                }
+            }
+        }
     }
 }
 </style>

+ 0 - 102
packages/qjkankan-kankan-view/src/components/Tags/treasure.vue

@@ -1,102 +0,0 @@
-<template>
-  <transition mode="out-in">
-    <div class="treasure" v-if="tagclick.type == 'treasure'">
-      <div class="treasurecon">
-        <p>恭喜您,找到寶藏!</p>
-        <img :src="require('@/assets/images/icon/gifts_on.png')" alt="" />
-        <div @click.stop="goto_now" class="btn">立即前往</div>
-      </div>
-      <ui-icon class="close" @click.stop="emit('close')" type="state_f"></ui-icon>
-
-    </div>
-  </transition>
-</template>
-
-<script setup>
-import { onMounted, watch, defineEmits, computed, ref, nextTick, defineProps } from "vue";
-import { useApp, getApp } from "@/app";
-import { useStore } from "vuex";
-import browser from "@/utils/browser";
-
-const store = useStore();
-
-const tagclick = computed(() => store.getters["tag/tagClickType"]);
-
-const emit = defineEmits(["close"]);
-
-const goto_now = () => {
-
-  let tag = {};
-
-  try {
-    tag = JSON.parse(tagclick.value.data.hotContent);
-    browser.openLink(
-      "/subPackage/pages/activity/activity?pageId=" + tag.couponLink,
-      `https://m.cdfmembers.com/shop/600667208/showactivity?pageId=${tag.couponLink}`,
-      `/pages/showactivity/main?pageId=${tag.couponLink}`
-    );
-    emit("close");
-  } catch (error) {
-    console.log(error);
-  }
-};
-</script>
-
-<style lang="scss" scoped>
-.treasure {
-  position: fixed;
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  margin: 0 auto;
-  max-width: unset;
-  z-index: 101;
-  background: rgba(0, 0, 0, 0.5);
-  display: flex;
-  align-items: center;
-  flex-direction: column;
-  justify-content: center;
-  .treasurecon {
-    text-align: center;
-    width: 90%;
-    max-width: 500px;
-    p {
-      height: 33px;
-      font-size: 24px;
-      font-weight: 400;
-      color: #ffd980;
-      line-height: 33px;
-      text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
-    }
-    > img {
-      width: 100%;
-    }
-
-    .btn {
-      max-width: 122px;
-      margin: 0 auto;
-      height: 32px;
-      line-height: 32px;
-      color: #ed5d18;
-      background: linear-gradient(180deg, #fbecc7 0%, #fff8e8 6%, #f8e0b4 15%, #f1c387 52%, #fad78c 87%, #f8e2ad 94%, #fdde8e 100%);
-      border-radius: 16px;
-      font-size: 16px;
-      font-weight: bold;
-      position: relative;
-      top: -32px;
-      z-index: 99;
-    }
-  }
-
-  .close{
-    position: absolute;
-    right: 30px;
-    font-size: 20px;
-    top: 50px;
-    color: #000;
-  }
-}
-</style>

+ 0 - 116
packages/qjkankan-kankan-view/src/components/Tags/waterfall.vue

@@ -1,116 +0,0 @@
-<template>
-  <transition mode="out-in">
-    <div class="waterfall" v-if="tagclick.type == 'waterfall'">
-      <div class="waterfallcon">
-        <div class="wfheader">
-          <img :src="require('@/assets/images/icon/top5.png')" alt="" />
-          <ui-icon @click="emit('close')" type="close"></ui-icon>
-        </div>
-        <ul class="wfcon">
-          <li @click.stop="gotoGoods(item)" v-for="(item, i) in tagclick.data.products" :key="i">
-            <img v-if="i <= 2" :src="require(`@/assets/images/icon/${i + 1}.svg`)" alt="" />
-            <span v-else>{{ i + 1 }}</span>
-            <div class="wfavatar" :style="{ backgroundImage: `url(${item.pic})` }"></div>
-            <div class="wfinfo">
-              <p>{{ item.name }}</p>
-              <p>{{ item.symbol }} {{ item.price }} | 查看 ></p>
-            </div>
-          </li>
-        </ul>
-      </div>
-    </div>
-  </transition>
-</template>
-
-<script setup>
-import { onMounted, watch, defineEmits, computed, ref, nextTick, defineProps } from "vue";
-import { useApp, getApp } from "@/app";
-import { useStore } from "vuex";
-import browser from "@/utils/browser";
-import * as apis from "@/apis/index.js";
-
-const store = useStore();
-
-const tagclick = computed(() => store.getters["tag/tagClickType"]);
-
-const emit = defineEmits(["close"]);
-const gotoGoods = (item) => {
-  apis.burying_point({type:3});
-  browser.openLink(`/pages/item/item?productId=${item.id}`, `https://m.cdfmembers.com/shop/600667208/item?productId=${item.id}`);
-};
-</script>
-
-<style lang="scss" scoped>
-.waterfall {
-  position: fixed;
-  width: 100%;
-  height: 100%;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  margin: 0 auto;
-  max-width: 500px;
-  z-index: 101;
-  display: flex;
-  align-items: center;
-  flex-direction: column;
-  justify-content: flex-start;
-  pointer-events: none;
-  .waterfallcon {
-    text-align: center;
-    pointer-events: auto;
-    width: 90%;
-    padding: 10px 20px;
-    margin-top: 20%;
-    background: rgba(0, 0, 0, 0.6);
-    border-radius: 2px;
-    .wfheader {
-      display: flex;
-      justify-content: space-between;
-      width: 100%;
-      align-items: center;
-      > img {
-        width: 80px;
-      }
-    }
-    .wfcon {
-      color: #fff;
-      width: 100%;
-      padding-left: 10%;
-      max-height: 35vh;
-      overflow-y: auto;
-      > li {
-        display: flex;
-        align-items: center;
-        margin: 16px 0;
-        > img,
-        > span {
-          display: inline-block;
-          width: 20px;
-        }
-        .wfavatar {
-          width: 36px;
-          height: 36px;
-          background-size: cover;
-          margin: 0 10px;
-          background-color: #fff;
-          border-radius: 4px;
-          flex-shrink: 0;
-        }
-        .wfinfo {
-          text-align: left;
-          > p {
-            font-size: 16px;
-            &:last-of-type {
-              color: rgba(255, 255, 255, 0.8);
-              font-size: 12px;
-              margin-top: 6px;
-            }
-          }
-        }
-      }
-    }
-  }
-}
-</style>

+ 168 - 0
packages/qjkankan-kankan-view/src/components/shared/Checkbrowser.vue

@@ -0,0 +1,168 @@
+<!--  -->
+<template>
+    <div class="check-browser" :class="{ mobile: isMobile }">
+        <div class="pic"></div>
+        <p class="tips">{{ $t('toast.checkBrowser') }}</p>
+        <p class="center-tips">{{ $t('toast.changeBrowser') }}</p>
+        <div class="browser-list">
+            <div class="browser-item" v-for="i in list">
+                <div class="browser-pic" :class="i"></div>
+                <span class="borwser-name">{{ i }}</span>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref, toRefs, onBeforeMount, onMounted, computed } from 'vue'
+import browser from '@/utils/browser'
+const isMobile = computed(() => browser.isMobile)
+const list = ref(['Firefox', 'Edge', 'Safari', 'Chrome'])
+
+onBeforeMount(() => {})
+onMounted(() => {})
+</script>
+<style lang="scss" scoped>
+.check-browser {
+    width: 100vw;
+    height: 100vh;
+    background: #f7f7f7;
+    overflow: hidden;
+    .pic {
+        width: 240px;
+        height: 240px;
+        background: url('~@/assets/images/browser/pic_update.png') no-repeat;
+        background-size: 100% 100%;
+        margin: 120px auto 30px;
+    }
+    .tips {
+        font-size: 24px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #646566;
+        line-height: 33px;
+        text-align: center;
+    }
+    .center-tips {
+        font-size: 16px;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #909090;
+        line-height: 32px;
+        text-align: center;
+        margin: 10px auto 30px;
+    }
+    .browser-list {
+        width: 100%;
+        height: auto;
+        font-size: 16px;
+        font-weight: 400;
+        color: #909090;
+        line-height: 32px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .browser-item {
+            width: 80px;
+            margin-right: 100px;
+            margin-bottom: 10px;
+            &:last-of-type {
+                margin-right: 0;
+            }
+            .browser-pic {
+                width: 80px;
+                height: 80px;
+                background-size: 100% 100%;
+                background-repeat: no-repeat;
+                &.Firefox {
+                    background-image: url('~@/assets/images/browser/browser_Firefox.png');
+                }
+                &.Edge {
+                    background-image: url('~@/assets/images/browser/browser_Edge.png');
+                }
+                &.Safari {
+                    background-image: url('~@/assets/images/browser/browser_Safari.png');
+                }
+                &.Chrome {
+                    background-image: url('~@/assets/images/browser/browser_Chrome.png');
+                }
+            }
+            .borwser-name {
+                display: block;
+                width: 100%;
+                font-size: 16px;
+                text-align: center;
+            }
+        }
+    }
+}
+.mobile {
+    .pic {
+        width: 3.2rem;
+        height: 3.2rem;
+        background: url('~@/assets/images/browser/pic_update.png') no-repeat;
+        background-size: 100% 100%;
+        margin: 5.2rem auto 0.4rem;
+    }
+    .tips {
+        font-size: 0.32rem;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #646566;
+        line-height: 0.44rem;
+        text-align: center;
+    }
+    .center-tips {
+        font-size: 0.2133rem;
+        font-family: PingFangSC-Regular, PingFang SC;
+        font-weight: 400;
+        color: #909090;
+        line-height: 0.4267rem;
+        text-align: center;
+        margin: 10px auto 0.4rem;
+    }
+    .browser-list {
+        width: 100%;
+        height: auto;
+        font-size: 16px;
+        font-weight: 400;
+        color: #909090;
+        line-height: 0.4267rem;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .browser-item {
+            width: 1.0667rem;
+            margin-right: 1.3333rem;
+            margin-bottom: 0.1333rem;
+            &:last-of-type {
+                margin-right: 0;
+            }
+            .browser-pic {
+                width: 1.0667rem;
+                height: 1.0667rem;
+                background-size: 100% 100%;
+                background-repeat: no-repeat;
+                &.Firefox {
+                    background-image: url('~@/assets/images/browser/browser_Firefox.png');
+                }
+                &.Edge {
+                    background-image: url('~@/assets/images/browser/browser_Edge.png');
+                }
+                &.Safari {
+                    background-image: url('~@/assets/images/browser/browser_Safari.png');
+                }
+                &.Chrome {
+                    background-image: url('~@/assets/images/browser/browser_Chrome.png');
+                }
+            }
+            .borwser-name {
+                display: block;
+                width: 100%;
+                text-align: center;
+                font-size: 0.2133rem;
+            }
+        }
+    }
+}
+</style>

+ 1 - 1
packages/qjkankan-kankan-view/src/i18n/index.js

@@ -1,5 +1,5 @@
 import { nextTick } from 'vue'
-import { useI18n, createI18n } from 'vue-i18n/index'
+import { useI18n, createI18n } from 'vue-i18n'
 import browser from '@/utils/browser'
 
 export { useI18n }

+ 0 - 13
packages/qjkankan-kankan-view/src/main.js

@@ -1,13 +0,0 @@
-import "@/assets/theme.editor.scss";
-import ClickOutSide from "./utils/fns/ClickOutSide";
-import Components from "@/global_components";
-import { createApp } from "vue";
-import store from "./store";
-import App from "./app.vue";
-
-const app = createApp(App);
-// set i18n language
-app.use(store);
-app.use(Components);
-app.directive("click-outside", ClickOutSide);
-app.mount("#app");

+ 15 - 0
packages/qjkankan-kankan-view/src/pages/DesignOption/index.vue

@@ -0,0 +1,15 @@
+<!--  -->
+<template>
+    <div class="widgets-design-option">
+        <div class="delete-ruler">
+            <li>{{ $t('common.deleteRuleLine') }}</li>
+        </div>
+    </div>
+</template>
+<style lang="scss">
+.delete-ruler {
+    li {
+        white-space: nowrap;
+    }
+}
+</style>

+ 51 - 14
packages/qjkankan-kankan-view/src/pages/SPG.vue

@@ -3,35 +3,59 @@
     <LoadingLogo :thumb="true" />
     <div class="ui-view-layout" :class="{ show: show }">
         <div class="scene" ref="scene$"></div>
-        <UiTags />
-        <Information />
-        <BottomControl />
+        <!-- <template v-show="sceneUi"> -->
+        <div>
+            <UiTags />
+            <Information />
+            <BottomControl />
+        </div>
+        <!-- </template> -->
     </div>
+    <DesignOption />
 </template>
 
 <script setup>
 import { useMusicPlayer } from '@/utils/sound'
 const musicPlayer = useMusicPlayer()
-// import UiTags from '@/components/Tags'
 import UiTags from '@/components/Tags'
+import DesignOption from './DesignOption'
 import Information from '@/components/Information'
+
 import BottomControl from '@/components/Controls/BottomControl'
 import Password from '@/components/shared/Password.vue'
 import LoadingLogo from '@/components/shared/Loading.vue'
 import { createApp } from '@/app'
-import { ref, onMounted } from 'vue'
+import { listenMessage } from '@/utils/messageHandler'
+
+
+import { ref, onMounted, computed } from 'vue'
 import { useStore } from 'vuex'
 import { useApp, getApp } from '@/app'
 import browser from '@/utils/browser'
+import { useI18n, getLocale } from '@/i18n'
+const { t } = useI18n({ useScope: 'global' })
+
+
 
 const store = useStore()
 const show = ref(false)
 const scene$ = ref(null)
 
+const sceneUI = computed(() => store.getters['sceneUI'])
+
+listenMessage()
+
 onMounted(() => {
     const app = createApp({
         num: browser.getURLParam('m'),
         dom: scene$.value,
+        lang: getLocale(),
+        langs: {
+            en: {
+                'model.enter': t('model.enter'),
+            },
+        },
+        useShortcutKeys: true,
     })
     app.use('MinMap')
     app.use('Tag')
@@ -97,17 +121,30 @@ onMounted(() => {
     })
     app.store.on('tour', async tour => {
         app.TourManager.load(tour)
+        let tours = JSON.parse(
+            JSON.stringify(app.TourManager.tours, (key, val) => {
+                if (key === 'audio') {
+                    return null
+                } else {
+                    return val
+                }
+            })
+        )
         store.commit('tour/setData', {
-            tours: JSON.parse(
-                JSON.stringify(app.TourManager.tours, (key, val) => {
-                    if (key === 'audio') {
-                        return null
-                    } else {
-                        return val
-                    }
-                })
-            ),
+            tours: tours,
         })
+
+        window.parent.postMessage(
+            {
+                source: "qjkankan",
+                event: "toursList",
+                params: {
+                    tours,
+                },
+            },
+            "*"
+        );
+
         store.commit('tour/setBackUp', {
             tours: JSON.parse(
                 JSON.stringify(app.TourManager.tours, (key, val) => {

+ 47 - 10
packages/qjkankan-kankan-view/src/pages/spg.js

@@ -1,13 +1,50 @@
 import "@/assets/theme.editor.scss";
 import ClickOutSide from "@/utils/fns/ClickOutSide";
+import browser from '../utils/browser'
 import Components from "@/global_components";
-import { createApp } from "vue";
-import store from "@/store";
-import App from "./SPG.vue";;
-
-const app = createApp(App);
-// set i18n language
-app.use(store);
-app.use(Components);
-app.directive("click-outside", ClickOutSide);
-app.mount("#app");
+import Delegate from '../utils/fns/Delegate'
+import { getApp } from '../app'
+import { createApp } from 'vue'
+import store from '../store'
+import Spg from './SPG.vue'
+import Checkbrowser from '../components/shared/Checkbrowser.vue'
+import i18n, { getLocale, setI18nLanguage, loadLocaleMessages } from '../i18n'
+import { IsApp } from '@/utils/platform'
+let App
+if (browser.detectChrome() || browser.detectSafari() || browser.detectFirefox() || browser.detectEdge() || browser.detectWeixin() || browser.detectWeixinMiniProgram() || browser.detectAlipay()) {
+    App = Spg
+} else {
+    if (IsApp) {
+        App = SMG
+    } else {
+        App = Checkbrowser
+    }
+}
+
+const local = getLocale()
+loadLocaleMessages(i18n, local).then(() => {
+    setI18nLanguage(i18n, local)
+
+    const app = (window.__app = createApp(App))
+    app.use(i18n)
+    app.use(store)
+    app.use(Components)
+    app.directive('click-outside', ClickOutSide)
+    app.mount('#app')
+    const handleUserInputFocus = () => {
+        setTimeout(() => {
+            getApp().config.useShortcutKeys = false
+        }, 200)
+    }
+
+    const handleUserInputBlur = () => {
+        setTimeout(() => {
+            getApp().config.useShortcutKeys = true
+        }, 200)
+    }
+
+    Delegate(document, 'focus', 'input', () => handleUserInputFocus())
+    Delegate(document, 'focus', '[contenteditable]', () => handleUserInputFocus())
+    Delegate(document, 'blur', 'input', () => handleUserInputBlur())
+    Delegate(document, 'blur', '[contenteditable]', () => handleUserInputBlur())
+})

+ 26 - 3
packages/qjkankan-kankan-view/src/store/index.js

@@ -7,6 +7,7 @@ const store = createStore({
             mode: 'panorama',
             flying: false,
             floorId: null,
+            sceneUI: true,
             player: {
                 lang: 'zh',
                 showVR: false,
@@ -23,6 +24,7 @@ const store = createStore({
         }
     },
     getters: {
+        sceneUI: state => state.sceneUI,
         router: state => state.router,
         mode: state => state.mode,
         player: state => state.player,
@@ -38,6 +40,16 @@ const store = createStore({
          */
         mode(state, payload) {
             state.mode = payload
+            window.parent.postMessage(
+                {
+                    source: "qjkankan",
+                    event: "setMode",
+                    params: {
+                        mode: payload,
+                    },
+                },
+                "*"
+            );
         },
         /**
          * 设置相机模式
@@ -48,14 +60,15 @@ const store = createStore({
             if (payload == state.mode) {
                 return
             }
-            state.flying = true
+            store.commit('setFlying', true)
+
             useApp().then(sdk => {
                 sdk.Camera[payload]()
                     .then(() => {
-                        state.flying = false
+                        store.commit('setFlying', false)
                     })
                     .catch(() => {
-                        state.flying = false
+                        store.commit('setFlying', false)
                     })
             })
 
@@ -67,6 +80,16 @@ const store = createStore({
         },
         setFlying(state, payload) {
             state.flying = payload
+            window.parent.postMessage(
+                {
+                    source: "qjkankan",
+                    event: "isFlying",
+                    params: {
+                        isFlying: payload,
+                    },
+                },
+                "*"
+            );
         },
         SetPlayerOptions(state, payload) {
             for (let key in payload) {

+ 12 - 0
packages/qjkankan-kankan-view/src/utils/fns/Delegate.js

@@ -0,0 +1,12 @@
+export default function Delegate(delegateNode, eventType, selector, listener) {
+    delegateNode.addEventListener(
+        eventType,
+        function (event) {
+            var match = event.target.closest(selector)
+            if (match) {
+                listener.call(match, event)
+            }
+        },
+        true
+    )
+}

+ 53 - 0
packages/qjkankan-kankan-view/src/utils/messageHandler.js

@@ -0,0 +1,53 @@
+import { computed,provide, onMounted, onUnmounted, ref, nextTick } from 'vue'
+import { useStore } from 'vuex'
+
+export const listenMessage = () => {
+  const store = useStore()
+  const triggerTour = ref(0)
+  const isOpenTours = ref(false)
+
+  provide("triggerTour", triggerTour);
+  provide("isOpenTours", isOpenTours);
+
+  const handleMessage = (res) => {
+    if (Object.prototype.toString.call(res.data) == '[object Object]') {
+      if (res.data.source !== 'qjkankan') {
+        return
+      }
+
+      let { event, params } = res.data
+
+      //触发自动导览
+      if (event == "playTour") {
+        triggerTour.value += 1
+      }
+
+      //导览列表开关
+      if (event == "openTours") {
+        isOpenTours.value = params.showTours
+      }
+
+       //相机模式改变
+      if (event == "setMode") {
+        store.commit('setMode', params.name)
+      }
+
+      
+    }
+  }
+
+  onMounted(() => {
+    nextTick(() => {
+      window.removeEventListener('message', handleMessage)
+      window.addEventListener('message', handleMessage)
+    })
+
+  })
+
+  onUnmounted(() => {
+    window.removeEventListener('message', handleMessage)
+  })
+
+
+}
+

+ 18 - 0
packages/qjkankan-kankan-view/src/utils/track.js

@@ -0,0 +1,18 @@
+export const Track = function (eventName, options = {}) {
+  if (!KanKan.medici) {
+      return
+  }
+  KanKan.medici.track(eventName, options)
+}
+export const startTrack = function (eventName, options = {}) {
+  if (!KanKan.medici) {
+      return
+  }
+  KanKan.medici.startTrack(eventName, options)
+}
+export const endTrack = function (eventName, options = {}) {
+  if (!KanKan.medici) {
+      return
+  }
+  KanKan.medici.endTrack(eventName, options)
+}

Datei-Diff unterdrückt, da er zu groß ist
+ 2054 - 1951
packages/qjkankan-view/package-lock.json


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

@@ -11,8 +11,6 @@
     "axios": "^0.27.2",
     "clipboard": "^2.0.11",
     "core-js": "^3.8.3",
-    "sass": "^1.53.0",
-    "sass-loader": "^13.0.2",
     "tiny-emitter": "^2.1.0",
     "vue": "^3.2.13",
     "vue-i18n": "^9.1.10",
@@ -30,6 +28,8 @@
     "eslint-config-prettier": "^8.3.0",
     "eslint-plugin-prettier": "^4.0.0",
     "eslint-plugin-vue": "^8.0.3",
-    "prettier": "^2.4.1"
+    "prettier": "^2.4.1",
+    "sass": "^1.26.5",
+    "sass-loader": "^8.0.2"
   }
 }

+ 2 - 1
packages/qjkankan-view/public/show.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/iconfontQJ1.1.0/iconfont.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/iconfontVR/iconfont.css"/>
-    <link rel="stylesheet" href="//at.alicdn.com/t/font_2410347_4htx35g8w1b.css"/>
+    <link rel="stylesheet" href="//at.alicdn.com/t/c/font_2947721_9yw6iv77i18.css"/>
     <link rel="stylesheet" href="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper-bundle.min.css" />
     <link rel="icon" href="./favicon.ico" />
     <title>VR作品</title>
@@ -18,6 +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/howler/howler.min.js"></script>
     <script src="<%= VUE_APP_STATIC_DIR %>/lib/swiper/swiper-bundle.min.js"></script>
    
   </body>

Datei-Diff unterdrückt, da er zu groß ist
+ 4 - 0
packages/qjkankan-view/public/static/lib/howler/howler.min.js


BIN
packages/qjkankan-view/public/static/lib/krpano/skin/krpano-roundlogo.png


BIN
packages/qjkankan-view/public/static/lib/krpano/skin/masking.png


Datei-Diff unterdrückt, da er zu groß ist
+ 312 - 229
packages/qjkankan-view/public/static/lib/krpano/skin/vtourskin.xml


+ 1 - 1
packages/qjkankan-view/public/static/lib/krpano/tour.xml

@@ -12,7 +12,7 @@
 	               webvr="true"
 	               webvr_gyro_keeplookingdirection="false"
 	               webvr_prev_next_hotspots="true"
-	               littleplanetintro="false"
+	               littleplanetintro="true"
 	               title="true"
 	               thumbs="true"
 	               thumbs_width="120" thumbs_height="80" thumbs_padding="10" thumbs_crop="0|40|240|160"

Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
packages/qjkankan-view/src/assets/images/icon/3d_normal.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 31 - 0
packages/qjkankan-view/src/assets/images/icon/3d_selected.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
packages/qjkankan-view/src/assets/images/icon/collect.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 26 - 0
packages/qjkankan-view/src/assets/images/icon/commentary.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/commentary_disabled.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 28 - 0
packages/qjkankan-view/src/assets/images/icon/function_off.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 28 - 0
packages/qjkankan-view/src/assets/images/icon/function_on.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 28 - 0
packages/qjkankan-view/src/assets/images/icon/link.svg


+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/more.svg

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="34px" height="34px" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>more</title>
+    <defs>
+        <filter x="-75.0%" y="-75.0%" width="250.0%" height="250.0%" filterUnits="objectBoundingBox" id="filter-1">
+            <feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.2 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
+            <feMerge>
+                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
+                <feMergeNode in="SourceGraphic"></feMergeNode>
+            </feMerge>
+        </filter>
+    </defs>
+    <g id="展示端" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="移动展示端" transform="translate(-258.000000, 0.000000)" fill="#FFFFFF">
+            <g id="more" filter="url(#filter-1)" transform="translate(267.000000, 9.000000)">
+                <circle id="椭圆形" cx="1.5" cy="8" r="1.5"></circle>
+                <circle id="椭圆形" cx="8" cy="8" r="1.5"></circle>
+                <circle id="椭圆形" cx="14.5" cy="8" r="1.5"></circle>
+            </g>
+        </g>
+    </g>
+</svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
packages/qjkankan-view/src/assets/images/icon/music.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/music_disabled.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/pause01.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
packages/qjkankan-view/src/assets/images/icon/plane_normal.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/plane_selected.svg


packages/qjkankan-view/src/assets/images/icon/player_pic01@2x.png → packages/qjkankan-view/src/assets/images/icon/player_pic01.png


+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/playing01.svg

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="34px" height="34px" viewBox="0 0 34 34" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>playing01</title>
+    <defs>
+        <filter x="-75.0%" y="-75.0%" width="250.0%" height="250.0%" filterUnits="objectBoundingBox" id="filter-1">
+            <feOffset dx="0" dy="2" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="2" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.2 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix>
+            <feMerge>
+                <feMergeNode in="shadowMatrixOuter1"></feMergeNode>
+                <feMergeNode in="SourceGraphic"></feMergeNode>
+            </feMerge>
+        </filter>
+    </defs>
+    <g id="展示端" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="移动展示端" transform="translate(-403.000000, 0.000000)" fill="#FFFFFF">
+            <g id="playing01" filter="url(#filter-1)" transform="translate(412.000000, 9.000000)">
+                <circle id="椭圆形" fill-opacity="0.5" cx="8" cy="8" r="7"></circle>
+                <path d="M8,0.25 C3.71979319,0.25 0.25,3.71979319 0.25,8 C0.25,12.2802068 3.71979319,15.75 8,15.75 C12.2802068,15.75 15.75,12.2802068 15.75,8 C15.75,3.71979319 12.2802068,0.25 8,0.25 Z M8,1.75 C11.4517797,1.75 14.25,4.54822031 14.25,8 C14.25,11.4517797 11.4517797,14.25 8,14.25 C4.54822031,14.25 1.75,11.4517797 1.75,8 C1.75,4.54822031 4.54822031,1.75 8,1.75 Z" id="椭圆形" fill-rule="nonzero"></path>
+                <path d="M10.7519246,8.79705021 L7.5547002,10.839003 C7.09517151,11.1324875 6.47430216,11.0135294 6.16794971,10.5733026 C6.05843803,10.4159349 6,10.2310343 6,10.0419019 L6,5.95799632 C6,5.42890956 6.44771525,5 7,5 C7.19742499,5 7.39043268,5.05598342 7.5547002,5.1608952 L10.7519246,7.20284798 C11.2114532,7.4963325 11.3356271,8.09112305 11.0292747,8.53134984 C10.9560398,8.63658793 10.8617768,8.72689149 10.7519246,8.79705021 Z" id="三角形"></path>
+            </g>
+        </g>
+    </g>
+</svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 26 - 0
packages/qjkankan-view/src/assets/images/icon/roaming_normal.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
packages/qjkankan-view/src/assets/images/icon/roaming_selected.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 29 - 0
packages/qjkankan-view/src/assets/images/icon/rotation.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 26 - 0
packages/qjkankan-view/src/assets/images/icon/rotation_disabled.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 26 - 0
packages/qjkankan-view/src/assets/images/icon/share.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 25 - 0
packages/qjkankan-view/src/assets/images/icon/telephone.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
packages/qjkankan-view/src/assets/images/icon/text.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 26 - 0
packages/qjkankan-view/src/assets/images/icon/vr.svg


+ 0 - 15
packages/qjkankan-view/src/assets/scss/_base-vars.scss

@@ -1,15 +0,0 @@
-
-:root {
-  --colors-primary-fill: 255, 255, 255;
-  --colors-primary-base-fill: 0, 200, 175;
-  --colors-primary-base: rgb(var(--colors-primary-base-fill));
-  --colors-primary-hover: #4DD8C7;
-  // --colors-primary-hover: #008B7A;
-  --colors-primary-active: #008B7A;
-  --colors-primary-click: #005046;
-  --colors-warn: #FA3F48;
-  --colors-color: #999;
-  --colors-border-color: rgba(var(--colors-primary-fill), 0.16);
-  --colors-content-color: rgb(--colors-primary-fill);
-  
-}

+ 227 - 243
packages/qjkankan-view/src/assets/scss/theme.scss

@@ -1,101 +1,113 @@
-// @import "base";
-// @import "base-vars";
-$img-base-path: '~@qjkankan/components/src/assets/img/';
+// 资源图片目录地址(必要)
+$img-base-path: '~@/global_components/assets/img/';
+@import '~@/global_components/assets/scss/theme-editor.scss';
 
-@import '~@qjkankan/components/src/assets/scss/theme-editor.scss';
+:root {
+    --editor-main-color: #0076f6;
+    --editor-font-color: #999;
+
+    --editor-toolbox-top: 0;
+    --editor-toolbox-left: 0;
+    --editor-toolbox-width: 240px;
+    --editor-toolbox-padding: 0 10px;
+    --editor-menu-active: rgba(0, 200, 175, 0.16);
+
+    --colors-primary-base: var(--editor-main-color);
+    --colors-primary-click: #005046;
+}
 
 ::-webkit-scrollbar {
-  width: 4px;
-  height: 1px;
+    width: 4px;
+    height: 1px;
 }
 
 ::-webkit-scrollbar-thumb {
-  border-radius: 4px;
-  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
-  background: #ccc;
+    border-radius: 4px;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+    background: #ccc;
 }
 
 ::-webkit-scrollbar-thumb:hover {
-  background: #999;
+    background: #999;
 }
 
 ::-webkit-scrollbar-track {
-  box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
-  border-radius: 4px;
-  background: #000000;
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+    border-radius: 4px;
+    background: #000000;
 }
 ul,
 li {
-  margin: 0;
-  padding: 0;
-  list-style: none;
+    margin: 0;
+    padding: 0;
+    list-style: none;
 }
 html {
-  line-height: 1.15;
-  -webkit-text-size-adjust: 100%;
+    line-height: 1.15;
+    -webkit-text-size-adjust: 100%;
 }
 html,
 body {
-  width: 100%;
-  height: 100%;
-  margin: 0;
-  font-size: 14px;
-  overflow: hidden;
-  user-select: none;
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    font-size: 14px;
+    overflow: hidden;
+    user-select: none;
 }
 #app {
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  color: #fff;
-  background-color: #232323;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    color: #fff;
+    background-color: #232323;
 }
 
 .disable * {
-  opacity: 0.85;
-  pointer-events: none;
+    opacity: 0.85;
+    pointer-events: none;
 }
 
 .enable {
-  opacity: 1 !important;
-  pointer-events: all !important;
-  * {
     opacity: 1 !important;
     pointer-events: all !important;
-  }
+    * {
+        opacity: 1 !important;
+        pointer-events: all !important;
+    }
 }
 
 .hidden {
-  visibility: hidden !important;
-  pointer-events: none !important;
-  z-index: -1;
+    visibility: hidden !important;
+    pointer-events: none !important;
+    z-index: -1;
 }
 
 .scene {
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  overflow: hidden;
-  z-index: 1;
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    z-index: 1;
 }
 .slide-right-enter-active,
 .slide-right-leave-active {
-  will-change: transform;
-  transition: all 0.2s ease-in-out;
+    will-change: transform;
+    transition: all 0.2s ease-in-out;
 }
 .slide-right-enter-from {
-  opacity: 0;
-  transform: translate3d(100%, 0, 0);
+    opacity: 0;
+    transform: translate3d(100%, 0, 0);
 }
 .slide-right-enter {
-  opacity: 1;
-  transform: translate3d(-100%, 0, 0);
+    opacity: 1;
+    transform: translate3d(-100%, 0, 0);
 }
 .slide-right-leave-active {
-  opacity: 0;
-  transform: translate3d(100%, 0, 0);
+    opacity: 0;
+    transform: translate3d(100%, 0, 0);
 }
 // .slide-right-enter-active,
 // .slide-right-leave-active,
@@ -108,241 +120,213 @@ body {
 
 .fade-enter,
 .fade-leave-to {
-  opacity: 0;
+    opacity: 0;
 }
 .fade-enter-to,
 .fade-leave {
-  opacity: 1;
+    opacity: 1;
 }
 .fade-enter-active,
 .fade-leave-active {
-  transition: all 3s;
+    transition: all 3s;
 }
 
 .slide-right-enter {
-  opacity: 1;
-  transform: translate3d(-100%, 0, 0);
+    opacity: 1;
+    transform: translate3d(-100%, 0, 0);
 }
 .slide-right-leave-active {
-  opacity: 1;
-  transform: translate3d(100%, 0, 0);
+    opacity: 1;
+    transform: translate3d(100%, 0, 0);
 }
 .slide-left-enter {
-  opacity: 1;
-  transform: translate3d(-100%, 0, 0);
+    opacity: 1;
+    transform: translate3d(-100%, 0, 0);
 }
 .slide-left-leave-active {
-  opacity: 1;
-  transform: translate3d(100%, 0, 0);
+    opacity: 1;
+    transform: translate3d(100%, 0, 0);
 }
 
 .ui-view-layout {
-  width: 100%;
-  height: 100%;
-  visibility: hidden;
-  &.show {
-    visibility: visible;
-  }
+    width: 100%;
+    height: 100%;
+    visibility: hidden;
+    &.show {
+        visibility: visible;
+    }
 }
-input[type="password"]::-ms-reveal {
-  display: none;
+input[type="password"]::-ms-reveal{
+  display:none
 }
 .ui-editor-toolbox {
-  .edit-list {
-    li {
-      margin-top: 20px;
-      color: var(--editor-font-color);
-      border-bottom: solid 1px rgba(255, 255, 255, 0.16);
-      &:last-child {
-        border-bottom: none;
-      }
-      > div {
-        margin-bottom: 14px;
-      }
-      label {
-        color: #fff;
-        i {
-          cursor: pointer;
-        }
-      }
-      .title {
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
-        span {
-          font-weight: bold;
-          font-size: 16px;
-        }
-      }
+    .edit-list {
+        li {
+            margin-top: 20px;
+            color: var(--editor-font-color);
+            border-bottom: solid 1px rgba(255, 255, 255, 0.16);
+            &:last-child {
+                border-bottom: none;
+            }
+            > div {
+                margin-bottom: 14px;
+            }
+            label {
+                color: #fff;
+                i {
+                    cursor: pointer;
+                }
+            }
+            .title {
+                display: flex;
+                justify-content: space-between;
+                align-items: center;
+                span {
+                    font-weight: bold;
+                    font-size: 16px;
+                }
+            }
 
-      .between {
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-      }
+            .between {
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+            }
+        }
     }
-  }
 }
 
 .ql-editor {
-  padding: 0;
+    padding: 0;
 }
 a {
-  color: #00c8af;
+    color: #ED5D18;
 }
 
 [xui_min_map] {
-  top: 20px !important;
-  right: 20px !important;
+    top: 20px !important;
+    right: 20px !important;
 }
 .slider-box {
-  position: fixed;
-  top: 0;
-  right: 0;
-  width: var(--editor-toolbox-width);
-  height: 100%;
-  background: rgba(20, 20, 20, 1);
-  z-index: 1;
-  .slider-content {
-    color: rgba(255, 255, 255, 0.6);
-    .content-item {
-      padding: 20px 10px;
-      box-sizing: border-box;
-      border-bottom: 1px solid rgba(255, 255, 255, 0.16);
-      box-sizing: border-box;
-      &:last-of-type {
-        border-bottom: 1px solid transparent;
-      }
-    }
+    position: fixed;
+    top: 0;
+    right: 0;
+    width: var(--editor-toolbox-width);
+    height: 100%;
+    background: rgba(20, 20, 20, 1);
+    z-index: 1;
+    .slider-content {
+        color: rgba(255, 255, 255, 0.6);
+        .content-item {
+            padding: 20px 10px;
+            box-sizing: border-box;
+            border-bottom: 1px solid rgba(255, 255, 255, 0.16);
+            box-sizing: border-box;
+            &:last-of-type {
+                border-bottom: 1px solid transparent;
+            }
+        }
 
-    .item-title {
-      font-size: 16px;
-      font-weight: bold;
-      color: #999;
-      margin-bottom: 14px;
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-    }
-  }
-  .slider-title {
-    height: 64px;
-    border-bottom: 1px solid rgba(255, 255, 255, 0.16);
-    color: #999;
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    padding: 20px 10px;
-    box-sizing: border-box;
-    span {
-      font-size: 18px;
-      color: #999;
-      font-weight: bold;
+        .item-title {
+            font-size: 16px;
+            font-weight: bold;
+            color: #999;
+            margin-bottom: 14px;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+        }
     }
-    i {
-      cursor: pointer;
+    .slider-title {
+        height: 64px;
+        border-bottom: 1px solid rgba(255, 255, 255, 0.16);
+        color: #999;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        padding: 20px 10px;
+        box-sizing: border-box;
+        span {
+            font-size: 18px;
+            color: #999;
+            font-weight: bold;
+        }
+        i {
+            cursor: pointer;
+        }
     }
-  }
 }
 
 [is-mobile] {
-  [xui_min_map] {
-    width: 100px;
-    height: 100px;
-    top: 2.3rem !important;
-    right: 15px !important;
-    background-color: rgba(0, 0, 0, 0.2) !important;
-    border-radius: 4px 4px 0 0 !important;
-    border-top-left-radius: 0 !important;
-    transition: all 0.3s;
-    &.collapse {
-      transform: translateX(calc(100% + 15px));
-      .button-switch {
-        > .iconfont {
-          font-size: 12px;
-          transform: rotate(180deg) scale(0.7);
+    [xui_min_map] {
+        width: 100px;
+        height: 100px;
+        top: 2.3rem !important;
+        right: 15px !important;
+        background-color: rgba(0, 0, 0, 0.2) !important;
+        border-radius: 4px 4px 0 0  !important;
+        border-top-left-radius: 0 !important;
+        transition: all .3s;
+        &.collapse{
+          transform: translateX(calc(100% + 15px));
+          .button-switch{
+            >.iconfont{
+              font-size: 12px;
+              transform: rotate(180deg) scale(.7);
+            }
+       
+          }
+        }
+        .button-switch {
+            position: absolute;
+            top: 0;
+            left: -16px;
+            background-color: rgba(0, 0, 0, 0.2);
+            height: 32px;
+            width: 16px;
+            border-radius: 32px 0 0 32px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            transition: rotate .3s;
+            >.iconfont{
+              font-size: 12px;
+              transform: scale(.7);
+            }
+        }
+        .change{
+            position: absolute;
+            bottom: -29px;
+            left: 0;
+            height: 28px;
+            background-color: rgba(0, 0, 0, 0.2);
+            width: 100%;
+            text-align: center;
+            margin: 0;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            border-radius: 0 0 4px 4px!important;
+            >i{
+                margin-right: 4px;
+            }
         }
-      }
-    }
-    .button-switch {
-      position: absolute;
-      top: 0;
-      left: -20px;
-      background-color: rgba(0, 0, 0, 0.2);
-      height: 32px;
-      width: 20px;
-      border-top-left-radius: 4px;
-      border-bottom-left-radius: 4px;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      transition: rotate 0.3s;
-      > .iconfont {
-        font-size: 12px;
-        transform: scale(0.7);
-      }
-    }
-    .button-dollhouse {
-      position: absolute;
-      bottom: -30px;
-      left: 0;
-      width: 100%;
-      height: 30px;
-      font-size: 12px;
-      background-color: rgba(0, 0, 0, 0.2) !important;
-      color: #fff;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      border-top: 1px solid #eee;
-      border-radius: 0 0 4px 4px;
-      > .iconfont {
-        font-size: 14px;
-        margin-right: 0.0667rem;
-      }
     }
-  }
-  .ui-dialog {
-    .ui-dialog__box {
-      min-width: 100px;
-      width: 90%;
+    .ui-dialog{
+        .ui-dialog__box{
+            min-width: 100px;
+            width: 90%;
+        }
     }
-  }
-}
-@keyframes fadeInUp {
-  0% {
-    opacity: 0;
-    -webkit-transform: translate3d(0, 100%, 0);
-    transform: translate3d(0, 100%, 0);
-  }
-
-  to {
-    opacity: 1;
-    -webkit-transform: translateZ(0);
-    transform: translateZ(0);
-  }
 }
-.animated.faster {
-  -webkit-animation-duration: 0.5s;
-  animation-duration: 0.5s;
-}
-.fadeInUp {
-  -webkit-animation-name: fadeInUp;
-  animation-name: fadeInUp;
-}
-@keyframes fadeOutDown {
-  0% {
-    opacity: 1;
-  }
 
-  to {
+.v-enter,
+.v-leave-to {
     opacity: 0;
-    -webkit-transform: translate3d(0, 100%, 0);
-    transform: translate3d(0, 100%, 0);
-  }
+    transform: translateY(100px);
 }
 
-.fadeOutDown {
-  -webkit-animation-name: fadeOutDown;
-  animation-name: fadeOutDown;
+.v-enter-active,
+.v-leave-active {
+    transition: all 0.25s ease;
 }

+ 64 - 4
packages/qjkankan-view/src/components/Fdkk/index.vue

@@ -1,15 +1,74 @@
 <template>
   <div class="fdkkcon">
-    <iframe src="https://www.4dkankan.com/spc.html?m=SS-0UKHRqfv0r" frameborder="0"></iframe>
+    <iframe id="fdkkifr" src="http://192.168.20.66:8080/spg.html?m=KJ-t-CcMTDQc1MJ" frameborder="0"></iframe>
   </div>
 </template>
 
 <script setup>
-  
+import { ref, watch, computed, onUnmounted, onMounted, nextTick } from "vue";
+import { useStore } from "vuex";
+const store = useStore();
+
+const handleMessage = (res) => {
+  if (Object.prototype.toString.call(res.data) == '[object Object]') {
+    if (res.data.source !== 'qjkankan') {
+      return
+    }
+
+    let {event,params} = res.data
+
+    //导览片段
+    if (event == "toursList") {
+      store.commit('fdkk/setToursList', params.tours)
+    }
+
+    //是否导览中
+    if (event == "isPlayTours") {
+      store.commit('fdkk/setIsPlayTours', params.isPlay)
+    }
+
+    // 是否flying
+    if (event == "isFlying") {
+      store.commit('fdkk/setIsFlying', params.isFlying)
+    }
+
+    if (event == "setMode") {
+      store.commit('fdkk/setMode', params.mode)
+    }
+    
+    
+  }
+}
+
+onMounted(() => {
+  nextTick(() => {
+    window.removeEventListener('message', handleMessage)
+    window.addEventListener('message', handleMessage)
+  })
+
+})
+
+onUnmounted(() => {
+  window.removeEventListener('message', handleMessage)
+})
+
+
+
+  // window.parent.postMessage(
+  //   {
+  //     source: "cdf",
+  //     event: "audioMuted",
+  //     params: {
+  //       audioMuted: audioMuted.value,
+  //     },
+  //   },
+  //   "*"
+  // );
+
 </script>
 
 <style lang="scss" scoped>
-.fdkkcon{
+.fdkkcon {
   position: absolute;
   width: 100%;
   height: 100%;
@@ -17,7 +76,8 @@
   left: 0;
   right: 0;
   bottom: 0;
-  >iframe{
+
+  >iframe {
     width: 100%;
     height: 100%;
   }

+ 42 - 8
packages/qjkankan-view/src/components/Pano/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="pano"></div>
+  <div id="pano" v-show="currentScene.type != '4dkk'"></div>
   <Fdkk v-if="currentScene.type == '4dkk'" />
 </template>
 
@@ -12,9 +12,12 @@ import Fdkk from "../Fdkk";
 const store = useStore();
 
 const currentScene = computed(() => store.getters["scene/currentScene"]);
+const metadata = computed(() => store.getters["scene/metadata"]);
 
 const loadScene = async (currentScene) => {
   let app = await getApp();
+  console.log(app.krpanoDom);
+
   if (app.krpanoDom) {
     console.log(currentScene);
     let { sceneCode, initVisual } = currentScene;
@@ -29,24 +32,50 @@ const loadScene = async (currentScene) => {
 };
 
 watch(currentScene, (newVal) => {
-
+  history.replaceState(null, null, "".concat(window.location.pathname, "?").concat(`id=${metadata.value.id}&vr=${newVal.sceneCode}`));
   if (newVal.type == 'pano') {
-    loadScene(newVal);
-  } else{
+    nextTick(() => {
+      loadScene(newVal);
+
+    });
+  } else {
 
   }
 
-  console.log(newVal.sceneCode);
   // console.log(currentScene.value,'currentScene.value');
-  
+
 });
 
+const updateListPosi = () => {
+
+  let catalog = metadata.value.catalogs.find((item) => item.id == currentScene.value.category);
+
+  // 查询初始场景的所在1级分组
+  metadata.value.catalogRoot.forEach((item) => {
+    let temp = item.children && item.children.find((sub) => sub == catalog.id);
+    if (temp) {
+      store.commit("scene/setCurrentCatalogRoot", item);
+      return;
+    }
+  });
+
+  // 查询初始场景的所在2级分组
+  store.commit("scene/setCurrentSecondary", catalog);
+
+}
+
 useApp().then((app) => {
   app.Tags.on("clickHotspot", (data) => {
     let { id } = data;
     let tt = currentScene.value.someData.hotspots.find((item) => item.name == id);
-    store.commit("tags/setCurrentTag", tt);
-    console.log(tt);
+
+    if (tt.hotspotType == 'scene') {
+      store.commit("scene/setCurrentScene", tt.secne);
+      updateListPosi()
+    } else {
+      store.commit("tags/setCurrentTag", tt);
+      console.log(tt);
+    }
   });
 });
 </script>
@@ -56,4 +85,9 @@ useApp().then((app) => {
   width: 100%;
   height: 100%;
 }
+
+.novisible {
+  opacity: 0;
+  visibility: hidden;
+}
 </style>

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

@@ -1,7 +1,35 @@
 <template>
   <ul class="control">
+
+    <!-- 自定义链接 -->
+    <li @click="onLink" v-if="isLink">
+      <img :src="require(`@/assets/images/icon/link.svg`)" alt="" />
+    </li>
+
+    <!-- 联系电话 -->
+    <li @click="onTelephone" v-if="isTelephone">
+      <img :src="require(`@/assets/images/icon/telephone.svg`)" alt="" />
+    </li>
+
+    <!-- 简介 -->
+    <li @click="onIntroduce" v-if="metadata.description">
+      <img :src="require(`@/assets/images/icon/text.svg`)" alt="" />
+    </li>
+
+    <!-- 背景音乐 -->
+    <li @click="onIsBGM" v-if="metadata.backgroundMusic && metadata.backgroundMusic.id">
+      <img :src="require(`@/assets/images/icon/${showMusicPlaying ? 'music.svg' : 'music_disabled.svg'}`)" alt="" />
+    </li>
+
+    <!-- 解说音频 -->
+    <li @click="onIsCommentary">
+      <img :src="require(`@/assets/images/icon/${showCommentaryPlaying ? 'commentary.svg' : 'commentary_disabled.svg'}`)"
+        alt="" />
+    </li>
+
     <li @click="onIsAutoRotate">
-      <img :src="require(`@/assets/images/icon/${isAutoRotate ? 'rotation@2x.png' : 'rotation_disabled@2x.png'}`)" alt="" />
+      <img :src="require(`@/assets/images/icon/${isAutoRotate ? 'rotation@2x.png' : 'rotation_disabled@2x.png'}`)"
+        alt="" />
     </li>
 
     <li @click="onVR">
@@ -15,52 +43,144 @@
     <li @click="onFullScreen">
       <img :src="require(`@/assets/images/icon/${'fullscreen@2x.png'}`)" alt="" />
     </li>
+
   </ul>
+
+  <teleport to='body'>
+    <introduce v-if="showIntroduce" />
+    <telephone v-if="showTelephone" />
+    <clink v-if="showLink" />
+  </teleport>
 </template>
 
 <script setup>
-import { ref, watch, computed, onMounted, nextTick } from "vue";
+import { ref, watch, computed, onMounted, watchEffect, nextTick } from "vue";
 import { useStore } from "vuex";
 import { useApp } from "@/app";
+
+import introduce from "./control/text";
+import telephone from "./control/telephone";
+import clink from "./control/link";
+import { useMusicPlayer,useSoundPlayer } from '@/utils/sound'
+
+
+//背景音乐
+const musicPlayer = useMusicPlayer()
+
+//解说音乐
+const soundPlayer = useSoundPlayer()
+
 const store = useStore();
 
+const metadata = computed(() => store.getters["scene/metadata"]);
+
+
 const isAutoRotate = computed(() => store.getters["functions/isAutoRotate"]);
+
+const showMusicPlaying = ref(false)
+const showCommentaryPlaying = ref(false)
+
+// const isCommentary = computed(() => store.getters["functions/isCommentary"]);
+
+const currentScene = computed(() => store.getters["scene/currentScene"]);
+
+
+const isTelephone = computed(() => {
+  return metadata.value.customButton ? metadata.value.customButton.find(item => item.name == '电话').isShow : false
+});
+
+const isLink = computed(() => {
+  return metadata.value.customButton ? metadata.value.customButton.find(item => item.name == '链接').isShow : false
+});
+
+
+
+watchEffect(() => {
+  if (currentScene.value.explanation) {
+    let { audioUrl, openByDefault, repeat } = currentScene.value.explanation
+
+    if (audioUrl) {
+        store.commit("functions/setCommentaryUrl", {
+          src:audioUrl,
+          loop:repeat,
+          openByDefault:openByDefault
+        });
+        useSoundPlayer.player.isLock = false
+        useSoundPlayer.player.watchPlay()
+    }else{
+      store.commit("functions/setCommentaryUrl", '');
+      useSoundPlayer.player.isLock = true
+
+    }
+  }
+})
+
+
+const showIntroduce = computed(() => store.getters["functions/showIntroduce"]);
+const showTelephone = computed(() => store.getters["functions/showTelephone"]);
+const showLink = computed(() => store.getters["functions/showLink"]);
+
 const isFullscreen = ref(false)
 
+const onIntroduce = () => {
+  store.commit("functions/setShowIntroduce", true);
+}
+
+
+const onTelephone = () => {
+  store.commit("functions/setShowTelephone", true);
+}
+
+
+const onLink = () => {
+  store.commit("functions/setShowLink", true);
+}
+
+const onIsBGM = () => {
+  showMusicPlaying.value ? musicPlayer.pause() : musicPlayer.play()
+}
+
 const onIsAutoRotate = (data) => {
   store.commit("functions/setAutoRotate", !isAutoRotate.value);
 };
 
 
+const onIsCommentary = (data) => {
+  showCommentaryPlaying.value ? soundPlayer.pause() : soundPlayer.play()
+};
+
+
+
 const onFullScreen = () => {
-    let element = document.documentElement
-    if (isFullscreen.value) {
-        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()
-        }
+  let element = document.documentElement
+  if (isFullscreen.value) {
+    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;
+  }
+  // 改变当前全屏状态
+  //this.isFullscreen = !this.isFullscreen;
 }
 
 const onVR = (data) => {
   useApp().then((app) => {
+    console.log(app.krpanoDom.get('webvr'));
     app.krpanoDom.call("webvr.enterVR()")
   });
 };
@@ -96,13 +216,25 @@ const staticList = ref([
 
 
 onMounted(() => {
-    let events = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange']
-    events.forEach((item, index) => {
-        window.addEventListener(item, () => {
-            isFullscreen.value = !isFullscreen.value
-        })
+  let events = ['fullscreenchange', 'webkitfullscreenchange', 'mozfullscreenchange', 'MSFullscreenChange']
+  events.forEach((item, index) => {
+    window.addEventListener(item, () => {
+      isFullscreen.value = !isFullscreen.value
     })
+  })
+})
+
+musicPlayer.on('play', () => {
+  showMusicPlaying.value = true
+  soundPlayer.pause()
 })
+musicPlayer.on('pause', () => (showMusicPlaying.value = false))
+
+soundPlayer.on('play', () => {
+  showCommentaryPlaying.value = true
+  musicPlayer.pause()
+})
+soundPlayer.on('pause', () => (showCommentaryPlaying.value = false))
 </script>
 
 <style lang="scss" scoped>
@@ -111,12 +243,14 @@ onMounted(() => {
   right: 20px;
   bottom: 8px;
   display: flex;
-  > li {
+
+  >li {
     width: 36px;
     height: 36px;
     margin: 0 10px;
     cursor: pointer;
-    > img {
+
+    >img {
       width: 100%;
       height: 100%;
     }

+ 92 - 0
packages/qjkankan-view/src/components/UIGather/control/link.vue

@@ -0,0 +1,92 @@
+<template>
+  <div class="tag-layer" @click.stop>
+    <img class="close" @click.stop="close"
+      :src="require('@/assets/images/icon/material_preview_close@2x.png')" alt="" />
+
+    <div class="linkcon">
+      <div class="linkbody">
+        <iframe :src="link" frameborder="0"></iframe>
+      </div>
+    </div>
+  </div>
+
+</template>
+
+<script setup>
+import { reactive, defineEmits, onBeforeMount, onMounted, ref, watchEffect, computed, watch, nextTick } from "vue";
+import { useStore } from "vuex";
+const store = useStore();
+
+const metadata = computed(() => store.getters["scene/metadata"]);
+
+
+const link = computed(() => {
+  return metadata.value.customButton ? metadata.value.customButton.find(item => item.name == '链接').value : false
+});
+
+const close = () => {
+  store.commit("functions/setShowLink", false);
+};
+
+</script>
+
+<style lang="scss" scoped>
+
+.tag-layer {
+  width: 100vw;
+  height: 100vh;
+  z-index: 10000;
+  top: 0;
+  position: fixed;
+  left: 0;
+  background-color: rgba(0, 0, 0, 0.6);
+  backdrop-filter: blur(10px);
+
+  .linkcon {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 100%;
+  width: 100%;
+
+  .linkbody {
+    width: 90%;
+    height: 90%;
+    background: rgba(255,255,255,1);
+    border-radius: 2px;
+    color: #fff;
+    >iframe{
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  .title {
+    position: absolute;
+    left: 20px;
+    top: 20px;
+    height: 36px;
+    line-height: 36px;
+    padding: 0 30px;
+    background: rgba(0, 0, 0, 0.6);
+    border-radius: 20px;
+    color: #fff;
+    font-size: 14px;
+
+    >i {
+      margin-right: 4px;
+    }
+  }
+}
+  .close {
+    width: 36px;
+    height: 36px;
+    right: 30px;
+    top: 30px;
+    position: absolute;
+    cursor: pointer;
+    z-index: 999;
+  }
+}
+
+</style>

+ 108 - 0
packages/qjkankan-view/src/components/UIGather/control/telephone.vue

@@ -0,0 +1,108 @@
+<template>
+  <div class="tag-layer" @click.stop>
+
+    <div class="telephonecon">
+      
+      <div class="txtbody">
+        <div class="theader">
+          <span>联系电话</span>
+          <ui-icon class="close" type="player_close" @click.stop="close"></ui-icon>
+        </div>
+        <div class="telephone">
+          <img :src="require(`@/assets/images/icon/telephone.svg`)" alt="" />
+          <span>{{telephone}}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+
+</template>
+
+<script setup>
+import { reactive, defineEmits, onBeforeMount, onMounted, ref, watchEffect, computed, watch, nextTick } from "vue";
+import { useStore } from "vuex";
+const store = useStore();
+
+const metadata = computed(() => store.getters["scene/metadata"]);
+
+
+const telephone = computed(() => {
+  return metadata.value.customButton ? metadata.value.customButton.find(item => item.name == '电话').value : false
+});
+
+const close = () => {
+  store.commit("functions/setShowTelephone", false);
+};
+
+</script>
+
+<style lang="scss" scoped>
+.tag-layer {
+  width: 100vw;
+  height: 100vh;
+  z-index: 10000;
+  top: 0;
+  position: fixed;
+  left: 0;
+  background-color: rgba(0, 0, 0, 0.6);
+  backdrop-filter: blur(10px);
+
+  .telephonecon {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    height: 100%;
+    width: 100%;
+
+
+    .txtbody {
+      width: 240px;
+      background: rgba(0, 0, 0, 0.6);
+      border-radius: 10px;
+      font-size: 14px;
+      color: #fff;
+      padding: 14px 26px;
+      max-height: calc(100vh - 100px);
+      overflow-y: auto;
+      .theader {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 10px;
+        .close{
+          cursor: pointer;
+        }
+      }
+
+      .telephone{
+        display: flex;
+        align-items: center;
+        >span{
+          margin-top: 6px;
+          display: inline-block;
+        }
+      }
+
+    }
+
+    .title {
+      position: absolute;
+      left: 20px;
+      top: 20px;
+      height: 36px;
+      line-height: 36px;
+      padding: 0 30px;
+      background: rgba(0, 0, 0, 0.6);
+      border-radius: 20px;
+      color: #fff;
+      font-size: 14px;
+
+      >i {
+        margin-right: 4px;
+      }
+    }
+  }
+
+
+}
+</style>

+ 87 - 0
packages/qjkankan-view/src/components/UIGather/control/text.vue

@@ -0,0 +1,87 @@
+<template>
+  <div class="tag-layer" @click.stop>
+    <img class="close" @click.stop="close"
+      :src="require('@/assets/images/icon/material_preview_close@2x.png')" alt="" />
+
+    <div class="txtcon">
+      <div class="txtbody">
+        {{metadata.description}}
+      </div>
+    </div>
+  </div>
+
+</template>
+
+<script setup>
+import { reactive, defineEmits, onBeforeMount, onMounted, ref, watchEffect, computed, watch, nextTick } from "vue";
+import { useStore } from "vuex";
+const store = useStore();
+
+const metadata = computed(() => store.getters["scene/metadata"]);
+
+const close = () => {
+  store.commit("functions/setShowIntroduce", false);
+};
+
+</script>
+
+<style lang="scss" scoped>
+
+.tag-layer {
+  width: 100vw;
+  height: 100vh;
+  z-index: 10000;
+  top: 0;
+  position: fixed;
+  left: 0;
+  background-color: rgba(0, 0, 0, 0.6);
+  backdrop-filter: blur(10px);
+
+  .txtcon {
+  display: flex;
+  align-items: flex-start;
+  justify-content: center;
+  height: 100%;
+  width: 100%;
+  padding-top: 70px;
+
+  .txtbody {
+    width: 744px;
+    background: rgba(0, 0, 0, 0.6);
+    border-radius: 10px;
+    font-size: 14px;
+    color: #fff;
+    padding: 30px;
+    max-height: calc(100vh - 100px);
+    overflow-y: auto;
+  }
+
+  .title {
+    position: absolute;
+    left: 20px;
+    top: 20px;
+    height: 36px;
+    line-height: 36px;
+    padding: 0 30px;
+    background: rgba(0, 0, 0, 0.6);
+    border-radius: 20px;
+    color: #fff;
+    font-size: 14px;
+
+    >i {
+      margin-right: 4px;
+    }
+  }
+}
+  .close {
+    width: 36px;
+    height: 36px;
+    right: 30px;
+    top: 30px;
+    position: absolute;
+    cursor: pointer;
+    z-index: 999;
+  }
+}
+
+</style>

+ 6 - 13
packages/qjkankan-view/src/components/UIGather/index.vue

@@ -1,24 +1,17 @@
 <template>
-  <template v-if="!isEdit">
-      <Logo/>
-      <Tips/>
-      <Control />
-      <Menu />
-  </template>
-
-  <List />
-
+    <Logo/>
+    <Tips/>
+    <Control />
+    <Menu />
+    <sceneList />
 </template>
 
 <script setup>
 import Logo from "./logo";
 import Tips from "./tips";
-import List from "./list";
+import sceneList from "./list";
 import Control from "./control";
 import Menu from "./menu";
-import browser from "@/utils/browser"
 
 import { ref } from "vue";
-
-const isEdit = ref(browser.urlQueryValue('isEdit'));
 </script>

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

@@ -287,7 +287,7 @@ $width: 1150px;
 }
 
 .barshow{
-  max-height: 520px;
+  max-height: 190px;
 }
 
 @keyframes wordsLoop {

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

@@ -13,7 +13,7 @@ const metadata = computed(() => store.getters['scene/metadata'])
 
 </script>
 
-<style lang="less" scoped>
+<style lang="scss" scoped>
 .logo {
   position: absolute;
   top: 20px;

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


Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.