فهرست منبع

管理中心:创建新作品 流程复杂化

任一存 2 سال پیش
والد
کامیت
60e55a7780

+ 2 - 2
packages/qjkankan-editor/src/api/index.js

@@ -123,7 +123,7 @@ export function getUserInfo(ok, no) {
  * @param {*} no 
  */
  export function getSceneList(data, ok, no) {
-    return http.postJson(`${URL_FILL}/manage/work/select/4dkk/${number()}`, data, ok, no)
+    return http.postJson(`${URL_FILL}/manage/work/select/4dkk/${data.workId || number()}`, data, ok, no)
 }
 
 
@@ -531,7 +531,7 @@ export function setListSort(data, ok, no) {
  * @param {*} no 
  */
  export function saveWorks(data, ok, no) {
-    data.id = number()
+    !data.id && (data.id = number())
 
     return http.postJson(`${URL_FILL}/manage/work/edit`, data, ok, no)
 }

+ 3 - 1
packages/qjkankan-editor/src/components/materialSelectorForEditor.vue

@@ -493,7 +493,9 @@
         <i class="iconfont icon-material_prompt tool-tip-for-editor"
           v-tooltip="
             currentMaterialType === 'image' ? '请上传10MB以内、jpg/png格式的图片' :
-            currentMaterialType === 'pano' ? '请上传2:1、120MB以内、jpg格式的图片' : ''
+            currentMaterialType === 'pano' ? '请上传2:1、120MB以内、jpg格式的图片' :
+            currentMaterialType === 'audio' ? '请上传20MB以内、mp3格式的音频' :
+            currentMaterialType === 'video' ? '请上传200MB以内、mp4格式的视频' : ''
           ">
         </i>
         <FileInput

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1728 - 0
packages/qjkankan-editor/src/components/materialSelectorForManageCenter.vue


+ 9 - 0
packages/qjkankan-editor/src/components/shared/message/Confirm.vue

@@ -29,6 +29,7 @@
             <div v-else class="ui-message-footer"  :class="{'footer-material':isMaterial}">
                 <button class="ui-button cancel" :class="{deepcancel:!isMaterial}" @click="onNo">{{noText}}</button>
                 <button class="ui-button submit" @click="onOk">{{okText}}</button>
+                <button v-if="ok2" class="ui-button submit" @click="onOk2">{{ok2Text}}</button>
             </div>
         </div>
     </popup>
@@ -52,10 +53,12 @@ export default {
             icon: null,
             content: "",
             okText: i18n.t("common.set"),
+            ok2Text: i18n.t("common.set"),
             noText: i18n.t("common.giveup"),
             okLink: null,
             noLink: null,
             ok: null,
+            ok2: null,
             no: null
         };
     },
@@ -66,6 +69,12 @@ export default {
             }
             this.onClose();
         },
+        onOk2() {
+          if (this.ok2 && this.ok2(this) === false) {
+              return;
+          }
+          this.onClose();
+        },
         onNo() {
             this.no && this.no();
             this.onClose();

+ 93 - 0
packages/qjkankan-editor/src/directives/vTitleInManageCenter.js

@@ -0,0 +1,93 @@
+import Vue from 'vue'
+
+let timerId = null
+let isShowTitle = false
+let titleNode = null
+
+Vue.directive('title', {
+  bind: function (el, binding) {
+    if (!binding.value) {
+      return
+    }
+    el.addEventListener('mousemove', function(e) {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+        timerId = setTimeout(() => {
+          isShowTitle = true
+
+          titleNode = document.createElement('div')
+
+          titleNode.style.position = 'fixed',
+          titleNode.style.zIndex = 100,
+          titleNode.style.backgroundColor = '#ffffff'
+          titleNode.style.borderRadius = '2px'
+          titleNode.style.border = '1px solid rgba(151, 151, 151, 0.2)'
+          titleNode.style.padding = '2px 6px'
+          titleNode.style.fontSize = '12px'
+          titleNode.style.color = '#323233'
+          titleNode.innerText = binding.value
+          titleNode.style.left = e.clientX + 11 + 'px'
+          titleNode.style.top = e.clientY + 18 + 'px'
+
+          document.body.appendChild(titleNode)
+          if (e.clientX + 11 + titleNode.offsetWidth > document.documentElement.clientWidth) {
+            titleNode.style.left = document.documentElement.clientWidth - titleNode.offsetWidth + 'px'
+          }
+          if (e.clientY + 18 + titleNode.offsetHeight > document.documentElement.clientHeight) {
+            titleNode.style.top = document.documentElement.clientHeight - titleNode.offsetHeight + 'px'
+          }
+        }, 500);
+      }
+    }, {
+      passive: false,
+    })
+    el.addEventListener('mouseleave', function () {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+      } else {
+        isShowTitle = false
+        document.body.removeChild(titleNode)
+      }
+    })
+    el.addEventListener('mousedown', function () {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+      } else {
+        isShowTitle = false
+        document.body.removeChild(titleNode)
+      }
+    })
+    el.addEventListener('keydown', function () {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+      } else {
+        isShowTitle = false
+        document.body.removeChild(titleNode)
+      }
+    })
+    el.addEventListener('scroll', function () {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+      } else {
+        isShowTitle = false
+        document.body.removeChild(titleNode)
+      }
+    })
+    el.addEventListener('dragover', function () {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+      } else {
+        isShowTitle = false
+        document.body.removeChild(titleNode)
+      }
+    })
+    el.addEventListener('dragleave', function () {
+      if (!isShowTitle) {
+        clearTimeout(timerId)
+      } else {
+        isShowTitle = false
+        document.body.removeChild(titleNode)
+      }
+    })
+  },
+})

