ソースを参照

编辑器-导航-设置初始场景

任一存 3 年 前
コミット
c7c97d90ec

+ 2 - 2
packages/code/src/components/materialSelectorForEditor.vue

@@ -237,7 +237,7 @@
 </template>
 
 <script>
-import { getMaterialList, getSceneList, } from "@/api";
+import { getMaterialList, getSceneList } from "@/api";
 import { changeByteUnit } from '@/utils/file'
 import config from "@/config";
 import { debounce } from "@/utils/other.js"
@@ -343,7 +343,7 @@ export default {
 
   methods: {
     selectItem(item, e) {
-      item.materialType = this.currentMaterialType
+      item.materialType = this.currentMaterialType // 三维场景数据没有type字段来表明自己是三维场景。所以统一加一个字段。
       if (false) {
         // 对于图片,大于600kb的,压缩?
       } else {

+ 503 - 0
packages/code/src/components/materialSelectorFromWorkForEditor.vue

@@ -0,0 +1,503 @@
+<template>
+  <div class="table-select">
+    <span class="title">选择素材</span>
+    <div class="close-btn"><i class="iconfont icon-pop-ups_shut-down" @click="$emit('cancle')"></i></div>
+
+    <div class="material-tab">
+      <a class="material-tab-item" @click.prevent="currentMaterialType = 'pano'">
+        <span class="text">全景图</span>
+        <div v-if="currentMaterialType === 'pano'" class="bottom-line"></div>
+      </a>
+      <a class="material-tab-item" @click.prevent="currentMaterialType = '3D'">
+        <span class="text">三维场景</span>
+        <div v-if="currentMaterialType === '3D'" class="bottom-line"></div>
+      </a>
+    </div>
+    
+    <div class="filter">
+      <input type="text" placeholder="输入关键词" v-model="searchKey"/>
+      <i v-if="!searchKey" class="iconfont icon-editor_search search-icon"/>
+      <i v-if="searchKey" @click="searchKey=''" class="iconfont icontoast_red clear-icon"></i>
+    </div>
+
+    <div class="table table-pano" v-show="currentMaterialType === 'pano'">
+      <div class="table-head-row">
+        <span class="table-head">1</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersForPano" :key="i">{{item.name}}</span>
+      </div>
+      <div
+        v-if="panoList.length !== 0"
+        class="table-body"
+      >
+        <div class="table-body-row" v-for="(item,i) in panoList" :key="i">
+          <span class="table-data">
+            <div class="checkbox">
+              <!-- 负责功能 -->
+              <input
+                type="checkbox"
+                @change="e => selectItem(item, e)"
+                :checked="select.some(i => i[primaryKey] === item[primaryKey])"
+              >
+              <!-- 负责外观 -->
+              <span class="for-outer-circle"></span>
+              <span class="for-inner-circle"></span>
+            </div>
+          </span>
+          <span class="table-data" v-for="(sub,idx) in tableHeadersForPano" :key="idx">
+            <div v-if="sub.type=='image'" class="list-img">
+              <img :src="item.icon + `?x-oss-process=image/resize,p_10&${Math.random()}`" alt="">
+            </div>
+            <span class="ellipsis" v-else v-title="item.sceneTitle">{{item.sceneTitle}}</span>
+          </span>
+        </div>
+      </div>
+      <!-- 无数据时的提示 -->
+      <div v-if="panoList.length === 0" class="no-data">
+        <div v-if="latestUsedSearchKey">
+          <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
+          <span>{{'未搜索到结果~'}}</span>
+        </div>
+        <div v-if="!latestUsedSearchKey">
+          <img :src="require('@/assets/images/default/empty_04.png')" alt="">
+          <span>{{'暂无素材~'}}</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="table table-3D" v-show="currentMaterialType === '3D'">
+      <div class="table-head-row">
+        <span class="table-head">1</span>
+        <span class="table-head" v-for="(item,i) in tableHeadersFor3D" :key="i">{{item.name}}</span>
+      </div>
+      <div
+        v-if="scene3DList.length !== 0"
+        class="table-body"
+      >
+        <div class="table-body-row" v-for="(item,i) in scene3DList" :key="i">
+          <span class="table-data">
+            <div class="checkbox">
+              <!-- 负责功能 -->
+              <input
+                type="checkbox"
+                @change="e => selectItem(item, e)"
+                :checked="select.some(i => i[primaryKey] === item[primaryKey])"
+              >
+              <!-- 负责外观 -->
+              <span class="for-outer-circle"></span>
+              <span class="for-inner-circle"></span>
+            </div>
+          </span>
+          <span class="table-data" v-for="(sub,idx) in tableHeadersFor3D" :key="idx">
+            <div v-if="sub.type=='image'" class="list-img">
+              <img :src="item.icon + `?x-oss-process=image/resize,p_10&${Math.random()}`" alt="">
+            </div>
+            <span class="ellipsis" v-else v-title="item.sceneTitle">{{item.sceneTitle}}</span>
+          </span>
+        </div>
+      </div>
+      <!-- 无数据时的提示 -->
+      <div v-if="scene3DList.length === 0" class="no-data">
+        <div v-if="latestUsedSearchKey">
+          <img :src="require('@/assets/images/default/empty_04_search.png')" alt="">
+          <span>{{'未搜索到结果~'}}</span>
+        </div>
+        <div v-if="!latestUsedSearchKey">
+          <img :src="require('@/assets/images/default/empty_04.png')" alt="">
+          <span>{{'暂无素材~'}}</span>
+        </div>
+      </div>
+    </div>
+
+    <div class="btns">
+      <div>
+        <button class="ui-button deepcancel" @click="$emit('cancle')">取消</button>
+        <button class="ui-button submit" :class="{disable: !select.length}" @click="$emit('submit', select)">
+          确定
+        </button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from "vuex";
+
+export default {
+  props:{
+    primaryKey: {
+      default: 'id'
+    },
+    isMultiSelection: {
+      type: Boolean,
+      default: false,
+    }
+  },
+  components:{
+  },
+  computed:{
+    ...mapGetters([
+      'info',
+    ]),
+    tableHeadersForPano() {
+      return this.$MAPTABLEHEADER['pano'].filter(item => {
+        return ['icon', 'name'].includes(item.key)
+      })
+    },
+    tableHeadersFor3D() {
+      return this.$MAPTABLEHEADER['scene'].filter(item => {
+        return ['thumb', 'sceneName'].includes(item.key)
+      })
+    },
+    panoList() {
+      return this.info.scenes.filter((item) => {
+        return item.type === 'pano'
+      }).filter((item) => {
+        if (this.searchKey) {
+          return item.sceneTitle.includes(this.searchKey)
+        } else {
+          return item
+        }
+      })
+    },
+    scene3DList() {
+      return this.info.scenes.filter((item) => {
+        return item.type === '4dkk'
+      }).filter((item) => {
+        if (this.searchKey) {
+          return item.sceneTitle.includes(this.searchKey)
+        } else {
+          return item
+        }
+      })
+    }
+  },
+  data () {
+    return {
+      select: [],
+      searchKey:'', // 搜索关键词
+      latestUsedSearchKey: '',
+      currentMaterialType: 'pano',
+    }
+  },
+
+  methods: {
+    selectItem(item, e) {
+      item.materialType = this.currentMaterialType  // 三维场景数据没有type字段来表明自己是三维场景。所以统一加一个字段。
+      if (false) {
+        // 对于图片,大于600kb的,压缩?
+      } else {
+        if (this.isMultiSelection) {
+          if (e.target.checked) {
+            this.select.push(item)
+          } else {
+            const toDeleteIdx = this.select.findIndex((eachSelect) => {
+              return eachSelect.id === item.id
+            })
+            if (toDeleteIdx >= 0) {
+              this.select.splice(toDeleteIdx, 1)
+            }
+          }
+        } else {
+          if (e.target.checked) {
+            this.select = [item]
+          } else {
+            this.select = []
+          }
+        }
+      }
+    },
+  },
+  mounted() {
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.ellipsis{
+  text-overflow: ellipsis;
+  overflow: hidden;
+  white-space: nowrap;
+  width: 100%;
+  display: inline-block;
+}
+
+.table-select {
+  position: absolute;
+  z-index: 3;
+  left: 50%;
+  top: 50%;
+  transform: translateX(-50%) translateY(-50%);
+  width: 600px;
+  height: 730px;
+  background: #1A1B1D;
+  border-radius: 4px;
+  border: 1px solid #404040;
+  padding: 26px;
+}
+
+.title {
+  font-size: 18px;
+  color: rgba(255, 255, 255, 0.6);
+}
+
+.close-btn {
+  display: inline-block;
+  position: absolute;
+  top: 26px;
+  right: 20px;
+  font-size: 12px;
+  color: #969799;
+  cursor: pointer;
+  padding: 6px;
+}
+
+.material-tab {
+  margin-top: 35px;
+  > .material-tab-item {
+    display: inline-block;
+    margin-right: 20px;
+    position: relative;
+    cursor: pointer;
+    > .text {
+      font-size: 14px;
+      font-family: MicrosoftYaHei;
+      color: rgba(255, 255, 255, 0.6);
+    }
+    > .bottom-line {
+      position: absolute;
+      left: 50%;
+      transform: translateX(-50%);
+      bottom: -4px;
+      width: 16px;
+      height: 2px;
+      background: #0076F6;
+      border-radius: 1px;
+    }
+  }
+}
+
+.filter {
+  margin-top: 28px;
+  width: 100%;
+  height: 36px;
+  background: #252526;
+  border-radius: 2px;
+  border: 1px solid #404040;
+  position: relative;
+  > input {
+    box-sizing: border-box;
+    width: calc(100% - 42px);
+    height: 100%;
+    border: none;
+    padding-left: 16px;
+    background: transparent;
+    color: #fff;
+    outline: none;
+  }
+  > .search-icon {
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+    right: 18px;
+    color: #404040;
+    font-size: 20px;
+  }
+  > .clear-icon {
+    position: absolute;
+    top: 50%;
+    transform: translateY(-50%);
+    right: 18px;
+    color: #404040;
+    font-size: 20px;
+    cursor: pointer;
+  }
+}
+
+@table-height: 440px;
+@table-head-row-height: 40px;
+@table-border-size: 1px;
+
+.table {
+  margin-top: 20px;
+  border: @table-border-size solid #404040;
+  background: #1A1B1D;
+  width: 100%;
+  height: @table-height;
+  > .table-head-row {
+    width: 100%;
+    height: @table-head-row-height;
+    background: #252526;
+    color: rgba(255, 255, 255, 0.6);
+    .table-head {
+      font-size: 16px;
+      line-height: @table-head-row-height;
+      height: 100%;
+      display: inline-block;
+    }
+  }
+  > .table-body {
+    height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
+    overflow: auto;
+    display: inline-block;
+    width: 100%;
+    > .table-body-row {
+      height: 50px;
+      border-bottom: 1px solid #404040;
+      display: flex;
+      align-items: center;
+      > .table-data {
+        font-size:14px;
+        line-height:50px;
+        height: 100%;
+        color: #fff;
+        > .list-img {
+          position: relative;
+          height: 100%;
+          display: inline-block;
+          width: 100%;
+          > img {
+            position: absolute;
+            top: 50%;
+            transform: translateY(-50%);
+            width: 40px;
+            height: 40px;
+            object-fit: cover;
+          }
+        }
+      }
+    }
+  }
+  > .no-data {
+    height: calc(@table-height - @table-head-row-height - @table-border-size - @table-border-size);
+    width: 100%;
+    position: relative;
+    > div {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      text-align: center;
+      > img {
+        width: 116px;
+      }
+      > span {
+        margin-top: 20px;
+        display: block;
+        font-size: 14px;
+        color: rgba(255, 255, 255, 0.6);
+      }
+    }
+  }
+}
+
+.table-pano .table-head,
+.table-pano .table-data {
+  &:nth-of-type(1) {
+    width: 50px;
+    color: transparent;
+  }
+  &:nth-of-type(2) {
+    width: calc(116px - 50px);
+  }
+  &:nth-of-type(3) {
+    width: calc(416px - 116px);
+    padding-right: 30px;
+  }
+  &:nth-of-type(4) {
+    width: calc(100% - 416px);
+  }
+}
+
+.table-3D .table-head,
+.table-3D .table-data {
+  &:nth-of-type(1) {
+    width: 50px;
+    color: transparent;
+  }
+  &:nth-of-type(2) {
+    width: calc(116px - 50px);
+  }
+  &:nth-of-type(3) {
+    width: calc(416px - 116px);
+    padding-right: 30px;
+  }
+  &:nth-of-type(4) {
+    width: calc(100% - 416px);
+  }
+}
+
+.checkbox {
+  position: relative;
+  width: 100%;
+  height: 100%;
+  input {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    cursor: pointer;
+    opacity: 0;
+  }
+  .for-outer-circle {
+    width: 16px;
+    height: 16px;
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    border-radius: 50%;
+    border: 1px solid #404040;
+    pointer-events: none;
+  }
+  .for-inner-circle {
+    width: 8px;
+    height: 8px;
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    border-radius: 50%;
+    background: #0076F6;
+    pointer-events: none;
+    opacity: 0;
+  }
+}
+
+.checkbox > input:checked ~ .for-outer-circle {
+  border: 1px solid #0076F6;
+}
+
+.checkbox > input:checked ~ .for-inner-circle {
+  opacity: 1;
+}
+
+.checkbox > input:disabled {
+  cursor: not-allowed;
+}
+
+.btns {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 40px;
+  .upload-btn {
+    display: flex;
+    align-items: center;
+    > span {
+      display: inline-block;
+      margin-right: 4px;
+    }
+    i.tool-tip-for-editor {
+      font-size: 12px;
+      transform: scale(0.923) translateY(1px);
+      cursor: default;
+    }
+  }
+  > div {
+    .deepcancel {
+      margin-right: 16px;
+    }
+  }
+}
+</style>

+ 1 - 0
packages/code/src/components/select.vue

@@ -1,4 +1,5 @@
 <template>
+  <!-- todo: 旧版的初始场景设置时弹窗,可以删了? -->
   <div class="select-commodity">
     <a class="close" @click="$emit('cancle')">+</a>
     <h3 class="title">{{ title }}</h3>

+ 10 - 16
packages/code/src/views/navigation/initialSceneSettings.vue

@@ -20,16 +20,14 @@
       </button>
     </div>
 
-    <!-- <div class="dialog" style="z-index: 2000" v-if="showInitScene">
-      <MaterialSelectorForEditor
-        :selectableType="['image', 'pano', '3D']"
-        title="选择素材"
+    <div class="dialog" style="z-index: 2000" v-if="showInitScene">
+      <Selector
         @cancle="showInitScene = false"
         @submit="handleSelect"
       />
-    </div> -->
+    </div>
 
-    <div class="dialog" style="z-index: 2000" v-if="showInitScene">
+    <!-- <div class="dialog" style="z-index: 2000" v-if="showInitScene">
       <Select
         @cancle="showInitScene = false"
         :selected='info.firstScene'
@@ -37,17 +35,17 @@
         @submit="handleSelect"
       >
       </Select>
-    </div>
+    </div> -->
   </div>
 </template>
 
 <script>
 import { mapGetters } from "vuex";
-import Select from "@/components/select";
+import Selector from "@/components/materialSelectorFromWorkForEditor.vue";
 
 export default {
   components:{
-    Select,
+    Selector,
   },
   data(){
     return {
@@ -66,21 +64,17 @@ export default {
       });
       
     },
-    handleSelect(data){
-      this.info.firstScene = data
-      this.$store.commit("SetInfo", this.info);
-      console.log(this.info.firstScene);
-      this.showInitScene=false
+    handleSelect(data) {
+      this.info.firstScene = data[0] // 注意此处是浅拷贝
+      this.showInitScene = false
     }
   },
   computed: {
     ...mapGetters({
       info: "info",
-      backupInfo: "backupInfo"
     })
   },
   mounted(){
- 
   }
 }
 </script>