ソースを参照

Merge branch 'dev'

tremble 3 年 前
コミット
20dd4e495f
46 ファイル変更1870 行追加3878 行削除
  1. 3 2
      packages/qjkankan-editor/.env.testprod
  2. 18 1
      packages/qjkankan-editor/README.md
  3. BIN
      packages/qjkankan-editor/doc/场景分组信息原始数据结构.jpg
  4. BIN
      packages/qjkankan-editor/doc/场景分组树形结构.jpg
  5. 1 0
      packages/qjkankan-editor/package.json
  6. 10 6
      packages/qjkankan-editor/src/Store/index.js
  7. BIN
      packages/qjkankan-editor/src/assets/images/default/hotspot_scene_add.png
  8. BIN
      packages/qjkankan-editor/src/assets/images/icons/close01_hover@2x.png
  9. BIN
      packages/qjkankan-editor/src/assets/images/icons/close01_normal@2x.png
  10. 1 47
      packages/qjkankan-editor/src/assets/style/style.pc.edit.less
  11. 1 1
      packages/qjkankan-editor/src/components/insertPositionTipInEditor.vue
  12. 843 12
      packages/qjkankan-editor/src/components/materialSelectorForEditor.vue
  13. 0 327
      packages/qjkankan-editor/src/components/select.vue
  14. 115 126
      packages/qjkankan-editor/src/components/shared/Combox.vue
  15. 4 2
      packages/qjkankan-editor/src/components/shared/Switcher.vue
  16. 0 14
      packages/qjkankan-editor/src/components/shared/uploads/UploadMultiple.vue
  17. 0 416
      packages/qjkankan-editor/src/components/tableSelect.vue
  18. 1 1
      packages/qjkankan-editor/src/mixins/v-clickoutside.js
  19. 0 0
      packages/qjkankan-editor/src/directives/v-clickwindow.js
  20. 0 4
      packages/qjkankan-editor/src/framework/EditorHead.vue
  21. 0 10
      packages/qjkankan-editor/src/framework/Head.vue
  22. 0 89
      packages/qjkankan-editor/src/framework/SettingPC.vue
  23. 0 1
      packages/qjkankan-editor/src/framework/Toolbar.vue
  24. 2 6
      packages/qjkankan-editor/src/mixins/index.js
  25. 1 1
      packages/qjkankan-editor/src/pages/Edit.vue
  26. 2 0
      packages/qjkankan-editor/src/pages/edit.js
  27. 43 56
      packages/qjkankan-editor/src/utils/request.js
  28. 4 0
      packages/qjkankan-editor/src/views/base/backgroundMusicSettings.vue
  29. 4 0
      packages/qjkankan-editor/src/views/explanation/explanationSettings.vue
  30. 0 155
      packages/qjkankan-editor/src/views/hotspot/ConfirmPanel.vue
  31. 210 451
      packages/qjkankan-editor/src/views/hotspot/EditPanel.vue
  32. 15 10
      packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue
  33. 0 392
      packages/qjkankan-editor/src/views/hotspot/Setting.vue
  34. 0 180
      packages/qjkankan-editor/src/views/hotspot/Toolbar.vue
  35. 119 127
      packages/qjkankan-editor/src/views/hotspot/hotspotType/audio.vue
  36. 130 135
      packages/qjkankan-editor/src/views/hotspot/hotspotType/image.vue
  37. 33 10
      packages/qjkankan-editor/src/views/hotspot/hotspotType/link.vue
  38. 134 63
      packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue
  39. 0 34
      packages/qjkankan-editor/src/views/hotspot/hotspotType/style.less
  40. 45 17
      packages/qjkankan-editor/src/views/hotspot/hotspotType/textarea.vue
  41. 128 132
      packages/qjkankan-editor/src/views/hotspot/hotspotType/video.vue
  42. 1 95
      packages/qjkankan-editor/src/views/hotspot/index.vue
  43. 0 112
      packages/qjkankan-editor/src/views/information/Setting.vue
  44. 0 441
      packages/qjkankan-editor/src/views/information/Toolbar.vue
  45. 0 399
      packages/qjkankan-editor/src/views/information/index.vue
  46. 2 3
      packages/qjkankan-editor/vue.config.js

+ 3 - 2
packages/qjkankan-editor/.env.testprod

@@ -1,7 +1,8 @@
+# 部署测试环境时用这个
+NODE_ENV=production
 VUE_APP_MAIN_COLOR=''
 VUE_APP_STATIC_DIR=static
 VUE_APP_INNERNET=https://fcb.intranet.4dkankan.com
 VUE_APP_CDN=https://oss-xiaoan.oss-cn-shenzhen.aliyuncs.com
 VUE_APP_PROXY_URL='http://test.4dkankan.com/qjkankan/'
-VUE_APP_PROXY_4DKANKAN_URL=''
-VUE_APP_URL_FILL=/qjkankan
+VUE_APP_URL_FILL=https://test.4dkankan.com/qjkankan/

+ 18 - 1
packages/qjkankan-editor/README.md

@@ -1,3 +1,13 @@
+# 测试环境发布路径
+注意,路径被隐藏了,需要通过进入路径(打开文件夹)功能直接打开:
+
+/阿里云-四维时代-官网web测试服务器-120.25.146.52/var/www/html/panorama
+
+这个路径下没有服务器缓存。
+
+# 针对测试环境打包
+npm run build-testprod
+
 # someData模板
 
 ## 位置
@@ -68,7 +78,14 @@
       "value": "",
       "isShow": false
     }