+ 127 - 0
packages/qjkankan-editor/src/directives/vTooltipInManageCenter.js

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

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

@@ -7,6 +7,8 @@ import 'viewerjs/dist/viewer.css'
 import Viewer from 'v-viewer'
 import { showLoginTips } from '@/utils/request'
 import { Button } from 'element-ui';
+import '@/directives/vTitleInManageCenter.js'
+import '@/directives/vTooltipInManageCenter.js'
 
 Vue.component(Button.name, Button);
 

+ 150 - 29
packages/qjkankan-editor/src/views/material/works/index.vue

@@ -95,6 +95,17 @@
       :dark="false"
       @close="showPreview = false"
     />
+    <div class="dialog" style="z-index: 10" v-if="isShowMaterialSelector">
+      <MaterialSelector
+        title="选择素材"
+        @cancle="isShowMaterialSelector = false"
+        @submit="handleSubmitFromMaterialSelector"
+        :selectableType="['pano', '3D']"
+        :isMultiSelection="true"
+        :workId="newWorkId"
+        initialMaterialType="pano"
+      />
+    </div>
   </div>
 </template>
 
@@ -104,12 +115,16 @@ import preview from "@/components/preview";
 import workCardSkeleton from "@/components/workCardSkeleton.vue";
 import config from "@/config";
 import { debounce } from "@/utils/other.js"