-  ]
+  ],
+  "explanation": { // 解说信息
+    "audioId": "",
+    "audioName": "",
+    "audioUrl": "",
+    "openByDefault": true, // 是否默认开启
+    "repeat": true // 是否重复播放
+  }
 }
 ```
 

BIN
packages/qjkankan-editor/doc/场景分组信息原始数据结构.jpg


BIN
packages/qjkankan-editor/doc/场景分组树形结构.jpg


+ 1 - 0
packages/qjkankan-editor/package.json

@@ -9,6 +9,7 @@
     "serve-local": "vue-cli-service serve --mode bendi",
     "build": "vue-cli-service build",
     "build-prod": "vue-cli-service build --mode prod",
+    "build-testprod": "vue-cli-service build --mode testprod",
     "lint": "vue-cli-service lint"
   },
   "dependencies": {

+ 10 - 6
packages/qjkankan-editor/src/Store/index.js

@@ -12,7 +12,6 @@ const store = new Vuex.Store({
     userNickName: '',
 
     info: '',
-    // todo: 新版本开发完毕后就不需要这个了
     backupInfo: '',
     showInfo: '',
     hotspot: '',
@@ -22,7 +21,6 @@ const store = new Vuex.Store({
     temptablist: [],
     vrlist: [],
     allVrlist: [],
-    sceneList: [],
     activeItem: '',
     isEditing: false,
     isShow: false,
@@ -100,7 +98,6 @@ const store = new Vuex.Store({
     vrlist: state => state.vrlist,
     tablist: state => state.tablist,
     temptablist: state => state.temptablist,
-    sceneList: state => state.sceneList,
     isShow: state => state.isShow,
     allVrlist: state => state.allVrlist,
 
@@ -132,9 +129,6 @@ const store = new Vuex.Store({
     SetVrList(state, list) {
       state.vrlist = list
     },
-    SetSceneList(state, list) {
-      state.sceneList = list
-    },
     UpdateIsShowState(state, isShow) {
       state.isShow = isShow
     },
@@ -168,6 +162,16 @@ const store = new Vuex.Store({
       state.backupHotSpot = data
     },
 
+    setUploadStatusListImage(state, data) {
+      state.uploadStatusListImage = data
+    },
+    setUploadStatusListAudio(state, data) {
+      state.uploadStatusListAudio = data
+    },
+    setUploadStatusListVideo(state, data) {
+      state.uploadStatusListVideo = data
+    },
+    
     setEditorNavDragType(state, data) {
       if (!['topologyGroupLevel1', 'topologyGroupLevel2', 'scene'].includes(data)) {
         throw("拖拽类型必须是'topologyGroupLevel1', 'topologyGroupLevel2', 'scene'之一!")

BIN
packages/qjkankan-editor/src/assets/images/default/hotspot_scene_add.png


BIN
packages/qjkankan-editor/src/assets/images/icons/close01_hover@2x.png


BIN
packages/qjkankan-editor/src/assets/images/icons/close01_normal@2x.png


+ 1 - 47
packages/qjkankan-editor/src/assets/style/style.pc.edit.less

@@ -777,52 +777,6 @@ textarea:-ms-input-placeholder {
   }
 }
 
-.message-material {
-  border-radius: 4px;
-  @color: #0076F6;
-  background: #fff;
-  padding: 26px;
-  .header-material {
-    border-bottom: none;
-    line-height: 1;
-    height: auto;
-    > span {
-      font-size: 18px;
-      margin-left: 0;
-      &:last-child {
-        width: auto;
-        cursor: pointer;
-        > i {
-          font-size: 20px;
-          color: #909090;
-        }
-      }
-    }
-  }
-
-  .main-material {
-    .ui-message-icon, .ui-message-title {
-      display: none;
-    }
-    .ui-message-content {
-      line-height: 20px;
-      font-size: 14px;
-      color: #323233;
-      text-align: left;
-      margin: 40px 0;
-    }
-  }
-
-
-  .footer-material {
-    margin: 0;
-    margin-top: 60px;
-    padding: 0;
-    border-top: none;
-    text-align: right;
-  }
-}
-
 .ui-message-header {
   width: 100%;
   font-size: 18px;
@@ -865,7 +819,7 @@ textarea:-ms-input-placeholder {
 
   .ui-message-content {
     font-size: 14px;
-    margin: 20px;
+    margin-top: 20px;
     margin-bottom: 30px;
     word-break: break-all;
   }

+ 1 - 1
packages/qjkankan-editor/src/components/insertPositionTipInEditor.vue

@@ -252,7 +252,7 @@ export default {
             // 把原来那个二级分组条目删除
             this.$nextTick(() => {
               const toDeleteIndex = originalParentGroup.children.findIndex((eachLevel2Id) => {
-                return eachLevel2Id.endsWith('__need__delete__')
+                return eachLevel2Id.toString().endsWith('__need__delete__')
               })
               originalParentGroup.children.splice(toDeleteIndex, 1)
             })

ファイルの差分が大きいため隠しています
+ 843 - 12
packages/qjkankan-editor/src/components/materialSelectorForEditor.vue


+ 0 - 327
packages/qjkankan-editor/src/components/select.vue

@@ -1,327 +0,0 @@
-<template>
-  <!-- todo: 旧版的初始场景设置时弹窗,可以删了? -->
-  <div class="select-commodity">
-    <a class="close" @click="$emit('cancle')">+</a>
-    <h3 class="title">{{ title }}</h3>
-    <div class="filtert">
-      <div>
-        <input
-          type="text"
-          placeholder="输入关键词"
-          v-model="key"
-          @keyup.enter="search"
-        />
-        <i
-        @click="search"
-          class="iconfont iconsearch"
-        ></i>
-      </div>
-    </div>
-
-    <template>
-      <div class="scene-layer">
-        <tabList :list="info.catalogRoot" :cls="'w-menu'" @clickItem="item=>{taboneActive = item}" :hiddenHover="true" :active="taboneActive" :id="'selct11'" :subId="'selct111'">
-        </tabList>
-        <tabList v-if="childTab.length > 1" :list="childTab" :cls="'w-menu'" :hiddenHover="true" @clickItem="item=>{tabtowActive = item}"
-           :active="tabtowActive" :id="'subselct11'" :subId="'subselct111'">
-        </tabList>
-       
-        <div>
-          <div class="pano-con"  v-if="filterScenes.length > 0">
-            <ul>
-              <li
-                v-for="(item, i) in filterScenes"
-                @click="select = item"
-                :class="{ 'li-active': select.sceneCode == item.sceneCode }"
-                :key="i"
-              >
-                <div class="typeli">
-                  <i
-                    class="iconfont iconedit_type_3d"
-                    :class="{'iconedit_type_panorama':item.type!=='4dkk'}"
-                  ></i>
-                </div>
-                <div class="img">
-                  <img :key="i" :src="`${item.icon}?rnd=${Math.random()}`" alt="" />
-                </div>
-                <div class="ui-title">
-                  <span>{{
-                   item.sceneTitle
-                  }}</span>
-                </div>
-              </li>
-            </ul>
-          </div>
-          <div class="nodata" v-else>
-              <img :src="$noresult" alt="">
-              <span>{{!!isClickSearch?'未搜索到结果~':'暂无素材'}}</span>
-            </div>
-        </div>
-      </div>
-    </template>
-
-    <div class="btns">
-      <a @click="$emit('cancle')">取消</a>
-      <a :class="{ disable: disable }" @click="$emit('submit', select)">确定</a>
-    </div>
-  </div>
-</template>
-
-<script>
-import tabList from "@/components/tablist";
-import { mapGetters } from "vuex";
-import { getTabSceneList } from "@/api";
-
-export default {
-components: {tabList},
- props: {
-    selected: {
-      default() {
-        return {};
-      },
-      type: Object | String,
-    },
-    title: {
-      default: "",
-      type: String,
-    }
-  },
-  watch: {
-    taboneActive: {
-      immediate:true,
-      deep:true,
-      handler: function (newVal,oldVal) {
-        
-        if (!newVal.id) {
-          this.taboneActive = this.info.catalogRoot[0]
-        }
-
-        let temp = []
-        newVal.children && newVal.children.forEach(item=>{
-          this.info.catalogs.forEach(sub=>{
-            if (item==sub.id) {
-              temp.push(sub)
-            }
-          })
-        })
-
-        this.childTab = temp
-
-        if (this.childTab.length == 1 || newVal!=oldVal) {
-          this.tabtowActive = this.childTab[0]
-        }
-      },
-    },
-    tabtowActive: {
-      immediate:true,
-      handler: function (newVal) {
-        if (!newVal) {
-          this.tabtowActive = this.childTab[0]
-        } else{
-          this.$emit("catalog",newVal);
-          this.scenes = this.info.scenes.filter(item=>{
-            return newVal.id == item.category
-          })
-          this.key = ''
-
-          this.search()
-        }
-      }
-    }
-  },
-  computed: {
-    ...mapGetters({
-      tablist:'tablist',
-      info: "info",
-      backupInfo: "backupInfo"
-    }),
-    disable() {
-      return !this.select.id;
-    }
-  },
-  data() {
-    return {
-      taboneActive:{children:[]},
-      tabtowActive:'',
-      select:{...this.selected},
-      list:[],
-      childTab:[],
-      scenes:[],
-      filterScenes:[],
-      isClickSearch:'',
-      key: ""
-    };
-  },
-
-  methods: {
-    search(){
-      let tmp = this.scenes.filter(item=>{
-        if (item.sceneTitle.indexOf(this.key)>-1) {
-          return item
-        }
-      })
-      this.filterScenes = tmp.sort((a,b)=>a.weight-b.weight)
-    },
-    getTabSceneList(catalogId=null){
-      if (!catalogId) {
-        catalogId = this.taboneActive.children.length<=0 ? this.taboneActive.id : this.tabtowActive.id
-      }
-      getTabSceneList({catalogId},(data)=>{
-          this.list = data.data||[]
-      })
-    },
-  },
-  mounted() {
-    this.key = "";
-  },
-};
-</script>
-
-<style lang="less" scoped>
-::-webkit-scrollbar-track {
-  box-shadow: inset 0 0 5px rgb(0 0 0 / 20%);
-  border-radius: 4px;
-  background: #fff;
-}
-.select-commodity {
-  position: fixed;
-  z-index: 3;
-  left: 50%;
-  top: 50%;
-  transform: translateX(-50%) translateY(-50%);
-  color: #202020;
-  background: #ffffff;
-  max-width: 960px;
-  width: 100%;
-  border-radius: 6px;
-}
-
-.select-commodity > * {
-  padding: 15px;
-}
-
-.title {
-  font-size: 16px;
-  line-height: 20px;
-  font-weight: 400;
-  margin: 0;
-  font-weight: bold;
-  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
-}
-
-.close {
-  position: absolute;
-  right: -8px;
-  top: -15px;
-  font-size: 25px;
-  color: #909090;
-  transform: rotate(45deg);
-  cursor: pointer;
-}
-
-.filtert {
-  padding: 15px;
-}
-
-.filtert > div {
-  width: 210px;
-  height: 34px;
-  background: rgba(22, 26, 26, 1);
-  border-radius: 2px;
-  display: inline-block;
-  margin-right: 10px;
-  position: relative;
-  vertical-align: middle;
-}
-
-.filtert > div > select,
-.filtert > div > input {
-  box-sizing: border-box;
-  width: 100%;
-  height: 100%;
-  border: none;
-  background: none;
-  color: #202020;
-  padding: 8px 10px;
-  outline: none;
-  background: #ffffff;
-  border: 1px solid #ebebeb;
-}
-
-.filtert > div > input {
-  padding-right: 40px;
-}
-
-.filtert > div > i {
-  position: absolute;
-  top: 50%;
-  transform: translateY(-50%);
-  right: 10px;
-  cursor: pointer;
-  color: @color;
-}
-
-.scene-layer {
-  min-height: 400px;
-  max-height: 60vh;
-  overflow-y: auto;
-  position: relative;
-  .nodata {
-    position: absolute;
-    left: 50%;
-    top: 40%;
-    transform: translate(-50%, -50%);
-  }
-  .pano-con{
-    background: #fff;
-    padding: 0;
-    > ul {
-      > li{
-        cursor: pointer;
-        margin: 10px 10px 30px 0;
-        .ui-title {
-          > span {
-            color: #202020;
-          }
-        }
-        .typeli,
-        .oper {
-          background: rgba(0, 0, 0, 0.5);
-          .iconfont{
-            color:#fff
-          }
-        }
-      }
-    }
-  }
-}
-
-
-.btns {
-  text-align: center;
-  > a {
-    width: 120px;
-    height: 40px;
-    text-align: center;
-    line-height: 40px;
-    opacity: 1;
-    border-radius: 20px;
-    font-size: 12px;
-    cursor: pointer;
-    display: inline-block;
-    color: @color;
-    margin: 0 10px;
-    &:nth-child(2) {
-      background-color: @color;
-      color: #fff;
-    }
-    &:nth-child(1) {
-      border: 1px solid @color;
-    }
-  }
-  .disable {
-    pointer-events: none !important;
-    opacity: 0.5 !important;
-  }
-}
-</style>

+ 115 - 126
packages/qjkankan-editor/src/components/shared/Combox.vue

@@ -1,145 +1,134 @@
 <template>
-    <div class="com-combox ui-input" :class="{show:showPopup}" @click="show" v-clickoutside="hide">
-        <div class="input">
-            <p v-if="current">{{current.name}}</p>
-        </div>
-        <ul class="ui-input">
-            <li
-                v-for="(item,key) in data"
-                :key="key"
-                @click="onClick(item)"
-                :class="{active:selectedId == item.id}"
-            >
-                <slot :item="item">
-                    <template>
-                        <span>{{item.name}}</span>
-                    </template>
-                </slot>
-            </li>
-        </ul>
-        <a class="iconfont icon_pulldown"></a>
+  <div class="com-combox" :class="{show:showPopup}" @click="show" v-clickoutside="hide">
+    <div class="input">
+      <p v-if="current">{{current.name}}</p>
     </div>
+    <a class="iconfont icon-material_preview_upload_collect"></a>
+    <ul>
+      <li
+        v-for="(item,key) in data"
+        :key="key"
+        @click="onClick(item)"
+        :class="{active:selectedId == item.id}"
+      >
+        <slot :item="item">
+          <template>
+            <span>{{item.name}}</span>
+          </template>
+        </slot>
+      </li>
+    </ul>
+  </div>
 </template>
 <script>
 export default {
-    props: {
-        data: Array,
-        type: {
-            type: String,
-            default: "object"
-        },
-        selectedId: {
-            type: String,
-            default:''
-        }
+  props: {
+    data: Array,
+    type: {
+      type: String,
+      default: "object"
     },
-    data() {
-        return {
-            showPopup: false,
-        };
+    selectedId: {
+      type: String,
+      default:''
+    }
+  },
+  data() {
+    return {
+      showPopup: false,
+    };
+  },
+  computed: {
+    current() {
+      let tmp = this.data.find(item=>{
+         return this.selectedId == item.id
+      })
+      return tmp
+    }
+  },
+  methods: {
+    show() {
+      if (this.showPopup === true) {
+        this.showPopup = false;
+        return;
+      }
+      this.showPopup = true;
     },
-    computed: {
-        current() {
-            let tmp = this.data.find(item=>{
-               return this.selectedId == item.id
-            })
-            return tmp
-        }
+    hide() {
+      this.showPopup = false;
     },
-    methods: {
-        show() {
-            if (this.showPopup === true) {
-                this.showPopup = false;
-                return;
-            }
-            this.showPopup = true;
-        },
-        hide() {
-            this.showPopup = false;
-        },
-        onClick(item) {
-            if (this.selectedId == item.id) {
-                return this.$emit("click", item);
-            }
-            this.$emit("change", item);
-        }
+    onClick(item) {
+      if (this.selectedId == item.id) {
+        return this.$emit("click", item);
+      }
+      this.$emit("change", item);
     }
+  }
 };
 </script>
 <style lang="less" scoped>
 .com-combox {
-    cursor: pointer;
-    position: relative;
-    padding: 5px;
-    &.show {
-        ul {
-            display: block;
-        }
-
-        a {
-            transform: translateY(-50%) rotate(180deg);
-        }
-    }
-    > div {
-        height: 100%;
-        display: flex;
-        align-items: center;
-    }
-    .input p {
-        width: 100%;
-        padding-right: 50px;
-        overflow: hidden;
-        white-space: nowrap;
-        text-overflow: ellipsis;
-        text-align: left;
-    }
+  position: relative;
+  border: 1px solid rgba(151, 151, 151, 0.2);
+  padding: 0 16px;
+  background: #1A1B1D;;
+  border-radius: 2px;
+  height: 36px;
+  cursor: pointer;
+  z-index: 100;
+  &.show {
     ul {
-        display: none;
-        padding: 0;
-        position: absolute;
-        left: -1px;
-        right: -1px;
-        top: 100%;
-        width: auto;
-        height: auto;
-        border-top-left-radius: 0;
-        border-top-right-radius: 0;
-        overflow-x: hidden;
-        overflow-y: auto;
-        max-height: 130px;
-        background: #000;
-        box-shadow: 0 5px 5px rgba(0, 0, 0, 0.3);
-        z-index: 10000;
-
-        li {
-            padding: 5px;
-            display: flex;
-            height: 30px;
-            align-items: center;
-            &.active,
-            &:hover {
-                background: #272729;
-                color: @color;
-            }
-        }
-    }
-    i {
-        font-size: 22px;
-        margin-top: 2px;
-        margin-right: 5px;
-        &.icon_logo {
-            font-size: 17px;
-            margin-top: 0;
-            margin-left: 3px;
-            margin-right: 7px;
-        }
+      display: block;
     }
     a {
-        position: absolute;
-        right: 5px;
-        top: 50%;
-        font-size: 16px;
-        transform: translateY(-50%);
+      transform: translateY(-50%) rotate(180deg);
+    }
+  }
+  > .input {
+    height: 100%;
+    display: flex;
+    align-items: center;
+    .p {
+      width: 100%;
+      padding-right: 50px;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      text-align: left;
+    }
+  }
+  
+  ul {
+    display: none;
+    padding: 0;
+    position: absolute;
+    left: -1px;
+    right: -1px;
+    top: 100%;
+    background: #1A1B1D;
+    border-radius: 0px 0px 2px 2px;
+    border: 1px solid #404040;
+    overflow-x: hidden;
+    overflow-y: auto;
+    max-height: 130px;
+    li {
+      height: 36px;
+      padding: 0 16px;
+      display: flex;
+      align-items: center;
+      &.active,
+      &:hover {
+        background: #252526;
+        color: @color;
+      }
     }
+  }
+  a {
+    position: absolute;
+    right: 16px;
+    top: 50%;
+    font-size: 12px;
+    transform: translateY(-50%);
+  }
 }
 </style>

+ 4 - 2
packages/qjkankan-editor/src/components/shared/Switcher.vue

@@ -8,7 +8,9 @@ export default {
     name: "com-switcher",
     props: {
         name: String,
-        value: Number,
+        value: {
+          required: true,
+        },
         disable: Boolean
     },
     // data() {
@@ -20,7 +22,7 @@ export default {
         onClick() {
             this.$emit("change", Number(!this.value), this.name);
         }
-    }
+    },
 };
 </script>
 <style lang="less" scoped>

+ 0 - 14
packages/qjkankan-editor/src/components/shared/uploads/UploadMultiple.vue

@@ -90,24 +90,10 @@ export default {
       e.target.value = "";
     });
   },
-  beforeDestroy() {
-    // this.clear();
-  },
   methods: {
     click() {
       this.$el.click();
     },
-    clear() {
-      this.dataURL && window.URL.revokeObjectURL(this.dataURL);
-      this.name = null;
-      this.type = null;
-      this.size = null;
-      this.files = null;
-      this.dataURL = null;
-      this.base64 = null;
-      this.poster = null;
-    },
-    upload() {},
   },
 };
 </script>

+ 0 - 416
packages/qjkankan-editor/src/components/tableSelect.vue

@@ -1,416 +0,0 @@
-<template>
-  <div class="select-commodity">
-    <a class="close" @click="$emit('cancle')">+</a>
-    <h3 class="title">{{title}}</h3>
-    <div class="filtert">
-      <div>
-        <input
-          type="text"
-          placeholder="输入关键词"
-          v-model="key"
-          @keyup.enter="isClickSearch = !!key, (paging.current = 1) && $emit('updateList',key)">
-          <i class="iconfont iconsearch" @click="isClickSearch = !!key, (paging.current = 1) && $emit('updateList',key)"></i>
-      </div>
-    </div>
-
-   <template>
-      <div class="table-layer">
-      <table class="list">
-        <tr>
-          <th>
-            <div class="checkbox" v-if="!hideAll">
-              <input
-                type="checkbox"
-                v-model="allSelect"
-                @click="e => selectAll(e.target)">
-              <span></span>
-            </div>
-          </th>
-          <th v-for="(item,i) in tabHeaders" :key="i">{{item.name}}</th>
-        </tr>
-        <tr v-for="(item,i) in list" :key="i">
-          <td>
-            <div class="checkbox">
-              <input
-                type="checkbox"
-                @change="e => selectItem(item, e.target)"
-                :checked="select.some(i => i[primaryKey] === item[primaryKey])"
-              >
-              <span></span>
-            </div>
-          </td>
-          <td v-for="(sub,idx) in tabHeaders" :key="idx">
-            <div v-if="sub.type=='image'" class="list-img">
-              <img :src="item[sub.key]" alt="">
-            </div>
-            <div class="audio" v-else-if="sub.type=='audio'" >
-              <v-audio :vkey="item.id" :idleft="`_${$randomWord(true,8,8)}`" :idright="`_${$randomWord(true,8,8)}`" :myAudioUrl="item[sub.key]"></v-audio>
-          </div>
-            <span class="shenglvhao" v-else>{{item[sub.key]}}</span>
-          </td>
-        </tr>
-        <tr v-if="list.length === 0">
-          <td colspan="10">
-            <div class="nodata">
-              <img :src="$noresult" alt="">
-              <span>{{isClickSearch?'未搜索到结果~':'暂无素材,快去上传吧'}}</span>
-            </div>
-          </td>
-        </tr>
-      </table>
-    </div>
-
-    <div class="paging">
-      <p></p>
-      <Paging
-        v-if="paging.total>0"
-        style="float: right"
-        :paging="paging"
-        @changeCurrent="changeCurrent"
-        />
-    </div>
-   </template>
-
-    <div class="btns">
-      <a @click="$emit('cancle')">取消</a>
-      <a :class="{disable:disable}" @click="$emit('submit', select)" >确定</a>
-    </div>
-  </div>
-</template>
-
-<script>
-import Paging from './paging'
-import vAudio from '@/components/audio'
-
-export default {
-props:{
-  list:{
-    default(){
-      return []
-    },
-    type:Array
-  },
-
-  tabHeader:{
-    default(){
-      return []
-    },
-    type:Array
-  },
- 
-  paging: {
-    default:function () {
-      return {}
-    },
-    type: Object
-  },
-  selected:{
-    default(){
-      return []
-    },
-    type:Array
-  },
-  title:{
-    default:'',
-    type:String
-  },
-  current: {
-    default:''
-  },
-  primaryKey: {
-    default:'id'
-  },
-  hideAll:{
-    type:Boolean,
-    default:false
-  }
-},
-  components:{
-    Paging,
-    vAudio
-  },
-  watch:{
-    select(){
-    }
-  },
-  computed:{
-    disable(){
-      return !this.select.length
-    },
-    tabHeaders(){
-      return this.tabHeader.filter(item=>{
-        return item.key!='detail'
-      })
-    }
-  },
-  data () {
-    return {
-      categs: [],
-      isClickSearch:'',
-      select: [...this.selected],
-      allSelect: false,
-      key:'',
-      tmppaging:{...this.paging}
-    }
-  },
-
-  methods: {
-    changeCurrent(data){
-      this.$emit('changeCurrent',data)
-    },
-    selectAll(isSelect) {
-      this.list.forEach(item => {
-        this.selectItem(item, isSelect)
-      })
-    },
-    selectItem(item, e) {
-      let isSelect = e.checked
-      if (this.hideAll) {
-        if (item.isUse == '1') {
-          e.checked = false
-          return this.$alert({content:'选中素材不能超过600kb'})
-        }
-        this.select = [item]
-      }
-      else{
-        let index = this.select.findIndex(i => i[this.primaryKey] === item[this.primaryKey])
-        if (isSelect) {
-          !~index && this.select.push(item)
-        } else {
-          ~index && this.select.splice(index, 1)
-        }
-      }
-
-    },
-    
-  },
-  mounted() {
-    this.key = ''
-  }
-}
-</script>
-
-<style lang="less" scoped>
-::-webkit-scrollbar-track {
-    box-shadow: inset 0 0 5px rgb(0 0 0 / 20%);
-    border-radius: 4px;
-    background: #fff;
-}
-.shenglvhao{
-  text-overflow: ellipsis;
-  overflow: hidden;
-  white-space: nowrap;
-  max-width: 200px;
-  display: inline-block;
-}
-.select-commodity {
-  position: absolute;
-  z-index: 3;
-  left: 50%;
-  top: 50%;
-  transform: translateX(-50%) translateY(-50%);
-  color: #202020;
-  background: #FFFFFF;
-  max-width: 960px;
-  width: 100%;
-  border-radius: 6px;
-}
-
-.select-commodity > * {
-  padding: 15px;
-}
-
-.title {
-  font-size: 16px;
-  line-height: 20px;
-  font-weight: 400;
-  margin: 0;
-  font-weight: bold;
-  border-bottom: 1px solid rgba(255,255,255,0.3);
-}
-
-.close {
-  position: absolute;
-  right: -8px;
-  top: -15px;
-  font-size: 25px;
-  color: #909090;
-  transform: rotate(45deg);
-  cursor: pointer;
-}
-
-.filtert {
-  padding: 15px;
-}
-
-.filtert > div {
-  width: 210px;
-  height: 34px;
-  background: rgba(22,26,26,1);
-  border-radius: 2px;
-  display: inline-block;
-  margin-right: 10px;
-  position: relative;
-  vertical-align: middle;
-}
-
-.filtert > div > select,
-.filtert > div > input {
-  box-sizing: border-box;
-  width: 100%;
-  height: 100%;
-  border: none;
-  background: none;
-  color: #202020;
-  padding: 8px 10px;
-  outline: none;
-  background: #FFFFFF;
-  border: 1px solid #EBEBEB;
-}
-
-.filtert > div > input {
-  padding-right: 40px;
-}
-
-.filtert > div > i {
-  position: absolute;
-  top: 50%;
-  transform: translateY(-50%);
-  right: 10px;
-  cursor: pointer;
-  color:@color;
-}
-
-.scene-layer {
-  min-height: 400px;
-  max-height: 60vh;
-  overflow-y: auto;
-  position: relative;
-  .nodata{
-    position: absolute;
-    left: 50%;
-    top: 50%;
-    transform: translate(-50%,-50%);
-  }
-}
-
-.table-layer {
-  min-height: 400px;
-  max-height: 60vh;
-  overflow-y: auto;
-}
-
-
-.list {
-  border-collapse: collapse;
-  width: 100%;
-}
-
-.list td,
-.list th {
-  font-size:14px;
-  line-height:20px;
-  text-align: center;
-  padding: 10px 0;
-  color: #909090;
-  border-bottom: 1px solid #EBEBEB;
-}
-
-.list th {
-  font-weight: bold;
-  color: #202020;
-}
-
-
-.list-img {
-  height: 40px;
-  line-height: 40px;
-  position: relative;
-}
-
-.list-img > img {
-  width: 40px;
-  height: 40px;
-}
-
-.checkbox {
-  position: relative;
-  width:14px;
-  height:14px;
-  border-radius:2px;
-}
-
-.checkbox > input,
-.checkbox > span {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  left: 0;
-  top: 0;
-}
-
-.checkbox > input {
-  z-index: 1;
-  opacity: 0;
-  cursor: pointer;
-}
-
-.checkbox > span {
-  z-index: 2;
-  background:#fff;
-  border:1px solid #ccc;
-  pointer-events: none;
-}
-
-.checkbox > input:checked + span {
-  background:#fff;
-  border:1px solid #0076F6;
-  background:@color url(/static/img/g.png) no-repeat center center;
-}
-
-.checkbox > input:disabled {
-  cursor: not-allowed;
-}
-
-.checkbox > input:disabled + span {
-  background:#CCCCCC;
-  background:rgba(0,200,175,0.3) no-repeat center center;
-}
-
-.paging {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  p {
-    font-size: 12px;
-  }
-}
-
-.btns {
-  text-align: center;
-  > a {
-    width:120px;
-    height:40px;
-    text-align: center;
-    line-height: 40px;
-    opacity:1;
-    border-radius:20px;
-    font-size:12px;
-    cursor: pointer;
-    display: inline-block;
-    color: @color;
-    margin: 0 10px;
-    &:nth-child(2) {
-      background-color: @color;
-      color: #fff;
-    }
-    &:nth-child(1) {
-      border:1px solid @color;
-    }
-  }
-  .disable{
-    pointer-events: none!important;
-    opacity: 0.5!important;
-  }
-}
-</style>

+ 1 - 1
packages/qjkankan-editor/src/mixins/v-clickoutside.js

@@ -1,5 +1,5 @@
 import Vue from "vue";
-import { on } from "./dom";
+import { on } from "../mixins/dom";
 
 const nodeList = [];
 const ctx = "@@clickoutsideContext";

packages/qjkankan-editor/src/mixins/v-clickwindow.js → packages/qjkankan-editor/src/directives/v-clickwindow.js


+ 0 - 4
packages/qjkankan-editor/src/framework/EditorHead.vue

@@ -126,13 +126,9 @@ export default {
         this.info.icon = this.catalogTopology[0].children[0].children[0].icon
       }
 
-      // todo: 干啥呢?
       if (this.info.firstScene) {
         this.info.firstScene = this.info.scenes.find(item=>item.sceneCode==this.info.firstScene.sceneCode)
       }
-
-      // todo: 干啥呢?
-      this.$store.commit("SetInfo", this.info);
     },
 
     onSave() {

+ 0 - 10
packages/qjkankan-editor/src/framework/Head.vue

@@ -69,16 +69,6 @@ export default {
         });
         return false;
       }
-      // if (this.info.scenes.length <= 0 && this.isShow) {
-      //   this.$alert({
-      //     content: "至少添加一个场景才保存/预览,请前往“场景导航”添加",
-      //     forceOK: true,
-      //     ok: () => {
-      //       this.$router.push({ path: "/information" });
-      //     },
-      //   });
-      //   return false;
-      // }
       return true;
     },
     onView() {

+ 0 - 89
packages/qjkankan-editor/src/framework/SettingPC.vue

@@ -1,89 +0,0 @@
-<template>
-  <div class="pc-setting" app-border dir-left>
-    <slot></slot>
-  </div>
-</template>
-<script>
-export default {
-  name: "pc-setting",
-  props: {
-    scrollbar: {
-      type: Boolean,
-      default: true
-    }
-  },
-  mounted() {
-    // 添加滚动条
-    this.scrollbar &&
-      this.$nextTick(() =>
-        $(this.$el).mCustomScrollbar({
-          axis: "y",
-          scrollInertia: 200,
-          autoHideScrollbar: false
-        })
-      );
-  },
-  activated() {
-    this.scrollbar &&
-      this.$nextTick(() => {
-        $(this.$el).mCustomScrollbar("update");
-        $(this.$el).mCustomScrollbar("scrollTo", "top", 0);
-      });
-  }
-};
-</script>
-<style lang="less" scoped>
-.pc-setting {
-  // width: 100%;
-  .view-setting {
-    padding: 10px;
-    > li {
-      padding: 10px;
-      font-size: 14px;
-      .title {
-        display: flex;
-        justify-content: space-between;
-        margin-bottom: 10px;
-        label {
-          color: #ababab;
-          font-size: 12px;
-        }
-      }
-      .remark {
-        display: block;
-        white-space: normal;
-        font-size: 12px;
-        line-height: 1.5;
-        color: #ababab;
-      }
-    }
-    .title {
-        display: flex;
-        justify-content: space-between;
-        margin-bottom: 10px;
-        label {
-          color: #ababab;
-          font-size: 12px;
-        }
-      }
-      .remark {
-        display: block;
-        white-space: normal;
-        font-size: 12px;
-        line-height: 1.5;
-        color: #ababab;
-      }
-  }
-
-  /deep/ .vue-slider {
-    padding: 7px 10px !important;
-  }
-  /deep/ .vue-slider-process {
-    background-color: @color;
-  }
-  /deep/ .vue-slider-dot-tooltip-inner {
-    border-color: @color;
-    background-color: @color;
-  }
-}
-</style>

+ 0 - 1
packages/qjkankan-editor/src/framework/Toolbar.vue

@@ -65,7 +65,6 @@ export default {
   computed: {
     ...mapGetters({
       info: "info",
-      backupInfo: "backupInfo"
     })
   },
   methods: {

+ 2 - 6
packages/qjkankan-editor/src/mixins/index.js

@@ -4,8 +4,8 @@ import config from "../config";
 import bus from "../utils/eventbus.js";
 import { Alert, Confirm, Tips } from "../components/shared/message";
 
-import clickoutside from "./v-clickoutside";
-import clickwindow from "./v-clickwindow";
+import clickoutside from "@/directives/v-clickoutside";
+import clickwindow from "@/directives/v-clickwindow";
 import * as api from "../api";
 
 import { Message, InfiniteScroll } from 'element-ui'
@@ -114,12 +114,8 @@ Vue.prototype.$nameSort = {
 
 Vue.prototype.$scrollbars = [];
 
-// todo: 无用了
-let SettingPanel = require("@/framework/SettingPC").default;
-
 Vue.mixin({
   components: {
-    SettingPanel,
   },
   directives: {
     clickoutside: clickoutside,

+ 1 - 1
packages/qjkankan-editor/src/pages/Edit.vue

@@ -44,5 +44,5 @@ img {
   outline: 0;
 }
 </style>
-<style lang="less" src="@/assets/style/style.pc.edit.less"></style>
+<style lang="less" src="@/assets/style/style.pc.editor.less"></style>
 <style src="@/assets/fonts/iconfont.css"></style>

+ 2 - 0
packages/qjkankan-editor/src/pages/edit.js

@@ -8,6 +8,8 @@ import Viewer from 'v-viewer'
 import '@/directives/vTitleInEditor.js'
 import '@/directives/vTooltipInEditor.js'
 
+console.log('v0801.0834');
+
 Vue.use(Viewer,{
   defaultOptions: {
     toolbar: 0,

+ 43 - 56
packages/qjkankan-editor/src/utils/request.js

@@ -21,53 +21,46 @@ const noop = function() {};
 // 请求回调队列
 let postQueue = [];
 
-// 这个看起来过时了
-export const statusCode = {
-  NEXT: -999, //继续执行
+const statusCode = {
+  NEXT: '__not_important__', //继续执行
   SUCCESS: 0, //成功
-  EXCEPTION: -1, //异常错误
+
+  FAILURE_CODE_3001: 3001, // "对象不存在"
   FAILURE_CODE_3002: 3002, //请至少保留一个场景。
   FAILURE_CODE_3003: 3003, //文件名称不允许超过50个字符
   FAILURE_CODE_3005: 3005, //不是该用户作品
   FAILURE_CODE_3006: 3006, //作品已被删除,无法编辑
   FAILURE_CODE_3007: 3007, //素材已被引用,无法删除。
-  FAILURE_CODE_5003: 5003, //不支持此图片
-  FAILURE_CODE_7005: 7005, //审核中不能编辑
-  FAILURE_CODE_7006: 7006, //已审核不能编辑
-  FAILURE_CODE_5001: 5001, //token失效
-  FAILURE_CODE_5004: 5004, // 密码错误
-};
 
-/* 伟浩给的新版本错误码
-FAILURE_SYS_3001(3001, "对象不存在"),
 
-// 301X -> 权限问题类
-FAILURE_SYS_3010(3010, "Token为空"),
-FAILURE_SYS_3011(3011, "没有操作权限"),
+  // 301X -> 权限问题类
+  FAILURE_CODE_3010: 3010, // "Token为空"
+  FAILURE_CODE_3011: 3011, // "没有操作权限"
 
-// 302X -> 文件类
-FAILURE_CODE_3020(3020, "空文件"),
-FAILURE_CODE_3021(3021, "非法文件"),
-FAILURE_CODE_3022(3022, "上传文件超过最大值"),
-FAILURE_CODE_3023(3023, "非法格式"),
-FAILURE_CODE_3024(3024, "存储空间已满"),
-FAILURE_CODE_3025(3025, "上传失败"),
+  // 302X -> 文件类
+  FAILURE_CODE_3020: 3020, // "空文件"
+  FAILURE_CODE_3021: 3021, // "非法文件"
+  FAILURE_CODE_3022: 3022, // "上传文件超过最大值"
+  FAILURE_CODE_3023: 3023, // "非法格式"
+  FAILURE_CODE_3024: 3024, // "存储空间已满"
+  FAILURE_CODE_3025: 3025, // "上传失败"
 
+  // 31XX -> 自定义异常
+  FAILURE_CODE_3101: 3101, // "素材已经被引用, 不能删除"
+  FAILURE_CODE_3102: 3102, // "计算中的场景不能删除"
+  FAILURE_CODE_3103: 3103, // "服务器someData.json文件不存在"
 
-// 31XX -> 自定义异常
-FAILURE_CODE_3101(3101, "素材已经被引用, 不能删除"),
-FAILURE_CODE_3102(3102, "计算中的场景不能删除"),
-FAILURE_CODE_3103(3103, "服务器someData.json文件不存在"),
+  // 32XX -> 请求第三方API错误
+  FAILURE_CODE_3200: 3200, // "请求第三方API失败"
+  FAILURE_CODE_3201: 3201, // "请求第三方API返回失败"
 
-// 32XX -> 请求第三方API错误
-FAILURE_API_3200(3200, "请求第三方API失败"),
-FAILURE_API_3201(3201, "请求第三方API返回失败"),
-*/
+  FAILURE_CODE_5001: 5001, //token失效
+  FAILURE_CODE_5003: 5003, //不支持此图片
+  FAILURE_CODE_5004: 5004, // 密码错误
 
-/**
- * 已知错误提示集合
- */
-// const defineErrorCode = []
+  FAILURE_CODE_7005: 7005, //审核中不能编辑
+  FAILURE_CODE_7006: 7006, //已审核不能编辑
+};
 
 let __showNetworkError = false;
 
@@ -142,35 +135,25 @@ export function statusCodesHandler(result, callback) {
     });
   }
 
-  if (result.code == statusCode.FAILURE_CODE_3007) {
-    return $alert({ content: "素材已被引用,无法删除。" });
-  }
-
   if (result.code == statusCode.FAILURE_CODE_3002) {
     return $alert({ content: "请至少保留一个场景。" });
   }
 
-  if (result.code == statusCode.FAILURE_CODE_3006) {
-    return $alert({ content: "作品已被删除,无法编辑" });
+  if (result.code == statusCode.FAILURE_CODE_3003) {
+    return $alert({ content: '文件名称不允许超过50个字符' })
   }
 
   if (result.code == statusCode.FAILURE_CODE_3005) {
+    return $alert({ content: "作品已被删除,无法编辑" });
     return;
   }
-
-  if (result.code == statusCode.FAILURE_CODE_3003) {
-    return statusCode.FILE;
-    // return $alert({ content: '文件名称不允许超过50个字符' })
-  }
-
-  if (result.code == statusCode.FAILURE_CODE_5003) {
-    return statusCode.FILE;
-    // return $alert({ content: '不支持此图片' })
+  
+  if (result.code == statusCode.FAILURE_CODE_3006) {
+    return $alert({ content: "作品已被删除,无法编辑" });
   }
 
-  if (result.code == statusCode.FAILURE_CODE_5004) {
-          return vue.$msg.error("密码错误");
-          // return vue.({ content: "密码错误" });
+  if (result.code == statusCode.FAILURE_CODE_3007) {
+    return $alert({ content: "素材已被引用,无法删除。" });
   }
 
   if (result.code == statusCode.FAILURE_CODE_5001) {
@@ -178,6 +161,14 @@ export function statusCodesHandler(result, callback) {
     return showLoginTips();
   }
 
+  if (result.code == statusCode.FAILURE_CODE_5003) {
+    return $alert({ content: '不支持此图片' })
+  }
+
+  if (result.code == statusCode.FAILURE_CODE_5004) {
+    return vue.$msg.error("密码错误");
+  }
+
   if (result.code != statusCode.SUCCESS) {
     return $alert({ content: `${result.msg}` });
   }
@@ -237,10 +228,6 @@ export const http = {
           return;
         }
 
-        if (flag === statusCode.FILE) { // 并没有这个值
-          done(result);
-        }
-
         if (flag === statusCode.NEXT) {
           done(result, result.code == 0);
         }

+ 4 - 0
packages/qjkankan-editor/src/views/base/backgroundMusicSettings.vue

@@ -103,6 +103,9 @@ export default {
     color: #0076F6;
     font-size: 14px;
     cursor: pointer;
+    &:hover {
+      border-color: @color;
+    }
     i {
       font-size: 14px;
     }
@@ -120,6 +123,7 @@ export default {
     position: relative;
     &:hover {
       color: #0076F6;
+      border-color: @color;
       > .audio-control {
         display: inline-block;
       }

+ 4 - 0
packages/qjkankan-editor/src/views/explanation/explanationSettings.vue

@@ -110,6 +110,9 @@ export default {
   > button {
     width: 100%;
     margin-top: 16px;
+    &:hover {
+      border-color: @color;
+    }
     i {
       font-size: 14px;
     }
@@ -127,6 +130,7 @@ export default {
     position: relative;
     &:hover {
       color: #0076F6;
+      border-color: @color;
       > .audio-control {
         display: inline-block;
       }

+ 0 - 155
packages/qjkankan-editor/src/views/hotspot/ConfirmPanel.vue

@@ -1,155 +0,0 @@
-<template>
-    <transition
-        appear
-        name="custom-classes-transition"
-        enter-active-class="animated slideInRight speed"
-        leave-active-class="animated slideOutRight speed"
-    >
-        <div class="hots-panel" v-show="show">
-            <div class="ui-between header" app-border dir-bottom>
-                <span>{{$t('modules.hotspot.add')}}</span>
-                <i class="iconfont icon_close" @click="cancel(false)"></i>
-            </div>
-            <div class="content">
-                <div>
-                    <ul>
-                        <li app-border dir-bottom>
-                            <div class="title">{{$t('modules.hotspot.location')}}</div>
-                            <div style="margin: 15px 0;">
-                                <button class="ui-button submit block" :class="{'disable':$store.state.hotspot.canAddTag==false}" @click="confirm">{{$t('modules.hotspot.location_confirm')}}</button>
-                            </div>
-                            <div class="ui-between remark">{{$t('modules.hotspot.location_tips')}}</div>
-                        </li>
-                    </ul>
-                </div>
-            </div>
-            <!-- <div class="ui-between footer" app-border dir-top>
-                <button class="ui-button submit" @click="save">完成</button>
-                <button class="ui-button cancel" @click="cancel">取消</button>
-            </div>-->
-        </div>
-    </transition>
-</template>
-<script>
-
-export default {
-    props: {
-        show: Boolean
-    },
-    data() {
-        return {};
-    },
-    watch:{
-        show(){
-            if(this.show){
-                this.$store.commit("hotspot/SetStyle", null);
-            }
-        }
-    },
-    methods: {
-        confirm() {
-            this.cancel(true);
-        },
-        cancel(isConfirm) {
-            if (!isConfirm) {
-                this.$bus.emit("hotspot/Tag/Cancel");
-            }
-            this.$store.commit('hotspot/SetCanAddTag',false)
-            this.$emit("close", isConfirm);
-        }
-    }
-};
-</script>
-<style lang="less" scoped>
-.hots-panel {
-    position: fixed;
-    right: 0;
-    top: 0;
-    height: 100%;
-    width: 236px;
-    background: rgba(38, 39, 41, 1);
-    box-shadow: 0px 0px 20px #090909;
-    z-index: 10;
-    display: flex;
-    flex-direction: column;
-    .header {
-        height: 51px;
-        padding: 0 10px;
-        display: flex;
-        .icon_close {
-            cursor: pointer;
-        }
-    }
-    .footer {
-        padding: 15px;
-        .ui-button {
-            width: 45%;
-        }
-    }
-    .content {
-        display: flex;
-        flex: 1;
-        overflow: hidden;
-        > div {
-            width: 100%;
-            height: 100%;
-        }
-        ul {
-            width: 100%;
-        }
-        li {
-            padding: 10px;
-            > div {
-                margin-bottom: 15px;
-                &:last-child {
-                    margin-bottom: 0;
-                }
-                &.title {
-                    margin-bottom: 10px;
-                }
-                label {
-                    color: #ababab;
-                    font-size: 12px;
-                }
-            }
-            &:last-child {
-                border: none;
-                &::after {
-                    display: none;
-                }
-            }
-            .link-button {
-                display: flex;
-                justify-content: space-between;
-                button {
-                    width: 45%;
-                }
-            }
-        }
-        .styles {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            li {
-                cursor: pointer;
-                width: 38px;
-                height: 38px;
-                background-position: center center;
-                background-size: 80%;
-                background-repeat: no-repeat;
-                border: solid 2px #262729;
-                &.active {
-                    border-color: @color;
-                }
-            }
-        }
-        .remark {
-            color: #ababab;
-            line-height: 1.5;
-            letter-spacing: 0.1px;
-            white-space: pre-wrap;
-            font-size: 12px;
-        }
-    }
-}
-</style>

+ 210 - 451
packages/qjkankan-editor/src/views/hotspot/EditPanel.vue

@@ -6,122 +6,94 @@
     leave-active-class="animated slideOutRight speed"
   >
     <div class="hots-panel" v-show="show">
-      <div class="ui-between header" app-border dir-bottom>
+      <div class="ui-between header">
         <span>{{editTitle}}热点</span>
         <i class="iconfont icon_close" @click="confirmCancel"></i>
       </div>
       <div class="content">
-        <div>
-          <ul>
-            <li app-border dir-bottom>
-              <div class="ui-remark">请点击热点图标,将鼠标移至全景图进行标记。</div>
-              <div class="medias-list">
-                  <ul>
-                      <li
-                          v-for="item in mediaList"
-                          :key="item.name"
-                          :class="{active:mediaType==item.name}"
-                      >
-                          <span></span>
-                          <div>{{item.name}}</div>
-                      </li>
-                  </ul>
-              </div>
-              <div style="margin-bottom: 0">
-                <ul class="styles">
-                  <li
-                    :class="{ active: item.id == hotspot.icontype }"
-                    v-for="(item,i) in hotStyle"
-                    @click="addhotspot(item)"
-                    :key="i"
-                  >
-                    <img :src="item.thumb" alt="">
-                  </li>
-                </ul>
-              </div>
-              <div class="bars">
-                  <RangeItem :value="rang" @input="onRangeChange" />
-              </div>
-            </li>
-            <li app-border dir-bottom>
-              <div class="ui-between title">标题
-                  <div
-                    class="checkbox"
-                    @click="hotspot.visible=!hotspot.visible"
-                    :class="{checked:hotspot.visible}"
+        <div class="icon-setting">
+          <div class="icon-setting-title">热点图标</div>
+          <div class="remark">选择图标</div>
+          <div class="icon-list">
+            <div class="margin-handler-layer">
+              <ul>
+                <li
+                  :class="{ active: item.id == hotspot.icontype }"
+                  v-for="(item,i) in hotStyle"
+                  @click="addhotspot(item)"
+                  :key="i"
                 >
-                    <i class="iconfont icon_checkbox"></i>
-                    &nbsp;显示标题
-                </div>
-              </div>
-              <div>
-                <input
-                  type="text"
-                  class="ui-input"
-                  placeholder="请填写标题限50字"
-                  :maxlength="50"
-                  v-model="hotspot.hotspotTitle"
-                />
-              </div>
-              <div class="ui-between title">字号</div>
-              <div class="medias-list">
-                  <ul>
-                      <li
-                          v-for="item in fontSizeList"
-                          :key="item.name"
-                          @click="hotspot.fontSize = item.name"
-                          :class="{active:hotspot.fontSize==item.name}"
-                      >
-                          <span></span>
-                          <div>{{item.name}}</div>
-                      </li>
-                  </ul>
-              </div>
-            </li>
-            <li>
-              <div class="ui-between title">效果</div>
-              <combox
-                :data="hotSpotTypeList"
-                :selected-id="hotspot.hotspotType"
-                @change="onhotSpotTypeChange"
-              ></combox>
-              <component 
-              @sceneSelect="handleSceneSelect" 
-              :scene="hotspot.secne"
-
-              @imageChange="data=>{hotspot.image=data}" 
-              :image="hotspot.image"
-
-              @linkChange="data=>{hotspot.hyperlink=data}" 
-              :link="hotspot.hyperlink"
-
-              @textChange="data=>{hotspot.textarea=data}" 
-              :textarea="hotspot.textarea"
-
-              @audioChange="data=>{hotspot.audio=data}" 
-              :audio="hotspot.audio"
-
-               @videoChange="data=>{hotspot.video=data}" 
-              :video="hotspot.video"
-              
-              :is="component"
-              ></component>
-            </li>
-          </ul>
+                  <img :src="item.thumb" alt="">
+                </li>
+              </ul>
+            </div>
+          </div>
+          <div class="bars">
+            <RangeItem :value="rang" @input="onRangeChange" />
+          </div>
+        </div>
+        <div class="title-setting">
+          <div class="title-setting-title">标题设置</div>
+          <div class="switch-wrapper">
+            <span class="label">是否显示标题</span>
+            <Switcher :value="hotspot.visible" @change="hotspot.visible = !hotspot.visible"></Switcher>
+          </div>
+          <div class="title-input-wrapper">
+            <input
+              v-model.trim="hotspot.hotspotTitle"
+              type="text"
+              maxlength="15"
+              placeholder="请输入标题,限15字"
+            />
+            <span class="count">{{hotspot.hotspotTitle.length}}/15</span>
+          </div>
+        </div>
+        <div class="effect-setting">
+          <div class="effect-setting-title">效果设置</div>
+          <combox
+            class="combox"
+            :data="hotSpotTypeList"
+            :selected-id="hotspot.hotspotType"
+            @change="onhotSpotTypeChange"
+          ></combox>
+          <component
+            class="effect-setting-component"
+          
+            @sceneSelect="handleSceneSelect" 
+            :scene="hotspot.secne"
+
+            @imageChange="data=>{hotspot.image=data}" 
+            :image="hotspot.image"
+
+            @linkChange="data=>{hotspot.hyperlink=data}" 
+            :link="hotspot.hyperlink"
+
+            @textChange="data=>{hotspot.textarea=data}" 
+            :textarea="hotspot.textarea"
+
+            @audioChange="data=>{hotspot.audio=data}" 
+            :audio="hotspot.audio"
+
+            @videoChange="data=>{hotspot.video=data}" 
+            :video="hotspot.video"
+            
+            :is="effectSettingComponent"
+          />
         </div>
       </div>
       <div class="ui-between footer" app-border dir-top>
+        <button class="ui-button deepcancel"  :class="{disable: false}" @click="confirmCancel">取消</button>
         <button class="ui-button submit"  :class="{disable: false}" @click="save">完成</button>
       </div>
     </div>
   </transition>
 </template>
 
-
 <script>
-import RangeItem from "@/components/rangeItem";
+import RangeItem from "@/components/rangeItem/index.vue";
 import Combox from "@/components/shared/Combox";
 import { mapGetters } from "vuex";
+import Switcher from "@/components/shared/Switcher.vue";
 
 let HTMap = {
   scene:{
@@ -160,11 +132,9 @@ export default {
   props: ['show','data','editTitle'],
   components:{
     RangeItem,
-    Combox
+    Combox,
+    Switcher,
   },
-
-  
-
   data(){
     let cdn = this.$config.getStaticResource('/panoassets/images/hotspot/icon/')
     let hotStyle = []
@@ -176,8 +146,6 @@ export default {
         thumb:cdn+`img_doticon_${String(i+1).padStart(2, '0')}.svg`
       }
     }
-
-   
     return {
       canSave:false,
       hotSpotTypeList:[
@@ -206,27 +174,6 @@ export default {
           name:'视频'
         }
       ],
-      mediaList: [
-          {
-              name: "默认",
-              icon: "iconphotoview",
-          }
-      ],
-      fontSizeList:[
-          {
-              name: "12",
-              icon: "iconphotoview",
-          },
-          {
-              name: "14",
-              icon: "iconvideo_view",
-          },
-          {
-              name: "16",
-              icon: "iconsoundview",
-          }
-      ],
-      mediaType:'默认',
       hotStyle,
       rang: {
         label: '图标大小',
@@ -234,7 +181,7 @@ export default {
         gradient: 0.5,
         value: 1,
         min: 0.5,
-        max: 2
+        max: 2,
       },
       selectItem:'',
       styIcon:'',
@@ -298,7 +245,7 @@ export default {
       hotspot:'hotspot',
       backupHotSpot:'backupHotSpot'
     }),
-    component(){
+    effectSettingComponent(){
       let tmp = this.hotspot.hotspotType
       return () => import(`./hotspotType/${tmp}.vue`);
     },
@@ -329,6 +276,25 @@ export default {
     onRangeChange(data) {
       this.rang = { ...this.rang, value: data.value }
       this.hotspot.size = data.value
+      switch (data.value) {
+        case 0.5:
+          console.log(0.5);
+          this.hotspot.fontSize = 12
+          break;
+        case 1:
+          console.log(1);
+          this.hotspot.fontSize = 14
+          break;
+        case 1.5:
+          this.hotspot.fontSize = 17
+          break;
+        case 2:
+          this.hotspot.fontSize = 20
+          break;
+        default:
+          console.error('unexpected range value: ', data.value);
+          break;
+      }
     },
     listerFn(data){
       this.selectItem = {
@@ -409,356 +375,149 @@ export default {
 };
 </script>
 <style lang="less" scoped>
-.icon_checkbox {
-    font-size: 14px;
-    &::before {
-        content: "\e667";
-    }
-}
-
-
-.checkbox {
-    cursor: pointer;
-    &.checked {
-        color: @color;
-        .icon_checkbox::before {
-            content: "\e671";
-        }
-    }
-}
-
 .hots-panel {
-  position: fixed;
-  right: 0;
-  top: 0;
-  height: 100%;
-  width: 236px;
-  background: rgba(38, 39, 41, 1);
-  box-shadow: 0px 0px 20px #090909;
+  background: #1A1B1D;
   z-index: 10;
+  
   display: flex;
   flex-direction: column;
+  
   .header {
-    height: 51px;
-    padding: 0 10px;
+    padding: 20px;
     display: flex;
+    font-size: 18px;
+    color: #fff;
+    flex: 0 0 auto;
     .icon_close {
+      color: rgba(255, 255, 255, 0.6);
       cursor: pointer;
     }
   }
-  .footer {
-    padding: 15px;
-    .ui-button {
-      width: 100%;
-    }
-  }
   .content {
-    display: flex;
-    flex: 1;
-    overflow: hidden;
-    > div {
-      width: 100%;
-      height: 100%;
-      overflow-y: auto;
-    }
-    ul {
-      width: 100%;
-      &.lock {
-        li {
-          pointer-events: none;
-          opacity: 0.5;
-        }
-        li.position {
-          pointer-events: auto;
-          opacity: 1;
-        }
-      }
-    }
-    li {
-      padding: 10px;
-      > div {
-        margin-bottom: 15px;
-        &:last-child {
-          margin-bottom: 0;
-        }
-        &.title {
-          margin-bottom: 10px;
-        }
-        label {
-          color: #ababab;
-          font-size: 12px;
-        }
+    padding: 20px 20px 14px 20px;
+    background: #252526;
+    flex: 1 0 1px;
+    overflow: auto;
+    .icon-setting {
+      .icon-setting-title {
+        font-size: 18px;
+        color: #FFFFFF;
       }
-      &:last-child {
-        border: none;
-        &::after {
-          display: none;
-        }
+      .remark {
+        margin-top: 16px;
+        font-size: 14px;
+        color: #ababab;
       }
-      .link-button {
-        display: flex;
-        justify-content: space-between;
-        button {
-          width: 45%;
-        }
-      }
-    }
-    .medias-list {
-            position: relative;
-            ul {
-                margin-bottom: 10px;
-                display: flex;
-                justify-content: space-between;
-            }
+      .icon-list {
+        margin-top: 16px;
+        height: 158px;
+        background: #1A1B1D;
+        border-radius: 2px;
+        border: 1px solid #404040;
+        overflow: auto;
+        padding: 4px;
+        > .margin-handler-layer {
+          overflow: hidden;
+          ul {
+            display: flex;
+            align-items: center;
+            flex-wrap: wrap;
+            margin-right: -17px;
+            margin-bottom: -17px;
             li {
-                position: relative;
-                // cursor: pointer;
-                padding: 0;
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                span {
-                    width: 14px;
-                    height: 14px;
-                    background-color: #fff;
-                    border: solid 3px #fff;
-                    border-radius: 50%;
-                }
-                i {
-                    font-size: 23px;
-                    margin-left: 4px;
-                    color: rgba(255, 255, 255, 0.5);
-                }
-                em {
-                    display: none;
-                    position: absolute;
-                    top: -8px;
-                    left: 50%;
-                    width: 0;
-                    height: 0;
-                    border-style: solid;
-                    border-width: 8px;
-                    border-color: #000 transparent transparent;
-                }
-
-                div {
-                    padding: 5px;
-                    border-radius: 4px;
-                    font-size: 14px;
-                }
-
-                &.active {
-                    span {
-                        background-color: @color;
-                    }
-                    i {
-                        color: @color;
-                    }
-                }
-                &:hover {
-                    em,
-                    div {
-                        display: block;
-                    }
-                }
-            }
-        }
-    .medias {
-        height: 105px; 
-        width: 210px;
-        position: relative;
-        background: #161A1A;
-        cursor: pointer;
-        border: 1px solid #555A5A;
-        >img{
-          width: 100%;
-          height: 100%;
-        }
-        .btn-push{
-            position: absolute;
-            top: 50%;
-            left: 50%;
-            transform: translate(-50%,-50%);
-            text-align: center;
-            color: @color;
-            >i{
-                font-size: 20px;
-            }
-            >span{
-                display: block;
+              cursor: pointer;
+              margin-right: 17px;
+              margin-bottom: 17px;
+              width: 38px;
+              height: 38px;
+              border: solid 2px transparent;
+              border-radius: 4px;
+              display: flex;
+              align-items: center;
+              justify-content: center;
+              &.active {
+                border-color: #0076f6;
+              }
             }
+          }
         }
+      }
+      .bars{
+        margin-top: 16px;
+      }
     }
-    .styles {
-      display: flex;
-      align-items: center;
-      flex-wrap: wrap;
-      min-width: 216px;
-      li {
-        position: relative;
-        cursor: pointer;
-        padding: 0;
-        margin-left: 20px;
-        margin-top: 20px;
+    .title-setting {
+      margin-top: 24px;
+      .title-setting-title {
+        font-size: 18px;
+        color: #FFFFFF;
+      }
+      .switch-wrapper {
         display: flex;
-        width: 38px;
-        height: 38px;
-        border: solid 2px transparent;
         align-items: center;
-        justify-content: center;
-        &:first-child {
-          margin-left: 0;
+        justify-content: space-between;
+        margin-top: 18px;
+        .label {
+          color: rgba(255, 255, 255, 0.6);
+          font-size: 14px;
         }
-        &:nth-of-type(4n+1) {
-          margin-left: 0;
+      }
+      > .title-input-wrapper {
+        position: relative;
+        border: 1px solid rgba(151, 151, 151, 0.2);
+        padding: 0 16px;
+        background: #1A1B1D;
+        border-radius: 2px;
+        height: 36px;
+        width: 100%;
+        margin-top: 18px;
+        &:focus-within {
+          border-color: #0076F6;
         }
-
-        &:nth-of-type(-n+4) {
-          margin-top: 0;
+        > input {
+          border: none;
+          background: transparent;
+          outline: none;
+          height: 100%;
+          width: calc(100% - 50px);
+          padding: 0;
+          color: #fff;
+          letter-spacing: 1px;
+          font-size: 14px;
         }
-        
-        > span {
+        > .count {
           position: absolute;
-          left: 0;
-          right: 0;
-          bottom: -20px;
-          text-align: center;
-          font-size: 12px;
-        }
-        >i{
-            font-size: 32px;
-        }
-        >img{
-          width: 34px;
-          height: 34px;
-        }
-        &.active {
-          border-color: @color;
-          > span {
-            color: @color;
-          }
-        }
-        .hot-style {
-          margin: 0;
-          position: relative;
-          width: 28px;
-          height: 28px;
-          &.hot-style-image {
-            background-position: center center;
-            background-repeat: no-repeat;
-            background-size: contain;
-            background-repeat: no-repeat;
-            &:hover {
-              a {
-                display: block;
-              }
-            }
-            a {
-              display: none;
-              position: absolute;
-              right: 0;
-              top: 0;
-              width: 16px;
-              height: 16px;
-              line-height: 16px;
-              text-align: center;
-              background-color: #c77a7a;
-              border-radius: 50%;
-              transform: translate(50%, -50%);
-              &:hover {
-                background-color: #e85353;
-              }
-              i {
-                font-size: 12px;
-              }
-            }
-          }
-          &.hot-style-default {
-            border-radius: 50%;
-            border: solid 1px rgba(255, 255, 255, 0.1);
-            em {
-              position: absolute;
-              left: 50%;
-              top: 50%;
-              margin-left: -5px;
-              margin-top: -5px;
-              width: 10px;
-              height: 10px;
-              border: solid 0.5px #fff;
-              background-color: @color;
-              border-radius: 50%;
-            }
-            ul {
-              margin: 0;
-              cursor: default;
-              position: fixed;
-              right: 236px;
-              width: 254px;
-              padding-top: 14px;
-              z-index: 10000;
-              background: rgba(37, 40, 40, 1);
-              box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.16);
-              border-radius: 5px;
-              white-space: normal;
-              li {
-                width: 26px;
-                height: 26px;
-                margin: 0;
-                margin-left: 14px;
-                display: inline-block;
-                border: solid 1px rgba(255, 255, 255, 0.5);
-                border-radius: 50%;
-                margin-bottom: 14px;
-                &.active {
-                  border: solid 2px #fff;
-                  padding: 2px;
-                }
-                div {
-                  width: 100%;
-                  height: 100%;
-                  border-radius: 50%;
-                }
-              }
-            }
-            > span {
-              position: absolute;
-              right: -6px;
-              top: -6px;
-              width: 16px;
-              height: 16px;
-              border-radius: 50%;
-              background-color: @color;
-              display: flex;
-              align-items: center;
-              justify-content: center;
-              i {
-                font-size: 12px;
-              }
-            }
-          }
-
-          &.hot-style-upload {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            border: solid 1px #555a5a;
-            i {
-              font-size: 20px;
-              color: @color;
-            }
-          }
+          top: 50%;
+          transform: translateY(-50%);
+          right: 16px;
+          font-size: 14px;
+          color: rgba(255, 255, 255, 0.2);
         }
       }
     }
-    .bars{
-      margin-top: 20px;
+    .effect-setting {
+      margin-top: 16px;
+      .effect-setting-title {
+        font-size: 18px;
+        color: #FFFFFF;
+      }
+      .combox {
+        margin-top: 16px;
+      }
+      .effect-setting-component {
+        margin-top: 16px;
+      }
+    }
+  }
+  .footer {
+    flex: 0 0 auto;
+    padding: 15px;
+    background: #252526;
+    .deepcancel {
+      margin-right: 10px;
     }
-    .remark {
-      color: #ababab;
-      line-height: 1.5;
-      letter-spacing: 0.1px;
-      white-space: pre-wrap;
-      font-size: 12px;
+    .ui-button {
+      width: 112px;
     }
   }
 }

+ 15 - 10
packages/qjkankan-editor/src/views/hotspot/HotSpotList.vue

@@ -44,29 +44,25 @@
         <div>暂无热点信息~</div>
       </div>
     </div>
-    <eidt-panel
+    <EditPanel
+      class="adding-hotspot-panel"
       v-if="showPanel"
       :editTitle="editTitle"
       @save="save"
-      @select="
-        (data) => {
-          $emit('select', data);
-        }
-      "
       :show="showPanel"
       @close="close"
-    ></eidt-panel>
+    ></EditPanel>
   </div>
 </template>
 
 <script>
-import EidtPanel from "./EditPanel"
+import EditPanel from "./EditPanel"
 import { mapGetters } from "vuex"
 import browser from "@/utils/browser"
 export default {
   name: 'HotSpotList',
   components: {
-    EidtPanel,
+    EditPanel,
   },
   computed: {
     ...mapGetters({
@@ -254,6 +250,7 @@ export default {
   display: flex;
   flex-direction: column;
   background: #252526;
+  position: relative;
   > .title {
     font-size: 18px;
     color: #fff;
@@ -301,7 +298,7 @@ export default {
         border-radius: 2px;
         display: flex;
         align-items: center;
-        padding: 0 10px;
+        padding: 0 5px 0 10px;
         &:hover {
           background: #252526;
           .icon-delete {
@@ -322,6 +319,7 @@ export default {
           margin-left: 12px;
           display: none;
           cursor: pointer;
+          padding: 5px;
           &:hover {
             color: #fa5555;
           }
@@ -386,5 +384,12 @@ export default {
   .ui-button {
     width: 100%;
   }
+  .adding-hotspot-panel {
+    position: absolute;
+    top: 0;
+    height: 100%;
+    right: 0;
+    width: 100%;
+  }
 }
 </style>

+ 0 - 392
packages/qjkankan-editor/src/views/hotspot/Setting.vue

@@ -1,392 +0,0 @@
-<template>
-  <setting-panel :scrollbar="false">
-    <ul class="view-setting" :class="{ disable: false }">
-      <li class="top" app-border dir-bottom>
-        <div class="title">热点设置</div>
-        <div class="ui-remark">在全景图中添加图标热点,并设置热点的效果。</div>
-        <button
-          class="ui-button submit"
-          :class="{ disable: !activeItem }"
-          @click="open(null)"
-        >
-          添加热点
-        </button>
-      </li>
-      <li app-border class="list">
-        <div class="tips" v-if="someData.hotspots.length>0">当前全景图热点({{ someData.hotspots.length }})</div>
-        <div class="hots">
-          <ul v-if="someData.hotspots.length > 0">
-            <li
-              v-for="(item, key) in someData.hotspots"
-              :key="key"
-              @click="open(item)"
-            >
-              <div>
-                <i class="style" :class="{ default: true }">
-                  <em
-                    :style="{
-                      'background-image': require('@/assets/images/img_panorama_dot.png'),
-                    }"
-                    v-show="item.styleId == null"
-                  ></em>
-                </i>
-                <span>{{ item.hotspotTitle }}</span>
-              </div>
-              <i class="iconfont icon_delete" @click.stop="deleIndex = key"></i>
-              <a
-                href="javascript:;"
-                v-clickoutside="clickoutside"
-                :class="{ active: deleIndex == key }"
-                @click.stop="deleteHot(item)"
-                >删除</a
-              >
-            </li>
-          </ul>
-        </div>
-      </li>
-    </ul>
-    <eidt-panel
-      v-if="showPanel"
-      :editTitle="editTitle"
-      @save="save"
-      @select="
-        (data) => {
-          $emit('select', data);
-        }
-      "
-      :show="showPanel"
-      @close="close"
-    ></eidt-panel>
-  </setting-panel>
-</template>
-<script>
-import EidtPanel from "./EditPanel";
-import { mapGetters } from "vuex";
-import browser from "@/utils/browser";
-export default {
-  components: {
-    EidtPanel,
-  },
-  computed: {
-    ...mapGetters({
-      activeItem: "activeItem",
-      hotspot:'hotspot',
-      info:"info"
-    }),
-  },
-  data() {
-    return {
-      editLink: "",
-      showPanel: false,
-      someData: { hotspots: [] },
-      deleIndex: -1,
-      editTitle: "编辑",
-    };
-  },
-  watch: {
-    "$route.name": function() {
-      this.showPanel = false;
-    },
-    activeItem: {
-      immediate: true,
-      handler: function(newVal) {
-        this.someData = newVal.someData || "";
-
-        if (this.someData) {
-          if (typeof this.someData == 'string') {
-       
-              try {
-                  this.someData = JSON.parse(this.someData)
-              } catch(e) {
-                  console.log(e);
-                  return false;
-              }
-          }
-          if (!this.someData.hotspots) {
-            this.someData.hotspots = []
-          }
-        }
-        else{
-          this.someData = { hotspots: [] }
-        }
-        console.log(this.someData.hotspots,111111);
-      },
-    },
-    showPanel(newVal) {
-      this.$store.commit("UpdateIsEditingState", newVal);
-      this.$bus.emit("canEdit", !newVal);
-    },
-  },
-  mounted() {
-    this.$bus.on("openHotspot", (data) => {
-      let idx = this.someData.hotspots.findIndex((item) => item.name == data);
-      let beforeIdx = this.someData.hotspots.findIndex((item) => item.name == this.hotspot.name);
-      if (beforeIdx == idx) {
-        return
-      }
-      if (this.editTitle == '新增') {
-        if (this.showPanel) {
-          return this.$confirm({
-              content: "热点内容未编辑完,确定要关闭吗",
-              ok: () => {
-                this.deleteKRHotspot(this.hotspot)
-                this.open(this.someData.hotspots[idx]);
-              }
-          });
-        }
-
-      }
-
-      this.open(this.someData.hotspots[idx]);
-
-    });
-  },
-  methods: {
-    deleteKRHotspot(data) {
-      let krpano = document.getElementById("krpanoSWFObject");
-      krpano.call("removehotspot(" + data.name + ",true);");
-      krpano.call("removeplugin(" + ("tooltip_" + data.name) + ",true);");
-    },
-    close(data) {
-      if (data) {
-          if (data.type == 'edit') {
-              this.deleteKRHotspot(data.data)
-              this.$bus.emit('addhotspot',data.data)
-              let idx = this.someData.hotspots.findIndex(item=>item.name == data.data.name)
-              this.someData.hotspots[idx] =data.data
-          }
-          else{
-              this.deleteKRHotspot(data.data)
-          }
-      }
-      this.showPanel = false;
-    },
-
-    updateInfo(){
-      let iidx = this.info.scenes.findIndex(item=>this.activeItem.sceneCode == item.sceneCode)
-      if (iidx>-1) {
-        this.info.scenes[iidx] = {
-          ...this.activeItem
-        }
-      }
-      this.$store.commit("SetInfo", this.info);
-    },
-    save(data) {
-      var krpano = document.getElementById("krpanoSWFObject");
-      let HV = window.__krfn.utils.getHotspotHV(krpano, data.name);
-      data.ath = HV.ath;
-      data.atv = HV.atv;
-      let idx = this.someData.hotspots.findIndex((item) => item.name === data.name)
-      if (idx<=-1) {
-        this.someData.hotspots.push(data);
-      }
-      else{
-        this.someData.hotspots[idx] = data
-      }
-
-      this.activeItem.someData = this.someData;
-      this.$msg.success(this.editTitle + "成功")
-
-      let iidx = this.info.scenes.findIndex(item=>this.activeItem.sceneCode == item.sceneCode)
-      if (iidx>-1) {
-        this.info.scenes[iidx] = {
-          ...this.activeItem
-        }
-      }
-      
-      this.updateInfo()
-
-    },
-    deleteHot(data) {
-      this.someData.hotspots.splice(
-        this.someData.hotspots.findIndex((item) => item.name === data.name),
-        1
-      );
-      this.deleteKRHotspot(data);
-      this.activeItem.someData = this.someData;
-      this.updateInfo()
-      this.$msg.success("删除成功")
-    },
-    open(data) {
-      this.editTitle = "新增";
-      let temp = data ? browser.CloneObject(data) : {
-        name: "_"+this.$randomWord(true,8,8),
-        hotspotTitle:'',
-        fontSize:12,
-        type:'',
-        img:'',
-        link:'',
-        visible: true,
-        ath: '',
-        atv: '',
-        icontype: 'ditu',
-        size:1,
-        hotspotType:'scene',
-        secne:'',
-        hyperlink:'',
-        textarea:'',
-        image:[],
-        audio:'',
-        video:''
-      }      
-
-      this.$store.commit("SetHotspot", temp);
-      this.showPanel = true;
-
-      if (data) {
-        this.editLink = temp.link;
-        this.editTitle = "编辑";
-        var krpano = document.getElementById("krpanoSWFObject");
-        window.__krfn.utils.looktohotspot(krpano, data.name);
-      }
-    },
-    clickoutside() {
-      if (this.deleIndex > -1) {
-        this.deleIndex = -1;
-      }
-    },
-  },
-};
-</script>
-<style lang="less" scoped>
-.view-setting {
-  height: 100%;
-  display: flex;
-  flex-direction: column;
-  padding: 0!important;
-  li {
-    display: flex;
-    &.top{
-      flex-direction: column;
-    }
-    &.list {
-      position: relative;
-      flex: 1;
-      padding: 0;
-      width: 100%;
-      flex-direction: column;
-      > div {
-        margin: 0;
-        display: block;
-      }
-    }
-    .ui-remark{
-        margin-bottom: 10px;
-    }
-  }
-
-  .tips {
-    padding: 10px;
-  }
-
-  .hots {
-    padding-top: 40px;
-    position: absolute;
-    left: 0;
-    top: 0;
-    width: 100%;
-    height: 100%;
-    ul {
-      width: 100%;
-      max-height: 100%;
-      overflow-y: auto;
-      overflow-x: hidden;
-    }
-    li {
-      cursor: pointer;
-      position: relative;
-      height: 40px;
-      line-height: 40px;
-      padding: 0 10px;
-      background: #373938;
-      margin-bottom: 10px;
-      &::after {
-        display: none;
-        content: "";
-        position: absolute;
-        width: 4px;
-        height: 100%;
-        right: 0;
-        top: 0;
-        background-color: @color;
-      }
-      &:hover {
-        &::after {
-          display: block;
-        }
-      }
-
-      > div {
-        position: relative;
-        width: 100%;
-        height: 100%;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        padding-left: 25px;
-        padding-right: 5px;
-      }
-      a {
-        position: absolute;
-        top: 0;
-        right: -100%;
-        width: 82px;
-        height: 100%;
-        line-height: 40px;
-        color: #fff;
-        text-align: center;
-        text-decoration: none;
-        background-color: @color;
-        box-shadow: -5px 0px 20px rgba(0, 0, 0, 0.5);
-        z-index: 10;
-        opacity: 0;
-        transition: right 0.3s, opacity 0.1s;
-        &.active {
-          right: 0px;
-          opacity: 1;
-        }
-      }
-      .style {
-        position: absolute;
-        left: 0;
-        top: 50%;
-        width: 20px;
-        height: 20px;
-        transform: translateY(-50%);
-        background-position: center center;
-        background-size: contain;
-        background-repeat: no-repeat;
-        border-radius: 50%;
-        &.default {
-          border: solid 1px rgba(255, 255, 255, 0.1);
-          em {
-            position: absolute;
-            left: 50%;
-            top: 50%;
-            transform: translate(-50%, -50%);
-            width: 80%;
-            height: 80%;
-            border: solid 0.5px #fff;
-            background: @color url("~@/assets/images/img_panorama_dot.png")
-              no-repeat;
-            background-size: 80% 80%;
-            background-position: center center;
-            border-radius: 50%;
-          }
-        }
-      }
-      .icon_delete {
-        font-size: 25px;
-        padding: 0 5px;
-        color: #999;
-        &:hover {
-          color: #fff;
-        }
-      }
-    }
-  }
-
-  .ui-button {
-    width: 100%;
-  }
-}
-</style>

+ 0 - 180
packages/qjkankan-editor/src/views/hotspot/Toolbar.vue

@@ -1,180 +0,0 @@
-<template>
-  <div class="app-view-toolbar" :class="{unable:!canEdit}" app-border dir-top>
-    <div class="room-label" >
-      <ul>
-        <li
-          :class="{ active: item.id === type }"
-          @click="type = item.id"
-          v-for="(item, i) in [$panoType[0],$panoType[1]]"
-          :key="i"
-        >
-          {{ item.name }}
-        </li>
-      </ul>
-    </div>
-    <div class="clip-center">
-      <div class="pano-con clip-scroller">
-        <ul ref="clip">
-          <li v-for="(item, i) in list" @click="activeItem = item" :class="{'li-active':item.sceneCode==activeItem.sceneCode}" :key="i">
-            <div class="typeli">
-              <i class="iconfont iconedit_type_3d" :class="{'iconedit_type_panorama':item.type!=='house'}"></i>
-            </div>
-            <div class="img">
-              <img :src="item.icon" alt="">
-            </div>
-            <div class="ui-title">
-              <span>{{item.fileName}}</span>
-            </div>
-          </li>
-        </ul>
-      </div>
-    </div>
-  </div>
-</template>
-<script>
-import { getPanoList } from "@/api";
-let $scroll = null;
-export default {
-  data() {
-    return {
-      type: "building",
-      list:[],
-      activeItem:'',
-      canEdit:true
-    };
-  },
-  activated() {
-    this.$nextTick(() => {
-          if ($scroll == null) {
-              $scroll = $(".clip-scroller")[0];
-
-              var options = {
-                horizontal: 1,
-                itemNav: 'basic',
-                speed: 300,
-                mouseDragging: 1,
-                touchDragging: 1
-              };
-
-              $scroll .sly(options);
-              // var frame = new Sly('#frame', options).init();
-              // new PerfectScrollbar($scroll, {
-              //     useBothWheelAxes: true,
-              //     suppressScrollY: true,
-              // });
-          }
-      });
-  },
-  methods:{
-    getPanoList(isFirst){
-      getPanoList({
-        pageNum: 0,
-        pageSize: 0,
-        searchKey: "",
-        type: this.type,
-        status:3
-      },data=>{
-        this.list = data.data.list
-        isFirst&&(this.activeItem = this.list[0])
-      })
-    },
-  },
-  created() {
-    this.getPanoList(true)
-  },
-  watch:{
-    activeItem(newVal){
-     newVal && this.$bus.emit('currentPcode',newVal)
-    },
-    type(){
-      this.getPanoList()
-    }
-  },
-  mounted(){
-    this.$bus.on('canEdit',data=>{
-      this.canEdit = data
-    })
-  }
-};
-</script>
-<style lang="less" scoped>
-.app-view-toolbar {
-  overflow: visible;
-  a {
-    color: #fff;
-    text-decoration: none;
-  }
- 
-  .room-label {
-    top: -32px;
-    left: 10px;
-    right: 0px;
-    position: absolute;
-    overflow: hidden;
-    ul {
-      display: flex;
-    }
-    li {
-      cursor: pointer;
-      width: 100px;
-      height: 32px;
-      line-height: 32px;
-      padding: 0 5px;
-      text-align: center;
-      border-top: solid 1px #5d5d5d;
-      border-right: solid 1px #5d5d5d;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      &:first-child {
-        border-left: solid 1px #5d5d5d;
-      }
-      &.active {
-        background-color: @color;
-      }
-    }
-  }
-
-
-
-  .clip-center {
-    flex: 1;
-    display: flex;
-    overflow: hidden;
-    .pano-con {
-      width: 100%;
-      padding: 0;
-      background: none;
-      margin: 0 10px;
-      >ul{
-        flex-wrap: unset;
-        >li{
-          height: 128px;
-          width: 128px;
-          cursor: pointer;
-          &:first-of-type{
-            margin-left: 0;
-          }
-        }
-      }
-    }
-    .clip-scroller {
-        width: 100%;
-        height: 100%;
-        position: relative;
-      padding-right: 20px;
-
-    }
-  }
-}
-  .unable{
-    &::before{
-      content: '';
-      z-index: 22;
-      position: absolute;
-      width: 100%;
-      top: -32px;
-      height: calc(100% + 32px );
-      background: rgba(0, 0, 0, 0.4);
-    }
-  }
-</style>

+ 119 - 127
packages/qjkankan-editor/src/views/hotspot/hotspotType/audio.vue

@@ -1,107 +1,69 @@
 <template>
-  <div>
-    <div class="medias">
-    <div class="btn-push">
-      <span v-if="!tAudio.id">请选择音频素材</span>
-      <div class="audio-con" v-else>
-          <span>{{tAudio.name}}</span>
-          <div class="del">
-              <span @click="del" class="ui-button submit">删除</span>
-          </div>
+  <div class="audio-hotspot-setting">
+    <button class="add-btn" v-if="!tAudio.id" @click="selectHandle">
+      <i class="iconfont icon-editor_add"></i>
+      添加音频
+    </button>
+    <template v-else>
+      <div class="music-display" @click.self="onClickCurrentMusic">
+        <Audio ref="my-audio" class="audio-control" :backgroundColor="'#1A1B1D'" :myAudioUrl="tAudio.ossPath"></Audio>
+        <div class="name" v-title="tAudio.name" @click="onClickCurrentMusic">{{tAudio.name}}</div>
+        <i class="iconfont icon-editor_list_delete" @click.stop="del"></i>
       </div>
-    </div>
-  </div>
-  <button class="ui-button submit" @click="selectHandle">选择音频</button>
-  <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
-      <Table
-        :list="list"
-        :tabHeader="$MAPTABLEHEADER[type]"
-        @updateList="update"
+      <button class="change-btn" @click="selectHandle">
+        <i class="iconfont icon-editor_update"></i>
+        更换音频
+      </button>
+    </template>
+
+    <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
+      <MaterialSelectorForEditor
+        title="选择音频"
         @cancle="isShowSelect = false"
-        :title="`选择${$MARERIALSTR[type]}`"
-        @changeCurrent="changeCurrent"
-        :paging="paging"
         @submit="handleSelect"
-      >
-    </Table>
-  </div>
+        :selectableType="['audio']"
+        initialMaterialType="audio"
+      />
+    </div>
+
   </div>
 </template>
 
 <script>
-import { getMaterialList} from "@/api";
-import Table from "@/components/tableSelect";
-import { changeByteUnit } from '@/utils/file'
+import MaterialSelectorForEditor from "@/components/materialSelectorForEditor.vue";
+import Audio from "@/components/audio/audioForEditor.vue";
+
 
 export default {
-  components:{Table},
   props:['audio'],
-  data(){
+  components: {
+    MaterialSelectorForEditor,
+    Audio,
+  },
+  data() {
     return {
-      type:'audio',
-      tAudio:{...this.audio},
-      isShowSelect:false,
-      list:[],
-      paging: {
-        pageSize: 8,
-        pageNum: 1,
-        total: 0,
-        showSize: 4,
-        current: 1
-      },
+      tAudio: {...this.audio},
+      isShowSelect: false,
     }
   },
   methods:{
+    onClickCurrentMusic() {
+      if (this.$refs['my-audio']) {
+        this.$refs['my-audio'].switchPlayPause()
+      }
+    },
     del(){
       this.tAudio = ''
     },
     selectHandle(){
       this.isShowSelect = true 
-      this.getMaterialList()
-    },
-    changeCurrent(data){
-      this.paging.pageNum = data;
-    },
-    update(data) {
-      this.key = data;
-      this.getMaterialList();
     },
     handleSelect(data){
       this.tAudio = {...data[0]}
       this.isShowSelect = false
     },
-    getMaterialList() {
-      getMaterialList(
-        {
-          pageNum: this.paging.pageNum,
-          pageSize: this.paging.pageSize,
-          searchKey: this.key,
-          type:this.type
-        },
-        (data) => {
-          this.list = [];
-          setTimeout(() => {
-            this.paging.pageNum = data.data.pageNum;
-            this.paging.pageSize = data.data.pageSize;
-            this.paging.total = data.data.total;
-            this.list = data.data.list.map(i=>{
-              i.fileSize = changeByteUnit(Number(i.fileSize))
-              return i
-            })
-          })
-        }
-      );
-    },
   },
   watch:{
-    "paging.pageNum": function () {
-      this.isShowSelect && this.getMaterialList();
-    },
-    isShowSelect(newVal){
-      if (!newVal) {
-        this.paging.pageNum = 1
-      }
-    },
     tAudio(newVal){
       this.$emit('audioChange',newVal)
     }
@@ -109,63 +71,93 @@ export default {
 }
 </script>
 
-<style lang="less" src="./style.less"></style>
-
 <style lang="less" scoped>
-.ui-button{
-  width: 100%;
-  margin-top: 10px;
-}
-.medias{
-  min-height: 70px;
-  overflow-y: auto;
-.audio-con{
-  width: 100%;
-  height: 100%;
-  position: relative;
-  >span{
-    position: absolute;
-    transform: translate(-50%,-50%);
-    top: 50%;
-    left: 50%;
-    width: 90%;
-    color: @color;
-    text-overflow: ellipsis;
-    overflow: hidden;
-    white-space: nowrap;
+.audio-hotspot-setting {
+  > .add-btn {
+    margin-top: 16px;
+    width: 100%;
+    height: 40px;
+    background: #1A1B1D;
+    border-radius: 2px;
+    border: 1px solid #404040;
+    display: block;
+    color: #0076F6;
+    font-size: 14px;
+    cursor: pointer;
+    &:hover {
+      border-color: @color;
+    }
+    i {
+      font-size: 14px;
+    }
   }
-  .del{
+  > .music-display {
+    cursor: pointer;
+    margin-top: 16px;
+    width: 100%;
+    height: 40px;
+    background: #1A1B1D;
+    border-radius: 2px;
+    border: 1px solid #404040;
+    color: #fff;
+    font-size: 14px;
+    position: relative;
+    &:hover {
+      color: #0076F6;
+      border-color: @color;
+      > .audio-control {
+        display: inline-block;
+      }
+      > i {
+        display: inline-block;
+      }
+    }
+    > .audio-control {
+      position: absolute;
+      top: 50%;
+      transform: translateY(-50%);
+      left: 18px;
+      display: none;
+    }
+    > .name {
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+      width: 65%;
+      text-overflow: ellipsis;
+      overflow: hidden;
+      white-space: nowrap;
+      display: inline-block;
+    }
+    > i {
       display: none;
       position: absolute;
-      left: 0;
-      top: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 9;
-      background: rgba(0, 0, 0, 0.5);
-      >.ui-button{
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        width: auto;
-        padding: 0 10px;
-        margin: 0;
-        line-height: 24px;
-        height: 24px;
-        position: absolute;
-        top: 50%;
-        left: 50%;
-        transform: translate(-50%,-50%);
+      top: 50%;
+      transform: translateY(-50%);
+      right: 18px;
+      &:hover {
+        color: #FA5555;
       }
     }
-    &:nth-of-type(3n){
-      margin-right: 0;
+  }
+  > .change-btn {
+    margin-top: 16px;
+    width: 100%;
+    height: 40px;
+    background: #1A1B1D;
+    border-radius: 2px;
+    border: 1px solid #404040;
+    display: block;
+    color: #0076F6;
+    font-size: 14px;
+    cursor: pointer;
+    &:hover {
+      border-color: @color;
     }
-    &:hover{
-      .del{
-        display: block;
-      }
+    i {
+      font-size: 14px;
     }
-}
+  }
 }
 </style>

+ 130 - 135
packages/qjkankan-editor/src/views/hotspot/hotspotType/image.vue

@@ -1,56 +1,53 @@
 <template>
-  <div>
-    <div class="medias">
-    <div class="btn-push">
-      <span v-if="images.length<=0">请选择图片<br/>不超过10MB</span>
-      <ul class="image-con" v-else>
-        <li v-for="(item,i) in images" :key="i">
-          <img :src="item.icon||$thumb" alt="">
-          <div class="del">
-              <span @click="del(item)" class="ui-button submit">删除</span>
+  <div class="image-effect-setting">
+
+    <div class="image-list-wrap">
+      <button class="add-btn" v-if="images.length === 0" @click="selectHandle">
+        <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
+        <div>添加图片</div>
+      </button>
+      <ul class="image-list" v-else>
+        <button class="add-btn" @click="selectHandle">
+          <div class="inner-wrap">
+            <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
+            <div>添加</div>
           </div>
+        </button>
+        <li v-for="(item,i) in images" :key="i">
+          <img class="thumb" :src="item.icon || $thumb" alt="">
+          <button class="delete-btn" @click="del(item)">
+            <img class="normal" src="@/assets/images/icons/close01_normal@2x.png" alt="">
+            <img class="hover" src="@/assets/images/icons/close01_hover@2x.png" alt="">
+          </button>
         </li>
       </ul>
     </div>
-  </div>
-  <button class="ui-button submit" @click="selectHandle">选择图片</button>
-  <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
-      <Table
-        :list="list"
-        :tabHeader="$MAPTABLEHEADER[type]"
-        @updateList="update"
+
+    <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
+      <MaterialSelectorForEditor
+        title="选择图片"
         @cancle="isShowSelect = false"
-        :title="`选择${$MARERIALSTR[type]}`"
-        @changeCurrent="changeCurrent"
-        :paging="paging"
         @submit="handleSelect"
-      >
-    </Table>
-  </div>
+        :selectableType="['image']"
+        :isMultiSelection="true"
+      />
+    </div>
+
   </div>
 </template>
 
 <script>
-import { getMaterialList} from "@/api";
-import Table from "@/components/tableSelect";
-import { changeByteUnit } from '@/utils/file'
+import MaterialSelectorForEditor from "@/components/materialSelectorForEditor.vue";
 
 export default {
-  components:{Table},
+  components:{
+    MaterialSelectorForEditor,
+  },
   props:['image'],
   data(){
     return {
-      type:'image',
-      images:[...this.image],
-      isShowSelect:false,
-      list:[],
-      paging: {
-        pageSize: 8,
-        pageNum: 1,
-        total: 0,
-        showSize: 4,
-        current: 1
-      },
+      images: [...this.image],
+      isShowSelect: false,
     }
   },
   methods:{
@@ -58,52 +55,17 @@ export default {
       let index = this.images.findIndex(i => i.id === item.id)
       ~index && this.images.splice(index, 1)
     },
-    selectHandle(){
+    selectHandle() {
       this.isShowSelect = true 
-      this.getMaterialList()
-    },
-    changeCurrent(data){
-      this.paging.pageNum = data;
-    },
-    update(data) {
-      this.key = data;
-      this.getMaterialList();
     },
-    handleSelect(data){
+    handleSelect(data) {
       this.images = this.images.concat(data)
       this.isShowSelect = false
     },
-    getMaterialList() {
-      getMaterialList(
-        {
-          pageNum: this.paging.pageNum,
-          pageSize: this.paging.pageSize,
-          searchKey: this.key,
-          type:this.type
-        },
-        (data) => {
-          this.paging.pageNum = data.data.pageNum;
-          this.paging.pageSize = data.data.pageSize;
-          this.paging.total = data.data.total;
-          this.list = data.data.list.map(i=>{
-            i.fileSize = changeByteUnit(Number(i.fileSize))
-            return i
-          })
-        }
-      );
-    },
   },
-  watch:{
-    "paging.pageNum": function () {
-      this.isShowSelect && this.getMaterialList();
-    },
-    isShowSelect(newVal){
-      if (!newVal) {
-        this.paging.pageNum = 1
-      }
-    },
-    images(newVal){
-      if (newVal.length>20) {
+  watch: {
+    images(newVal) {
+      if (newVal.length > 20) {
         return this.$alert({ content: "最多添加20张图片" });
       }
       this.$emit('imageChange',newVal)
@@ -112,73 +74,106 @@ export default {
 }
 </script>
 
-<style lang="less" src="./style.less"></style>
-
 <style lang="less" scoped>
-.ui-button{
-  width: 100%;
-  margin-top: 10px;
-}
-.medias{
-  min-height: 216px;
-  overflow-y: auto;
-  @gap:6px;
-.image-con{
-  display: flex;
-  flex-wrap: wrap;
-  align-items: flex-start;
-  padding: @gap;
-  width: 100%;
-  position: relative;
-  >li{
-    width: calc((100% - (@gap * 3)) / 3);
-    height: 59px;
-    margin-bottom: @gap;
+.image-effect-setting {
+  > .image-list-wrap {
+    min-height: 242px;
+    background: #1A1B1D;
+    border-radius: 2px;
+    border: 1px solid #404040;
     position: relative;
-    overflow: hidden;
-    margin-right: @gap;
-    >img{
-      height: 100%;
-      position: absolute;
-      transform: translate(-50%,-50%);
+    padding: 8px;
+    > .add-btn {
       top: 50%;
       left: 50%;
-    }
-    .del{
-      display: none;
+      transform: translate(-50%, -50%);
       position: absolute;
-      left: 0;
-      top: 0;
-      width: 100%;
-      height: 100%;
-      z-index: 9;
-      background: rgba(0, 0, 0, 0.5);
-      >.ui-button{
-        display: flex;
-        align-items: center;
-        width: auto;
-        padding: 0 10px;
-        margin: 0;
-        line-height: 24px;
-        height: 24px;
-        position: absolute;
-        top: 50%;
-        left: 50%;
-        transform: translate(-50%,-50%);
-        min-width: unset;
-        width: 90%;
-        font-size: 12px;
+      background: none;
+      border: none;
+      color: @color;
+      cursor: pointer;
+      > img {
+        width: 30px;
+      }
+      > div {
+        margin-top: 6px;
+        font-size: 14px;
       }
     }
-    &:nth-of-type(3n){
-      margin-right: 0;
-    }
-    &:hover{
-      .del{
-        display: block;
+    > .image-list {
+      margin-right: -4px;
+      margin-bottom: -8px;
+      > .add-btn {
+        background: none;
+        border-radius: 2px;
+        border: 2px solid #0076F6;
+        color: @color;
+        cursor: pointer;
+        display: inline-block;
+        width: 67px;
+        height: 67px;
+        margin-right: 4px;
+        margin-bottom: 8px;
+        position: relative;
+        vertical-align: bottom;
+        > .inner-wrap {
+          position: absolute;
+          top: 50%;
+          left: 50%;
+          transform: translate(-50%, -50%);
+          > img {
+            width: 18px;
+          }
+          > div {
+            margin-top: 4px;
+            font-size: 12px;
+          }
+        }
+      }
+      > li {
+        display: inline-block;
+        width: 67px;
+        height: 67px;
+        margin-right: 4px;
+        margin-bottom: 8px;
+        position: relative;
+        > .thumb {
+          width: 100%;
+          height: 100%;
+          object-fit: cover;
+          border-radius: 2px;
+        }
+        > .delete-btn {
+          position: absolute;
+          top: 0;
+          right: 0;
+          width: 20px;
+          height: 20px;
+          background: none;
+          border: none;
+          padding: 0;
+          cursor: pointer;
+          &:hover {
+            .normal {
+              display: none;
+            }
+            .hover {
+              display: initial;
+            }
+          }
+          > .normal {
+            display: initial;
+            width: 100%;
+            height: 100%;
+          }
+          > .hover {
+            display: none;
+            width: 100%;
+            height: 100%;
+          }
+        }
       }
     }
   }
 }
-}
 </style>

+ 33 - 10
packages/qjkankan-editor/src/views/hotspot/hotspotType/link.vue

@@ -1,12 +1,14 @@
 <template>
   <div>
-    <input
-      type="text"
-      class="ui-input"
-      placeholder="https://"
-      v-model.trim="hyperlink"
-      @change="onUrlChange()"
-    />
+    <div class="input-wrapper">
+      <input
+        v-model.trim="hyperlink"
+        type="text"
+        maxlength="15"
+        placeholder="https://"
+        @change="onUrlChange()"
+      />
+    </div>
   </div>
 </template>
 
@@ -36,8 +38,29 @@ export default {
 }
 </script>
 
-<style lang="less" src="./style.less"></style>
-
 <style lang="less" scoped>
-
+.input-wrapper {
+  position: relative;
+  border: 1px solid rgba(151, 151, 151, 0.2);
+  padding: 0 16px;
+  background: #1A1B1D;
+  border-radius: 2px;
+  height: 36px;
+  width: 100%;
+  margin-top: 18px;
+  &:focus-within {
+    border-color: #0076F6;
+  }
+  > input {
+    border: none;
+    background: transparent;
+    outline: none;
+    height: 100%;
+    width: 100%;
+    padding: 0;
+    color: #fff;
+    letter-spacing: 1px;
+    font-size: 14px;
+  }
+}
 </style>

+ 134 - 63
packages/qjkankan-editor/src/views/hotspot/hotspotType/scene.vue

@@ -1,36 +1,44 @@
 <template>
-  <div>
-    <div class="medias">
-    <div class="btn-push">
-      <span v-if="!selected.icon">选择场景</span>
-      <div class="scene-con" v-else>
-        <i class="iconfont iconedit_type_3d"
-                    :class="{'iconedit_type_panorama':selected.type!=='4dkk'}"></i>
-        <img class="icon" :src="selected.icon||$thumb" alt="">
-        <span class="shenglve">{{selected.sceneTitle||'名字'}}</span>
-        <i @click="del" class="iconfont iconedit_case_delete"></i>
+  <div class="scene-effect-setting">
+    <div class="add-btn-wrap" v-if="!selected.icon">
+      <button @click="showScene = true">
+        <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
+        <div>添加场景</div>
+      </button>
+    </div>
+    <div v-else class="scene-info">
+      <div class="image-wrap">
+        <i class="iconfont icon-scene-type" :class="selected.type === '4dkk' ? 'iconedit_type_3d' : 'iconedit_type_panorama'"></i>
+        <img class="thumb" :src=" selected.icon || $thumb" alt="">
+        <button class="delete-btn" @click="del">
+          <img class="normal" src="@/assets/images/icons/close01_normal@2x.png" alt="">
+          <img class="hover" src="@/assets/images/icons/close01_hover@2x.png" alt="">
+        </button>
+      </div>
+      <div class="right-wrap">
+        <button class="ui-button submit" @click="showScene = true">更换场景</button>
+        <div class="scene-title" v-title="selected.sceneTitle">{{selected.sceneTitle}}</div>
       </div>
     </div>
-  </div>
-  <button class="ui-button submit" @click="showScene = true">选择场景</button>
-  <div class="dialog" style="z-index: 2000" v-if="showScene">
-      <Select
+    
+    <div class="dialog" style="z-index: 2000" v-if="showScene">
+      <Selector
+        :selected="selected"
         @cancle="showScene = false"
-        :selected='selected'
-        :title="'选择素材'"
         @submit="handleSelect"
-      >
-      </Select>
+      />
     </div>
   </div>
 </template>
 
 <script>
-import Select from "@/components/select";
+import Selector from "@/components/materialSelectorFromWorkForEditor.vue";
 
 export default {
   props:['scene'],
-  components:{Select},
+  components:{
+    Selector,
+  },
   data(){
     return {
       showScene:false,
@@ -39,8 +47,8 @@ export default {
   },
   methods:{
     handleSelect(data){
-      this.$emit('sceneSelect',data)
-      this.selected = data
+      this.$emit('sceneSelect',data[0])
+      this.selected = data[0]
       this.showScene =false
     },
     del(){
@@ -51,50 +59,113 @@ export default {
 }
 </script>
 
-<style lang="less" src="./style.less"></style>
-
 <style lang="less" scoped>
-.ui-button{
-  width: 100%;
-  margin-top: 10px;
-}
-.medias{
-  height: 122px;
-  cursor: auto;
-}
-.scene-con{
-  display: flex;
-  justify-content: space-between;
-  padding: 10px;
-  width: 100%;
-  height: 100%;
-  position: relative;
-  .iconfont{
-    position: absolute;
-    left: 18px;
-    top: 18px;
-    color: #fff;
-    background: rgba(0, 0, 0, 0.5);
+.scene-effect-setting {
+  margin-top: 16px;
+  .add-btn-wrap {
+    height: 120px;
+    background: #1A1B1D;
     border-radius: 2px;
-    padding: 8px;
-  }
-  .icon{
-    width: 102px;
-    height: 102px;
-  }
-  >span{
-    flex: 1;
-    text-align: left;
-    padding-left: 10px;
-    white-space: break-spaces;
+    border: 1px solid #404040;
+    position: relative;
+    button {
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      position: absolute;
+      background: none;
+      border: none;
+      color: @color;
+      cursor: pointer;
+      img {
+        width: 30px;
+      }
+      div {
+        margin-top: 6px;
+        font-size: 14px;
+      }
+    }
   }
-  .iconedit_case_delete{
-    left: auto;
-    top: auto;
-    right: 10px;
-    bottom: 10px;
-    border-radius: 50%;
-    cursor: pointer;
+  .scene-info {
+    display: flex;
+    .image-wrap {
+      position: relative;
+      width: 120px;
+      height: 120px;
+      flex: 0 0 auto;
+      .icon-scene-type {
+        position: absolute;
+        top: 10px;
+        left: 10px;
+        width: 32px;
+        height: 32px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        background: rgba(0, 0, 0, 0.5);
+        border-radius: 2px;
+      }
+      .delete-btn {
+        position: absolute;
+        top: 0;
+        right: 0;
+        width: 20px;
+        height: 20px;
+        background: none;
+        border: none;
+        padding: 0;
+        cursor: pointer;
+        &:hover {
+          .normal {
+            display: none;
+          }
+          .hover {
+            display: initial;
+          }
+        }
+        .normal {
+          display: initial;
+          width: 100%;
+          height: 100%;
+        }
+        .hover {
+          display: none;
+          width: 100%;
+          height: 100%;
+        }
+      }
+      .thumb {
+        width: 100%;
+        height: 100%;
+        background: #B0B0B0;
+        border-radius: 2px;
+      }
+    }
+    .right-wrap {
+      flex: 1 0 1px;
+      margin-left: 16px;
+      button {
+        width: 100%;
+        padding: 0;
+      }
+      .scene-title {
+        margin-top: 10px;
+        display: -webkit-box;
+        -webkit-box-orient: vertical;
+        -webkit-line-clamp: 2;
+        overflow: hidden;
+      }
+    }
   }
 }
+
+.dialog {
+  position: fixed;
+  z-index: 30;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, 0.5);
+}
 </style>

+ 0 - 34
packages/qjkankan-editor/src/views/hotspot/hotspotType/style.less

@@ -1,34 +0,0 @@
-.medias {
-  height: 105px; 
-  width: 210px;
-  position: relative;
-  background: #161A1A;
-  border: 1px solid #555A5A;
-  overflow: hidden;
-  .btn-push{
-      position: absolute;
-      top: 50%;
-      left: 50%;
-      transform: translate(-50%,-50%);
-      text-align: center;
-      font-size: 12px;
-      width: 100%;
-      height: 100%;
-      >span{
-        position: absolute;
-        top: 50%;
-        left: 50%;
-        transform: translate(-50%,-50%);
-      }
-  }
-}
-
-.dialog {
-  position: fixed;
-  z-index: 30;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(0, 0, 0, 0.5);
-}

+ 45 - 17
packages/qjkankan-editor/src/views/hotspot/hotspotType/textarea.vue

@@ -1,33 +1,61 @@
 <template>
   <div>
-    <textarea
-      style="height:172px;"
-      maxlength="200"
-      placeholder="请输入文字内容,限200字"
-      type="text"
-      class="ui-input ui-textarea"
-      v-model="text"
-    />
+    <div class="textarea-wrapper">
+      <textarea
+        v-model.trim="text"
+        maxlength="200"
+        placeholder="请输入文字内容,限200字"
+        type="text"
+      />
+      <span class="count">{{text.length}}/200</span>
+    </div>
   </div>
 </template>
 <script>
 export default {
-  props:['textarea'],
-  data(){
+  props: ['textarea'],
+  data() {
     return {
-      text:this.textarea
+      text: this.textarea
     }
   },
-  watch:{
-    text(newVal){
-      this.$emit('textChange',newVal)
+  watch: {
+    text(newVal) {
+      this.$emit('textChange', newVal)
     }
   }
 }
 </script>
 
-<style lang="less" src="./style.less"></style>
-
 <style lang="less" scoped>
-
+.textarea-wrapper {
+  position: relative;
+  border: 1px solid rgba(151, 151, 151, 0.2);
+  background: #1A1B1D;
+  border-radius: 2px;
+  height: 119px;
+  width: 100%;
+  &:focus-within {
+    border-color: #0076F6;
+  }
+  > textarea {
+    padding: 9px 16px 30px 16px;
+    resize: none;
+    border: none;
+    background: transparent;
+    outline: none;
+    width: 100%;
+    height: calc(100% - 30px);
+    color: #fff;
+    letter-spacing: 1px;
+    font-size: 14px;
+  }
+  > .count {
+    position: absolute;
+    right: 16px;
+    bottom: 9px;
+    font-size: 14px;
+    color: rgba(255, 255, 255, 0.2);
+  }
+}
 </style>

+ 128 - 132
packages/qjkankan-editor/src/views/hotspot/hotspotType/video.vue

@@ -1,167 +1,163 @@
 <template>
-  <div>
-    <div class="medias">
-    <div class="btn-push">
-      <span v-if="!tVideo.id">请选择视频素材</span>
-      <div class="video-con" v-else>
-          <img :src="tVideo.icon||$thumb" alt="">
-          <div class="del">
-              <span @click="del" class="ui-button submit">删除</span>
-          </div>
+  <div class="video-hotspot-setting">
+
+    <div class="add-btn-wrap" v-if="!tVideo.id">
+      <button @click="selectHandle">
+        <img src="@/assets/images/default/hotspot_scene_add.png" alt="">
+        <div>添加视频</div>
+      </button>
+    </div>
+
+    <div class="has-video-wrap" v-else>
+      <div class="thumb-wrap">
+        <img class="thumb" :src="tVideo.icon||$thumb" alt="">
+        <button class="delete-btn" @click="del">
+          <img class="normal" src="@/assets/images/icons/close01_normal@2x.png" alt="">
+          <img class="hover" src="@/assets/images/icons/close01_hover@2x.png" alt="">
+        </button>
       </div>
+      <button class="change-btn" @click="selectHandle">
+        <i class="iconfont icon-editor_update"></i>
+        更换视频
+      </button>
     </div>
-  </div>
-  <button class="ui-button submit" @click="selectHandle">选择视频</button>
-  <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
-      <Table
-        :list="list"
-        :tabHeader="$MAPTABLEHEADER[type]"
-        @updateList="update"
+
+    <div class="dialog" style="z-index: 2000" v-if="isShowSelect">
+      <MaterialSelectorForEditor
+        title="选择视频"
         @cancle="isShowSelect = false"
-        :title="`选择${$MARERIALSTR[type]}`"
-        @changeCurrent="changeCurrent"
-        :paging="paging"
         @submit="handleSelect"
-      >
-    </Table>
-  </div>
+        :selectableType="['video']"
+        initialMaterialType="video"
+      />
+    </div>
   </div>
 </template>
 
 <script>
-import { getMaterialList} from "@/api";
-import Table from "@/components/tableSelect";
-import { changeByteUnit } from '@/utils/file'
+import MaterialSelectorForEditor from "@/components/materialSelectorForEditor.vue"
 
 export default {
-  components:{Table},
-  props:['video'],
-  data(){
+  components: {
+    MaterialSelectorForEditor,
+  },
+  props: ['video'],
+  data() {
     return {
-      type:'video',
-      tVideo:{...this.video},
-      isShowSelect:false,
-      list:[],
-      paging: {
-        pageSize: 8,
-        pageNum: 1,
-        total: 0,
-        showSize: 4,
-        current: 1
-      },
+      tVideo: { ...this.video },
+      isShowSelect: false,
     }
   },
-  methods:{
-    del(){
+  methods: {
+    del() {
       this.tVideo = ''
     },
-    selectHandle(){
-      this.isShowSelect = true 
-      this.getMaterialList()
+    selectHandle() {
+      this.isShowSelect = true
     },
-    changeCurrent(data){
-      this.paging.pageNum = data;
-    },
-    update(data) {
-      this.key = data;
-      this.getMaterialList();
-    },
-    handleSelect(data){
-      this.tVideo = {...data[0]}
+    handleSelect(data) {
+      this.tVideo = { ...data[0] }
       this.isShowSelect = false
     },
-    getMaterialList() {
-      getMaterialList(
-        {
-          pageNum: this.paging.pageNum,
-          pageSize: this.paging.pageSize,
-          searchKey: this.key,
-          type:this.type
-        },
-        (data) => {
-          this.paging.pageNum = data.data.pageNum;
-          this.paging.pageSize = data.data.pageSize;
-          this.paging.total = data.data.total;
-       
-          this.list =data.data.list.map(i=>{
-            i.icon = i.ossPath+this.$videoImg
-            i.fileSize = changeByteUnit(Number(i.fileSize))
-            return i
-          })
-        }
-      );
-    },
   },
-  watch:{
-    "paging.pageNum": function () {
-      this.isShowSelect && this.getMaterialList();
-    },
-    isShowSelect(newVal){
-      if (!newVal) {
-        this.paging.pageNum = 1
-      }
-    },
-    tVideo(newVal){
-      this.$emit('videoChange',newVal)
+  watch: {
+    tVideo(newVal) {
+      this.$emit('videoChange', newVal)
     }
   }
 }
 </script>
 
-<style lang="less" src="./style.less"></style>
-
 <style lang="less" scoped>
-.ui-button{
-  width: 100%;
-  margin-top: 10px;
-}
-.medias{
-  min-height: 122px;
-  overflow-y: auto;
-.video-con{
-  width: 100%;
-  height: 100%;
-  position: relative;
-  >img{
-    position: absolute;
-    transform: translate(-50%,-50%);
-    top: 50%;
-    left: 50%;
-    height: 100%;
-    color: @color;
-  }
-  .del{
-      display: none;
+.video-hotspot-setting {
+  > .add-btn-wrap {
+    height: 120px;
+    background: #1A1B1D;
+    border-radius: 2px;
+    border: 1px solid #404040;
+    position: relative;
+    > button {
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
       position: absolute;
-      left: 0;
-      top: 0;
+      background: none;
+      border: none;
+      color: @color;
+      cursor: pointer;
+      > img {
+        width: 30px;
+      }
+      > div {
+        margin-top: 6px;
+        font-size: 14px;
+      }
+    }
+  }
+
+  > .has-video-wrap {
+    > .thumb-wrap {
+      border-radius: 2px;
+      overflow: hidden;
       width: 100%;
-      height: 100%;
-      z-index: 9;
-      background: rgba(0, 0, 0, 0.5);
-      >.ui-button{
-        display: flex;
-        align-items: center;
-        width: auto;
-        padding: 0 10px;
-        margin: 0;
-        line-height: 24px;
-        height: 24px;
+      height: 132px;
+      background: #1A1B1D;
+      border-radius: 2px;
+      border: 1px solid #404040;
+      position: relative;
+      > .thumb {
+        width: 100%;
+        height: 100%;
+        object-fit: contain;
+      }
+      .delete-btn {
         position: absolute;
-        top: 50%;
-        left: 50%;
-        justify-content: center;
-        transform: translate(-50%,-50%);
+        top: 0;
+        right: 0;
+        width: 20px;
+        height: 20px;
+        background: none;
+        border: none;
+        padding: 0;
+        cursor: pointer;
+        &:hover {
+          .normal {
+            display: none;
+          }
+          .hover {
+            display: initial;
+          }
+        }
+        .normal {
+          display: initial;
+          width: 100%;
+          height: 100%;
+        }
+        .hover {
+          display: none;
+          width: 100%;
+          height: 100%;
+        }
       }
     }
-    &:nth-of-type(3n){
-      margin-right: 0;
-    }
-    &:hover{
-      .del{
-        display: block;
+    > .change-btn {
+      margin-top: 16px;
+      width: 100%;
+      height: 40px;
+      background: #1A1B1D;
+      border-radius: 2px;
+      border: 1px solid #404040;
+      display: block;
+      color: #0076F6;
+      font-size: 14px;
+      cursor: pointer;
+      &:hover {
+        border-color: @color;
+      }
+      i {
+        font-size: 14px;
       }
     }
-}
+  }
 }
 </style>

+ 1 - 95
packages/qjkankan-editor/src/views/hotspot/index.vue

@@ -1,103 +1,26 @@
 <template>
   <!-- 编辑器-热点 -->
   <div class="editor-hotspot">
-    <HotSpotList class="hot-spot-list" @select="handleSelectScene"></HotSpotList>
-    <div class="dialog" v-if="show">
-      <Select
-        @updateList="undatePano"
-        :panos="list"
-        :current="activeItem"
-        @cancle="show = false"
-        :title="'选择场景'"
-        :name="'scene'"
-        @submit="handelSelect"
-      >
-        <template slot="list" slot-scope="{ data }">
-          <div class="pano-con">
-            <div class="ui-remark">{{ data.name }}</div>
-            <ul>
-              <li
-                v-for="(item, i) in data.arr"
-                @click="activeItem = item"
-                :class="{ 'li-active': item.id == activeItem.id }"
-                :key="i"
-              >
-                <div class="typeli">
-                  <i class="iconfont iconedit_type_3d" :class="{'iconedit_type_panorama':item.type!=='house'}"></i>
-                </div>
-                <div class="img">
-                  <img :src="item.icon" alt="">
-                </div>
-                <div class="ui-title">
-                  <span>{{item.sceneTitle}}</span>
-                </div>
-              </li>
-            </ul>
-          </div>
-        </template>
-      </Select>
-    </div>
+    <HotSpotList class="hot-spot-list"></HotSpotList>
   </div>
 </template>
 <script>
 import HotSpotList from "./HotSpotList.vue";
-import Select from "@/components/select";
 
 export default {
   name: "HotSpot",
   components: {
     HotSpotList,
-    Select,
   },
   mounted(){
-    
   },
   watch: {
-    show(newVal){
-      if (newVal) {
-        this.searchKey = ''
-      }
-      else{
-        this.activeWebsite = ''
-      }
-    },
-    activeWebsite(newVal){
-      if (!newVal||!newVal.sceneCode) {
-        return
-      }
-      let tmp = ''
-      this.list.forEach(item=>{
-         if (!tmp) {
-            tmp = item.arr.find(i=>{
-              return newVal.sceneCode==i.sceneCode
-          })
-        }
-      })
-
-      this.activeItem = tmp || this.activeItem
-    }
   },
   data(){
     return {
-      show:false,
-      list:[],
-      activeItem: "",
-      searchKey: "",
-      activeWebsite:''
     }
   },
   methods:{
-    undatePano(data){
-      this.searchKey = data
-    },
-    handleSelectScene(data){
-      this.activeWebsite = data
-      this.show=true
-    },
-    handelSelect() {
-      this.$bus.emit('selectUrl',this.activeItem)
-      this.show = false
-    }
   }
 };
 </script>
@@ -114,22 +37,5 @@ export default {
     top: 0;
     height: 100%;
   }
-  .dialog {
-    position: fixed;
-    z-index: 30;
-    left: 0;
-    top: 0;
-    width: 100%;
-    height: 100%;
-    background-color: rgba(0, 0, 0, 0.5);
-    .pano-con{
-      height: auto;
-      background: none;
-      padding: 10px 0;
-      .ui-remark{
-        padding-left: 10px;
-      }
-    }
-  }
 }
 </style>

+ 0 - 112
packages/qjkankan-editor/src/views/information/Setting.vue

@@ -1,112 +0,0 @@
-<template>
-  <div class="view-setting" app-border dir-left>
-    <div class="ui-title">初始场景</div>
-    <div class="preview">
-      <img v-if="info.firstScene" :src="info.firstScene.icon" alt="">
-      <div class="tips" v-else>
-        <i class="iconfont iconphotoview" style="font-size: 40px"></i>
-      </div>
-    </div>
-    <div class="setinit" v-if="info.firstScene">
-      <button class="ui-button" @click="deleteIndexInfo">删除场景</button>
-      <button @click="showInitScene=true" class="ui-button submit" :class="{disable:false}">
-        修改场景
-      </button>
-    </div>
-
-    <template v-else>
-      <div class="setinit">
-        <button style="width:100%" @click="showInitScene=true" class="ui-button submit" :class="{disable:false}">
-          设置初始场景
-        </button>
-      </div>
-      <div class="ui-remark">初始场景为查看链接时进入的第一个场景,未设置时,不固定从某一场景打开</div>
-    </template>
-
-    <div class="dialog" style="z-index: 2000" v-if="showInitScene">
-      <Select
-        @cancle="showInitScene = false"
-        :selected='info.firstScene'
-        :title="'选择素材'"
-        @submit="handleSelect"
-      >
-      </Select>
-    </div>
-  </div>
-</template>
-
-<script>
-import { mapGetters } from "vuex";
-import Select from "@/components/select";
-
-export default {
-  components:{Select},
-  data(){
-    return {
-      showInitScene:false
-    }
-  },
-  methods:{
-    deleteIndexInfo(){
-      this.$confirm({
-          content: "是否删除?",
-          ok: () => {
-              this.info.firstScene = ''
-              this.$store.commit("SetInfo", this.info);
-              this.$msg.success('删除成功')
-          }
-      });
-      
-    },
-    handleSelect(data){
-      this.info.firstScene = data
-      this.$store.commit("SetInfo", this.info);
-      console.log(this.info.firstScene);
-      this.showInitScene=false
-    }
-  },
-  computed: {
-    ...mapGetters({
-      info: "info",
-      backupInfo: "backupInfo"
-    })
-  },
-  mounted(){
- 
-  }
-}
-</script>
-
-<style lang="less" scoped>
-.dialog {
-  position: fixed;
-  z-index: 30;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(0, 0, 0, 0.5);
-}
-.view-setting {
-  padding: 10px;
-  width: 100%;
-}
-.preview {
-  width: 100%;
-  height: 102px;
-  overflow: hidden;
-  >img{
-    width: 100%;
-    height: 100%;
-  }
-}
-.setinit {
-  width: 100%;
-  margin: 15px 0;
-  display: flex;
-  justify-content: space-between;
-  .ui-button {
-    width: 48%;
-  }
-}
-</style>

+ 0 - 441
packages/qjkankan-editor/src/views/information/Toolbar.vue

@@ -1,441 +0,0 @@
-<template>
-  <div class="app-view-toolbar app-view-full-toolbar">
-    <div class="tips">
-      <div class="ui-remark">
-        1、请自定义分组并添加全景素材或四维看看相机拍摄的场景素材;
-      </div>
-      <div class="ui-remark">
-        2、全景图可进行编辑,四维看看场景仅支持导航展示和热点关联。
-      </div>
-    </div>
-    <div class="pano-label">
-      <div class="pano-con">
-        <tabList
-          :deviation="-35"
-          :list="info.catalogRoot"
-          @clickItem="
-            (item) => {
-              taboneActive = item;
-            }
-          "
-          :active="taboneActive"
-          :id="'rand'"
-          @addGroup="hadnleAddGroup"
-          :subId="'rand1'"
-        >
-          <template slot="hover" slot-scope="{ item }">
-            <ul>
-              <li @click="$emit('addGroup', { type: 1, oper: 'edit', item })">
-                重命名
-              </li>
-              <li
-                @click="
-                  $emit('addGroup', {
-                    type: 2,
-                    oper: 'add',
-                    item: { parentId: item.id },
-                  })
-                "
-              >
-                创建二级分组
-              </li>
-              <li @click="del(item, 'one')">删除</li>
-            </ul>
-          </template>
-        </tabList>
-
-        <tabList
-          :deviation="-35"
-          v-if="childTab.length > 1"
-          :list="childTab"
-          @clickItem="
-            (item) => {
-              tabtowActive = item;
-            }
-          "
-          :active="tabtowActive"
-          :id="'subrand'"
-          @addGroup="
-            $emit('addGroup', {
-              type: 2,
-              oper: 'add',
-              item: { parentId: taboneActive.id },
-            })
-          "
-          :subId="'subrand1'"
-        >
-          <template slot="hover" slot-scope="{ item }">
-            <ul @mouseover.prevent @mouseleave.prevent>
-              <li @click="$emit('addGroup', { type: 2, oper: 'edit', item })">
-                重命名
-              </li>
-              <li @click="del(item, 'two')">删除</li>
-            </ul>
-          </template>
-        </tabList>
-
-        <template v-if="scenes.length > 0">
-          <draggable
-            tag="ul"
-            v-model="scenes"
-            animation="300"
-            @sort="uploadListSort"
-          >
-            <li v-for="(item, i) in scenes" :key="i">
-              <div class="typeli">
-                <i
-                  class="iconfont iconedit_type_3d"
-                  :class="{iconedit_type_panorama: item.type !== '4dkk' }"
-                ></i>
-              </div>
-              <div class="img">
-                <img :src="item.icon+`?${Math.random()}`" alt="" />
-              </div>
-              <div class="oper">
-                <i class="iconfont iconmore"></i>
-                <ul>
-                  <li @click="$emit('rename', item)">重命名</li>
-                  <li @click="delPano(item)">删除</li>
-                </ul>
-              </div>
-              <div class="ui-title">
-                <span>{{
-                  item.type == "house" ? item.roomName : item.sceneTitle
-                }}</span>
-              </div>
-            </li>
-          </draggable>
-        </template>
-        <div class="no-record" v-else>
-          <i class="iconfont iconedit_list_default"></i>
-          <p>暂无全景图或三维场景,可点击下方按钮进行添加</p>
-        </div>
-        <div class="add-btn">
-          <button class="ui-button submit" @click="$emit('addPano')">
-            选择全景图
-          </button>
-          <button class="ui-button submit" @click="$emit('addScene')">
-            选择三维场景
-          </button>
-        </div>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import tabList from "@/components/tablist";
-import browser from "@/utils/browser";
-
-import draggable from "vuedraggable";
-import { mapGetters } from "vuex";
-
-export default {
-  computed: {
-    ...mapGetters({
-      vrlist: "vrlist",
-      info: "info",
-    }),
-    oneWidth() {
-      let tmp = $("#tablist").width();
-      return tmp;
-    },
-    menuWidth() {
-      let tmp = $("#menucon").width();
-      return tmp;
-    },
-  },
-  data() {
-    return {
-      taboneActive: { children: [] },
-      tabtowActive: "",
-      childTab: [],
-      scenes: [],
-      interval: null,
-      list: [],
-      isLongPolling: false,
-      oneLeft: 0,
-      loadList: true,
-    };
-  },
-  watch: {
-    "info.scenes": {
-      deep: true,
-      handler: function (newVal) {
-        let arr = newVal.filter((item) => {
-          return this.tabtowActive.id == item.category;
-        });
-        this.scenes = arr.sort((a,b)=>a.weight-b.weight)
-      },
-    },
-    "info.catalogs": {
-      deep: true,
-      handler: function (newVal) {
-        let temp = [];
-        this.childTab = [];
-        let id = this.taboneActive.id;
-        let oneActive = this.info.catalogRoot.find((item) => item.id == id);
-        if (!oneActive) {
-          oneActive = this.info.catalogRoot[0]
-          this.taboneActive = this.info.catalogRoot[0]
-        }
-        oneActive.children &&
-          oneActive.children.forEach((item) => {
-            newVal.forEach((sub) => {
-              if (item == sub.id) {
-                temp.push(sub);
-              }
-            });
-          });
-        this.childTab = temp;
-      },
-    },
-    taboneActive: {
-      immediate: true,
-      deep: true,
-      handler: function (newVal, oldVal) {
-        if (!newVal.id) {
-          this.taboneActive = this.info.catalogRoot[0];
-        }
-        let temp = [];
-        newVal.children &&
-          newVal.children.forEach((item) => {
-            this.info.catalogs.forEach((sub) => {
-              if (item == sub.id) {
-                temp.push(sub);
-              }
-            });
-          });
-        this.childTab = temp;
-        if (this.childTab.length == 1 || newVal != oldVal) {
-          this.tabtowActive = this.childTab[0];
-        }
-      },
-    },
-    tabtowActive: {
-      immediate: true,
-      handler: function (newVal) {
-        if (!newVal) {
-          this.tabtowActive = this.childTab[0];
-        } else {
-          this.$emit("catalog", newVal);
-          let arr = this.info.scenes.filter((item) => {
-            return newVal.id == item.category;
-          });
-          this.scenes = arr.sort((a,b)=>a.weight-b.weight)
-        }
-      },
-    },
-  },
-
-  methods: {
-
-    hadnleAddGroup() {
-      this.$emit("addGroup", { type: 1, oper: "add", item: {} });
-    },
-    
-    uploadListSort() {
-      this.scenes.forEach((item, i) => {
-        item.weight = i+1
-      });
-
-      this.info.scenes.forEach((item)=>{
-        this.scenes.forEach((sub, idx) => {
-          sub.weight = idx+1
-          if (item.sceneCode == sub.sceneCode) {
-            item = sub
-          }
-        });
-      })
-
-      this.$store.commit("SetInfo", this.info);
-    },
-
-    delTree(data, type) {
-      let fn = (ele) => {
-        let tmp = [];
-        this.info.catalogs.forEach((sub, i) => {
-          if (ele == sub.id) {
-            this.info.scenes.forEach((item) => {
-              if (sub.id != item.category) {
-                tmp.push(item);
-              }
-            });
-            this.info.scenes = tmp;
-            this.info.catalogs.splice(i, 1);
-          }
-        });
-      };
-      if (type == "one") {
-        data.children.forEach((ele) => {
-          fn(ele);
-        });
-        let idx = this.info.catalogRoot.findIndex((item) => item.id == data.id);
-        this.info.catalogRoot.splice(idx, 1);
-        this.taboneActive = this.info.catalogRoot[0];
-      }
-
-      if (type == "two") {
-        let id = this.taboneActive.id;
-        let oneActive = this.info.catalogRoot.find((item) => item.id == id);
-        let idx = oneActive.children.findIndex((item) => item == data.id);
-        oneActive.children.splice(idx, 1);
-        fn(data.id);
-
-        let temp = browser.CloneObject(this.taboneActive);
-        this.taboneActive = "";
-        this.taboneActive = temp;
-      }
-
-
-      this.delFirstScene()
-      this.$bus.emit('scenesChange')
-      this.$store.commit("SetInfo", this.info);
-    },
-
-    delFirstScene(){
-        if (this.info.firstScene) {
-          let firIdx = this.info.scenes.find(item=>{
-            return item.sceneCode == this.info.firstScene.sceneCode
-          });
-          !firIdx&&(this.info.firstScene='')
-        }
-    },
-
-    del(data, type) {
-      if (this.info.catalogRoot.length <= 1 && type == "one") {
-        return this.$alert({
-          content: "请至少保留一个分组",
-          ok: () => {
-            return;
-          },
-        });
-      }
-
-      this.$confirm({
-        content: `分组“${data.name}”下所有${
-          type == "one" ? "二级分组和" : ""
-        }(场景/全景图)也都将会被删除,是否删除?`,
-        ok: () => {
-          this.delTree(data, type);
-          this.$msg.success("删除成功")
-        },
-      });
-    },
-    delPano(item) {
-      this.$confirm({
-        content: `${item.type=='4dkk'?'场景':'全景图'}“${item.sceneTitle}”下所有设置也都将会被删除,是否删除?`,
-        ok: () => {
-          let idx = this.info.scenes.findIndex(ele=>ele.sceneCode==item.sceneCode)
-          this.info.scenes.splice(idx,1)
-          this.delFirstScene()
-          this.$store.commit("SetInfo", this.info);
-          this.$bus.emit('scenesChange')
-          this.$msg.success("删除成功")
-        },
-      });
-    },
-  },
-
-  mounted() {
-    this.$bus.on('getActive',data=>{
-      if (data.type == 1) {
-        this.taboneActive = data.willActive
-      } else{
-        this.tabtowActive = data.willActive
-      }
-    })
-  },
-  components: {
-    draggable,
-    tabList,
-  },
-};
-</script>
-<style lang="less" scoped>
-.tips {
-  width: 100%;
-  .ui-remark {
-    margin-bottom: 10px;
-  }
-}
-.no-record {
-  position: absolute;
-  top: 50%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-  text-align: center;
-  color: rgba(255, 255, 255, 0.5);
-  > i {
-    font-size: 40px;
-  }
-  > p {
-    margin-top: 10px;
-  }
-}
-.pano-label {
-  .pano-con {
-    padding: 20px 30px;
-    height: calc(100vh - 250px);
-    .menu-con {
-      position: relative;
-      > .iconfont {
-        left: -20px;
-        top: 8px;
-        position: absolute;
-        cursor: pointer;
-      }
-      > .icon_forward {
-        right: 40px;
-        left: auto;
-      }
-      .sub-menu {
-        max-width: calc(100% - 70px);
-        position: relative;
-        overflow: hidden;
-        height: 40px;
-
-        > ul {
-          max-width: unset;
-          overflow: unset;
-          position: absolute;
-          left: 0;
-          transition: 0.3s ease all;
-          .fixed {
-            position: absolute;
-            right: 0;
-          }
-          // &::before{
-          //   width: calc(100% - 70px);
-          //   height: calc(100% - 10px);
-          //   pointer-events: none;
-          //   content: '';
-          //   background: linear-gradient(to right,rgba(#fff,0) 0%,rgba(#fff,0) 98%,rgba(#000,1) 100%);
-          //   position: absolute;
-          //   top: 0;
-          //   left: 0;
-          //   z-index: 999;
-          //   display: inline-block;
-          // }
-        }
-      }
-    }
-
-    > ul {
-      max-height: calc(100% - 82px);
-      overflow-y: auto;
-      position: relative;
-      left: -2px;
-      > li {
-        margin: 10px 20px 30px 0;
-      }
-    }
-    .add-btn {
-      z-index: 20;
-      .ui-button {
-        margin: 0 5px;
-      }
-    }
-  }
-}
-</style>

+ 0 - 399
packages/qjkankan-editor/src/views/information/index.vue

@@ -1,399 +0,0 @@
-<template>
-<!-- todo: 用不到了? -->
-  <div>
-    <setting @select="handleInitScene"></setting>
-    <toolbar
-      @catalog="data=>activeCataLog = data"
-      @addPano="onAddPano"
-      @addGroup="onAddGroup"
-      @addScene="onAddScene"
-      @rename="onRename"
-    ></toolbar>
-    <popup v-show="showAddGroup" :can-close="false">
-      <div class="ui-message ui-message-confirm dark" style="width: 400px">
-        <div class="ui-message-header">
-          <span>{{
-            currentTabAtri.oper == "add"
-              ? `新增${currentTabAtri.type == 1 ? "一" : "二"}级分组`
-              : `重命名${currentTabAtri.type == 1 ? "一" : "二"}级分组`
-          }}</span>
-          <span @click="showAddGroup = false">
-            <i class="iconfont icon_close"></i>
-          </span>
-        </div>
-        <div class="ui-message-main re-name">
-          <div>
-            <input
-              class="ui-input"
-              type="text"
-              maxlength="15"
-              placeholder="请输入分组名,限15个字"
-              v-model="currentTabAtri.name"
-            />
-          </div>
-        </div>
-
-        <div class="ui-message-footer">
-          <button class="ui-button cancel" @click="showAddGroup = false">
-            取消
-          </button>
-          <button
-            class="ui-button submit"
-            :class="{ disable: !currentTabAtri.name }"
-            @click="handleAddGroup()"
-          >
-            确定
-          </button>
-        </div>
-      </div>
-    </popup>
-
-    <popup v-show="showRename" :can-close="false">
-      <div class="ui-message ui-message-confirm dark" style="width: 400px">
-        <div class="ui-message-header">
-          <span>重命名</span>
-          <span @click="handleRenameClose">
-            <i class="iconfont icon_close"></i>
-          </span>
-        </div>
-        <div class="ui-message-main re-name">
-          <div>
-            <input
-              class="ui-input"
-              type="text"
-              maxlength="50"
-              placeholder="输入名字"
-              v-model="reNameItem.sceneTitle"
-            />
-          </div>
-        </div>
-
-        <div class="ui-message-footer">
-          <button class="ui-button cancel" @click="handleRenameClose">
-            取消
-          </button>
-          <button
-            class="ui-button submit"
-            :class="{ disable: !reNameItem.sceneTitle }"
-            @click="handleRename()"
-          >
-            确定
-          </button>
-        </div>
-      </div>
-    </popup>
-
-    <div class="dialog" style="z-index: 2000" v-if="showList">
-      <Table
-        :list="type == 'scene' ? sceneList : panoList"
-        :tabHeader="$MAPTABLEHEADER[type]"
-        @updateList="update"
-        @cancle="showList = false"
-        :title="type == 'scene' ? '选择三维场景' : '选择全景图'"
-        :primaryKey="type == 'scene' ? 'num' : 'id'"
-        @changeCurrent="changeCurrent"
-        :paging="paging"
-        @submit="handleSelect"
-      >
-      </Table>
-    </div>
-  </div>
-</template>
-<script>
-import Setting from "./Setting";
-import Toolbar from "./Toolbar";
-import Popup from "@/components/shared/popup";
-import {
-  getSceneList,
-  getMaterialList,
-} from "@/api";
-import Table from "@/components/tableSelect.vue";
-import { mapGetters } from "vuex";
-import { savePanoToWorks } from "@/api";
-import { changeByteUnit } from '@/utils/file'
-
-export default {
-  name: "home",
-  components: {
-    Setting,
-    Toolbar,
-    Popup,
-    Table,
-  },
-  computed: {
-    ...mapGetters({
-      sceneList: "sceneList",
-      info: "info",
-      backupInfo: "backupInfo"
-    }),
-  },
-  data() {
-    return {
-      activeCataLog: "",
-      type: "scene",
-      currentTabAtri: "",
-      showAddGroup: false,
-      showRename: false,
-      showList: false,
-      showInitScene: true,
-      reNameItem: {
-        id: "",
-        sceneTitle: "",
-      },
-      key: "",
-      paging: {
-        pageSize: 8,
-        pageNum: 1,
-        total: 0,
-        showSize: 4,
-        current: 1,
-      },
-      panoList: [],
-    };
-  },
-  mounted() {},
-
-  watch: {
-    "paging.pageNum": function () {
-      this.type == "scene" ? this.getSceneList() : this.getMaterialList();
-    },
-    showList(newVal) {
-      if (!newVal) {
-        this.paging = {
-          pageSize: 8,
-          pageNum: 1,
-          total: 0,
-          showSize: 4,
-          current: 1,
-        };
-      }
-    },
-  },
-
-  methods: {
-    handleInitScene() {
-      this.showInitScene = true;
-    },
-    update(data) {
-      this.key = data;
-      this.type == "scene" ? this.getSceneList() : this.getMaterialList();
-    },
-    handleSelect(data) {
-     let params = ''
-      if (this.type == "scene") {
-        params = data.map((item) => {
-          return {
-            icon: item.thumb,
-            sceneCode: item.num,
-            sceneTitle: item.sceneName,
-            type: "4dkk",
-            category:this.activeCataLog.id,
-            id:'s_'+this.$randomWord(true,8,8)
-          };
-        });
-      } else {
-        params = data.map((item) => {
-          return {
-            icon: item.icon,
-            sceneCode: item.sceneCode,
-            sceneTitle: item.name,
-            category:this.activeCataLog.id,
-            type: "pano",
-            id:'s_'+this.$randomWord(true,8,8)
-          };
-        });
-      }
-
-      params.forEach((item,i) => {
-        let temp = this.info.scenes.find(sub=>sub.sceneCode == item.sceneCode)
-        if (temp) {
-          console.log(this.$msg);
-            setTimeout(() => {
-              this.$msg.message(`${item.type=='4dkk'?'场景':'全景图'}${item.sceneTitle}已存在,不可重复添加`);
-            }, i*100);
-            return
-        }
-        !temp&&this.info.scenes.push(item)
-      });
-
-      this.$bus.emit('scenesChange')
-      this.$store.commit("SetInfo", this.info);
-      this.showList = false;
-    },
-
-    changeCurrent(data) {
-      this.paging.pageNum = data;
-    },
-
-    savePanoToWorks(data) {
-      savePanoToWorks(data, () => {
-        this.$bus.emit("refresh");
-      });
-    },
-
-    onRename(data) {
-      this.reNameItem = data;
-      this.showRename = true;
-    },
-
-    handleRenameClose(){
-      this.showRename = false
-      this.$bus.emit('scenesChange')
-      this.$store.commit("SetInfo", this.backupInfo);
-    },
-
-    handleRename() {
-      if (!this.reNameItem.sceneTitle.trim()) {
-        return this.$alert({ content: "请输入名字" });
-      }
-      this.$msg.success("重命名成功")
-      this.$store.commit("SetInfo", this.info);
-      this.showRename = false;
-    },
-
-    onAddGroup(data) {
-      this.showAddGroup = true;
-      this.currentTabAtri = { ...data, name: data.item.name || "" };
-    },
-
-    handleAddGroup() {
-      if (!this.currentTabAtri.name.trim()) {
-        return this.$alert({ content: "请输入名字" });
-      }
-      let willActive = ''
-      let tmp = this.currentTabAtri.item;
-      if (this.currentTabAtri.oper == "edit") {
-        tmp.name = this.currentTabAtri.name;
-      } else {
-        if (this.currentTabAtri.type == 1) {
-          let id = 'c_'+this.$randomWord(true,8,8)
-          willActive = {
-            id: 'r_'+this.$randomWord(true,8,8),
-            name: this.currentTabAtri.name,
-            children: [id],
-          }
-          this.info.catalogRoot.push(willActive);
-          this.info.catalogs.push({
-            id,
-            name: '默认二级分组',
-          });
-          console.log(this.info.catalogs);
-        }
-        if (this.currentTabAtri.type == 2) {
-          let id = 'c_'+this.$randomWord(true,8,8)
-          let item = this.info.catalogRoot.find(
-            (item) => item.id == tmp.parentId
-          );
-          item.children.push(id);
-          willActive = {
-            id,
-            name: this.currentTabAtri.name,
-          }
-
-          this.info.catalogs.push(willActive);
-        }
-      }
-
-      this.$bus.emit('scenesChange')
-      this.$store.commit("SetInfo", this.info);
-      this.$msg.success("操作成功")
-      this.showAddGroup = false;
-
-      if (this.currentTabAtri.oper != "edit") {
-        this.$bus.emit('getActive',{
-          type:this.currentTabAtri.type,
-          willActive
-        })
-      }
-    },
-
-    onAddScene() {
-      this.type = "scene";
-      this.getSceneList();
-      this.showList = true;
-    },
-
-    onAddPano() {
-      this.type = "pano";
-      this.getMaterialList();
-      this.showList = true;
-    },
-
-    getSceneList() {
-      getSceneList(
-        {
-          pageNum: this.paging.pageNum,
-          pageSize: this.paging.pageSize,
-          searchKey: this.key,
-        },
-        (data) => {
-          let { list, total } = data.data.data;
-          this.paging.total = total;
-
-          
-
-          this.$store.commit("SetSceneList", list);
-        }
-      );
-    },
-
-    getMaterialList() {
-      getMaterialList(
-        {
-          pageNum: this.paging.pageNum,
-          pageSize: this.paging.pageSize,
-          searchKey: this.key,
-          type: this.type,
-          urlSelect: true,
-        },
-        (data) => {
-          this.paging.pageNum = data.data.pageNum;
-          this.paging.pageSize = data.data.pageSize;
-          this.paging.total = data.data.total;
-          this.panoList = data.data.list.map(i=>{
-            i.fileSize = changeByteUnit(Number(i.fileSize))
-            i.createTime = i.createTime.substring(0,i.createTime.length-3)
-            i.updateTime = i.updateTime.substring(0,i.updateTime.length-3)
-            return i
-          })
-        }
-      );
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped>
-.dialog {
-  position: fixed;
-  z-index: 30;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  background-color: rgba(0, 0, 0, 0.5);
-}
-.pano-con {
-  height: auto;
-  background: none;
-  padding: 10px 0;
-  .ui-remark {
-    padding-left: 10px;
-  }
-  > ul {
-    > li {
-      cursor: pointer;
-    }
-  }
-}
-.re-name {
-  width: 80%;
-  margin: 40px auto;
-}
-.add-vr {
-  text-align: left;
-  .ui-remark {
-    margin: 10px 0;
-  }
-}
-</style>

+ 2 - 3
packages/qjkankan-editor/vue.config.js

@@ -1,5 +1,5 @@
-const proxy_url = process.env.VUE_APP_PROXY_URL || 'https://fcb.test.4dkankan.com'
-// https://vr-web01-uat.fcb.com.cn/
+const proxy_url = process.env.VUE_APP_PROXY_URL
+
 let pages = {
   edit: 'src/pages/edit.js',
   show: 'src/pages/show.js',
@@ -18,7 +18,6 @@ module.exports = {
     loaderOptions: {
       less: {
         globalVars: {
-          // TODO: 很多地方没用这个变量而用了字面值
           color: process.env.VUE_APP_MAIN_COLOR || "#0076F6"
         }
       }