+import MaterialSelector from "@/components/materialSelectorForManageCenter.vue";
+import { mapGetters } from "vuex";
+import Popup from "@/components/shared/popup";
 
 import {
   addWorks,
   getWorksList,
   delWorks,
-  getPanoInfo
+  getPanoInfo,
+  saveWorks,
 } from "@/api";
 
 export default {
@@ -117,6 +132,12 @@ export default {
     share,
     preview,
     workCardSkeleton,
+    MaterialSelector,
+  },
+  computed: {
+    ...mapGetters([
+      'info',
+    ])
   },
   data(){
     return {
@@ -141,6 +162,9 @@ export default {
       isShowBackTopBtn: false,
 
       isShowMask: false,
+
+      isShowMaterialSelector: false,
+      newWorkId: '',
     }
   },
   mounted(){
@@ -190,9 +214,102 @@ export default {
       })
     },
     add(){
-      addWorks({},(data)=>{
-        window.open(`./edit.html?id=${data.data.id}`)
-      })
+      // 新建作品,弹窗让用户给作品选择素材。
+      addWorks(
+        {},
+        (res) => {
+          this.newWorkId = res.data.id
+          this.isShowMaterialSelector = true
+        },
+      )
+    },
+    handleSubmitFromMaterialSelector(selected) {
+      // 拿新作品的初始数据
+      getPanoInfo(
+        this.newWorkId,
+        // 拿到了。
+        (data) => {
+          // 往里边添加用户选中的素材。
+          this.$store.commit("SetInfo", data);
+          for (const item of selected) {
+            if (item.materialType === 'pano') {
+              this.info.scenes.push({
+                icon: item.icon,
+                sceneCode: item.sceneCode,
+                sceneTitle: item.name,
+                category: this.info.catalogs[0].id,
+                type: "pano",
+                id: 's_' + this.$randomWord(true, 8, 8)
+              })
+            } else if (item.materialType === '3D') {
+              this.info.scenes.push({
+                icon: item.thumb,
+                sceneCode: item.num,
+                sceneTitle: item.sceneName,
+                category: this.info.catalogs[0].id,
+                type: "4dkk",
+                id:'s_'+this.$randomWord(true,8,8)
+              })
+            }
+          }
+
+          // 保存新作品
+          saveWorks(
+            {
+              id: this.newWorkId,
+              password: '',
+              someData: { ...this.info, status: 1 },
+            },
+            // 保存成功
+            () => {
+              // 隐藏素材选择弹窗
+              this.isShowMaterialSelector = false
+
+              // 刷新作品列表
+              this.list = []
+              this.isRequestingMoreData = false
+              this.hasMoreData = true
+              this.requestMoreData().then(() => {
+                // 刷新成功
+
+                // 弹出提示窗口
+                this.$confirm({
+                  title:'提示',
+                  content: "您已成功创建作品!",
+                  okText: '预览一下',
+                  ok: () => {
+                    this.handlePreview(this.list[0])
+                    this.newWorkId = ''
+                    this.$store.commit("SetInfo", {});
+                  },
+                  ok2Text: '继续编辑',
+                  ok2: () => {
+                    window.open(`./edit.html?id=${this.newWorkId}`)
+                    this.newWorkId = ''
+                    this.$store.commit("SetInfo", {});
+                  },
+                });
+              }).catch(() => {
+                this.$msg.message('已成功新建作品,但刷新作品列表失败,请稍后手动刷新。')
+                console.error('已成功新建作品,但刷新作品列表失败。')
+              })
+            },
+            // 保存失败,删除新建的作品。
+            (error) => {
+              console.error('保存失败:', error);
+              delWorks(this.newWorkId)
+              this.newWorkId = ''
+              this.$store.commit("SetInfo", {});
+            }
+          );
+        },
+        // 没拿到,删除新建的作品。
+        (error) => {
+          console.error('没拿到新建的作品数据:', error);
+          delWorks(this.newWorkId)
+          this.newWorkId = ''
+        }
+      )
     },
     edit(item){
         window.open(`./edit.html?id=${item.id}`)
@@ -240,32 +357,36 @@ export default {
     requestMoreData() {
       this.isRequestingMoreData = true
       const lastestUsedSearchKey = this.searchKey
-      getWorksList(
-        {
-          pageNum: Math.floor(this.list.length / config.PAGE_SIZE) + 1,
-          pageSize: config.PAGE_SIZE,
-          searchKey: this.searchKey,
-        },
-        (data) => {
-          this.list = this.list.concat(data.data.list)
-          if (this.list.length === data.data.total) {
-            this.hasMoreData = false
-          }
-          this.isRequestingMoreData = false
-          this.lastestUsedSearchKey = lastestUsedSearchKey
-          if (!lastestUsedSearchKey) {
-            this.workTotalNum = data.data.total
+      return new Promise((resolve, reject) => {
+        getWorksList(
+          {
+            pageNum: Math.floor(this.list.length / config.PAGE_SIZE) + 1,
+            pageSize: config.PAGE_SIZE,
+            searchKey: this.searchKey,
+          },
+          (data) => {
+            this.list = this.list.concat(data.data.list)
+            if (this.list.length === data.data.total) {
+              this.hasMoreData = false
+            }
+            this.isRequestingMoreData = false
+            this.lastestUsedSearchKey = lastestUsedSearchKey
+            if (!lastestUsedSearchKey) {
+              this.workTotalNum = data.data.total
+            }
+            // TODO: 这是干啥呢?
+            this.$nextTick(()=>{
+              this.$bus.emit('refreshTips')
+            })
+            resolve()
+          },
+          () => {
+            this.isRequestingMoreData = false
+            this.lastestUsedSearchKey = lastestUsedSearchKey
+            reject()
           }
-          // TODO: 这是干啥呢?
-          this.$nextTick(()=>{
-            this.$bus.emit('refreshTips')
-          })
-        },
-        () => {
-          this.isRequestingMoreData = false
-          this.lastestUsedSearchKey = lastestUsedSearchKey
-        }
-      );
+        );
+      })
     },
     onClickBackTop() {
       if (this.isBackingTop) {