瀏覽代碼

Merge branch 'master' of http://192.168.0.115:3000/bill/fuse-code

xzw 2 年之前
父節點
當前提交
0dbc77c549

+ 7 - 1
src/api/instance.ts

@@ -2,7 +2,7 @@ import { axiosFactory } from './setup'
 import { Message } from 'bill/index'
 import { showLoad, hideLoad } from '@/utils'
 import * as URL from './constant'
-import { ResCodeDesc } from './constant'
+import { ResCode, ResCodeDesc } from './constant'
 import { baseURL, params } from '@/env'
 
 const instance = axiosFactory()
@@ -34,6 +34,12 @@ addResErrorHandler(
     } else if (data) {
       const msg = data.code && ResCodeDesc[data.code] ? ResCodeDesc[data.code] : (data?.message || data?.msg)
       Message.error(msg)
+
+      if (data.code === ResCode.TOKEN_INVALID) {
+        setTimeout(() => {
+          location.href = '/'
+        }, 2000)
+      }
     }
   }
 )

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

@@ -11,7 +11,7 @@
         v-for="(item, i) in data" 
         :key="rawKey ? item.raw[rawKey] : i" 
         :class="{select: item.select}"
-        @click.stop="$emit('changeSelect', item)"
+        @click="$emit('changeSelect', item)"
       >
         <div class="atom-content">
           <slot name="atom" :item="item"></slot>

+ 2 - 1
src/layout/model-list/index.vue

@@ -23,6 +23,7 @@ import ModelSign from './sign.vue'
 import { fuseModels, getFuseModelShowVariable } from '@/store'
 
 import type { FuseModel } from '@/store'
+import { currentModel, fuseModel } from '@/model'
 
 export type ModelListProps = { 
   title?: string, 
@@ -41,7 +42,7 @@ defineEmits<{
 const modelList = computed(() => 
   fuseModels.value.map(model => ({
     raw: model,
-    select: custom.currentModel === model
+    select: custom.currentModel === model && currentModel.value === fuseModel
   }))
 )
 

+ 8 - 3
src/layout/model-list/sign.vue

@@ -1,7 +1,7 @@
 <template>
-  <div class="model-header" @click.stop="!model.error && $emit('click')">
+  <div class="model-header" @click="!model.error && $emit('click')">
     <p>{{ model.title }}</p>
-    <div class="model-action" @click.stop>
+    <div class="model-action">
       <ui-input type="checkbox" v-model="show" :class="{disabled: model.error}"/>
       <ui-icon 
         v-if="custom.modelsChangeStore" 
@@ -11,7 +11,7 @@
       />
     </div>
   </div>
-  <div class="model-desc" @click="$emit('click')" v-if="custom.currentModel === model">
+  <div class="model-desc" @click="$emit('click')" v-if="active">
     <p><span>数据来源:</span>{{ SceneTypeDesc[model.type] }}</p>
     <p><span>数据大小:</span>{{ model.size }}</p>
     <p><span>拍摄时间:</span>{{ model.time }}</p>
@@ -23,9 +23,14 @@ import { getFuseModelShowVariable, SceneTypeDesc } from '@/store'
 import { custom } from '@/env'
 
 import type { FuseModel } from '@/store'
+import { computed } from 'vue';
+import { currentModel, fuseModel } from '@/model';
 
 type ModelProps = { model: FuseModel, canChange?: boolean }
 const props = defineProps<ModelProps>()
+const active = computed(() => 
+  custom.currentModel === props.model && currentModel.value === fuseModel
+)
 
 type ModelEmits = {
   (e: 'changeSelect', selected: boolean): void

+ 5 - 4
src/layout/scene-list/index.vue

@@ -11,11 +11,12 @@
           class="scene-model-list"
           :class="{active: current === fuseModel}"
           :title="getModelTypeDesc(fuseModel as any)"
-          :show-content="current === fuseModel"
+          :show-content="showModelList"
         >
           <template #action>
             <ui-icon 
-              :type="`pull-${current === fuseModel ? 'up' : 'down'}`" 
+              :type="`pull-${showModelList ? 'up' : 'down'}`" 
+              @click="showModelList = !showModelList"
               ctrl 
             />
           </template>
@@ -30,7 +31,7 @@
 </template>
 
 <script lang="ts" setup>
-import { computed } from 'vue'
+import { computed, ref } from 'vue'
 import { scenes, SceneType, SceneTypeDesc, fuseModels } from '@/store'
 import List from '@/components/list/index.vue'
 import ModelList from '../model-list/index.vue'
@@ -41,6 +42,7 @@ import type { Scene } from '@/store'
 
 const emit = defineEmits<{ (e: 'update:current', data: ModelType): void }>()
 const props = defineProps<{ current: ModelType }>()
+const showModelList = ref(false)
 
 const list = computed(() => {
   const sceneList = scenes.value.map(scene => ({
@@ -63,7 +65,6 @@ const updateCurrent = (scene: FuseModelType | Scene) => {
     emit('update:current', { type: scene.type, num: scene.num })
   }
 }
-
 </script>
 
 <style lang="scss">

+ 27 - 10
src/layout/show/index.vue

@@ -1,12 +1,14 @@
 <template>
   <template v-if="loaded">
-    <SlideMenu />
-    
-    <router-view v-slot="{ Component }">
-      <keep-alive>
-        <component :is="Component" />
-      </keep-alive>
-    </router-view>
+    <div :class="{ hideLeft: !custom.showLeftPano }">
+      <SlideMenu />
+      
+      <router-view v-slot="{ Component }">
+        <keep-alive>
+          <component :is="Component" />
+        </keep-alive>
+      </router-view>
+    </div>
   </template>
 </template>
 
@@ -15,14 +17,24 @@ import { custom } from '@/env'
 import { ref } from 'vue'
 import { loadModel, fuseModel } from '@/model'
 import SlideMenu from './slide-menu.vue'
-import { initialFuseModels, initialScenes } from '@/store'
-
+import { 
+  initialFloders, 
+  initialFloderTypes, 
+  initialFuseModels, 
+  initialRecords, 
+  initialScenes, 
+  initialViews 
+} from '@/store'
 
 const loaded = ref(false)
 const initialSys = async () => {
   await Promise.all([
     initialFuseModels(),
-    initialScenes()
+    initialScenes(),
+    initialViews(),
+    initialRecords(),
+    initialFloders(),
+    initialFloderTypes()
   ])
   loaded.value = true
   loadModel(fuseModel)
@@ -36,4 +48,9 @@ initialSys()
   --editor-menu-width: 80px;
   --editor-head-height: 0px;
 }
+
+.hideLeft {
+  --editor-menu-left: calc(-1 * var(--editor-menu-width));
+  --left-pano-left: calc(var(--editor-menu-left) + var(--editor-menu-width) - var(--left-pano-width)) !important
+}
 </style>

+ 33 - 17
src/layout/show/slide-menu.vue

@@ -13,25 +13,40 @@
 
 <script lang="ts" setup>
 import { metas, RoutesName, router } from '@/router'
+import { views, records, floders } from '@/store';
+import { computed } from 'vue';
 
-const items = [
-  {
-    name: RoutesName.summaryShow,
-    ...metas[RoutesName.summaryShow]
-  },
-  {
-    name: RoutesName.viewShow,
-    ...metas[RoutesName.viewShow]
-  },
-  {
-    name: RoutesName.recordShow,
-    ...metas[RoutesName.recordShow]
-  },
-  {
-    name: RoutesName.folderShow,
-    ...metas[RoutesName.folderShow]
+const items = computed(() => {
+  const items = [
+    {
+      name: RoutesName.summaryShow,
+      ...metas[RoutesName.summaryShow]
+    }
+  ]
+
+  if (views.value.length) {
+    items.push({
+      name: RoutesName.viewShow,
+      ...metas[RoutesName.viewShow]
+    }) 
+  }
+
+  if (records.value.length) {
+    items.push({
+      name: RoutesName.recordShow,
+      ...metas[RoutesName.recordShow]
+    }) 
   }
-]
+
+  if (floders.value.length) {
+    items.push({
+      name: RoutesName.folderShow,
+      ...metas[RoutesName.folderShow]
+    }) 
+  }
+
+  return items
+})
 </script>
 
 <style lang="scss" scoped>
@@ -47,6 +62,7 @@ const items = [
   z-index: 2000;
   overflow: hidden;
   backdrop-filter: blur(4px);
+  transition: all .3s ease;
 
   > div {
     height: 70px;

+ 8 - 7
src/model/app.vue

@@ -8,9 +8,9 @@
 </template>
 
 <script lang="ts">
-import { defineComponent, ref, watchEffect, computed, watch, onMounted, nextTick } from 'vue'
+import { defineComponent, ref, watchEffect, computed, watch, nextTick } from 'vue'
 import { SceneType } from '@/store'
-import { params, showModelsMapStack } from '@/env'
+import { params } from '@/env'
 import { fuseModel, modelProps } from './index'
 import { modelSDKFactory } from './platform'
 
@@ -52,10 +52,6 @@ export const Model = defineComponent({
       async (type, oldType, onCleanup) => {
         const callback = modelProps.callback
 
-        if (oldType === fuseModel) {
-          onCleanup(showModelsMapStack.push(ref(new Map())))
-        }
-
         await nextTick()
         const { typePromise, typeCleanup } = typeChange()
         const modelPromise = modelSDKFactory(type, type === fuseModel ? fuseRef.value! : iframeRef.value!)
@@ -83,7 +79,6 @@ export default Model
 </script>
 
 <style scoped lang="scss">
-.external,
 .laser-layer {
   position: absolute;
   z-index: 1;
@@ -100,6 +95,12 @@ export default Model
 }
 
 .external {
+  position: absolute;
+  z-index: 1;
   border: none;
+  top: calc(var(--editor-head-height) + var(--header-top));
+  left: 0;
+  height: calc(100% - (var(--editor-head-height) + var(--header-top)));
+  width: 100%;
 }
 </style>

+ 0 - 5
src/views/folder/index.vue

@@ -26,17 +26,12 @@ import { LeftPano } from '@/layout'
 import { computed, ref } from 'vue';
 import { getUrlType, MetaType } from '@/utils'
 import { 
-  initialFloderTypes, 
-  initialFloders,
   floderTypes,
   getFloderByType,
 } from '@/store'
 
 import type { Floder } from '@/store'
 
-initialFloderTypes()
-initialFloders()
-
 const types = computed(() => 
   floderTypes.value.map(type => ({
     show: ref(true),

+ 7 - 4
src/views/record/index.vue

@@ -39,14 +39,17 @@ import { records, createRecord, Record, RecordStatus, autoSaveRecords, initialRe
 import { RightFillPano } from '@/layout'
 import Draggable from 'vuedraggable'
 import Sign from './sign.vue'
+import { Dialog } from 'bill/index'
 
 initialRecords()
 
 const start = () => records.value.push(createRecord())
-const deleteRecord = (record: Record) => {
-  const index = records.value.indexOf(record)
-  if (~index) {
-    records.value.splice(index, 1)
+const deleteRecord = async (record: Record) => {
+  if (await Dialog.confirm('确定要删除视频吗?')) {
+    const index = records.value.indexOf(record)
+    if (~index) {
+      records.value.splice(index, 1)
+    }
   }
 }
 

+ 1 - 2
src/views/record/show.vue

@@ -14,10 +14,9 @@
 
 <script setup lang="ts">
 import Sign from './sign.vue'
-import { records, initialRecords } from '@/store'
+import { records } from '@/store'
 import { LeftPano } from '@/layout'
 
-initialRecords()
 </script>
 
 <style lang="scss" scoped>

+ 11 - 4
src/views/record/sign.vue

@@ -1,5 +1,5 @@
 <template>
-  <ui-group-option class="sign">
+  <ui-group-option class="sign record-sign">
     <div class="content">
       <span class="cover">
         <img :src="getResource(getFileUrl(record.cover))" alt="" v-if="record.cover">
@@ -18,6 +18,7 @@
         v-show="isEditTitle" 
         ref="inputRef" 
         height="28px" 
+        :maxlength="15"
       />
       <div class="title" v-show="!isEditTitle">
         <p>{{ record.title }}</p>
@@ -51,7 +52,7 @@
 
 <script lang="ts">
 import { defineComponent, ref, computed, watchEffect } from 'vue'
-import { getFileUrl } from '@/utils'
+import { getFileUrl, getExtname } from '@/utils'
 import { useFocus } from 'bill/hook/useFocus'
 import { RecordStatus, createRecordFragment, getRecordFragmentBlobs, recordFragments } from '@/store'
 import { saveAs, loadPack } from '@/utils'
@@ -114,8 +115,8 @@ export default defineComponent({
       play: () => isPlayVideo.value = true,
       download() {
         const url = getResource(props.record.url)
-        const paths = url.split('/')
-        loadPack(saveAs(url, paths[paths.length - 1]))
+        const ext = getExtname(url) || 'mp4'
+        loadPack(saveAs(url, `${props.record.title}.${ext}`))
       },
     }
     props.record.immediately && actions.continue()
@@ -158,4 +159,10 @@ export default defineComponent({
 
 
 <style lang="scss" src="./style.scss" scoped>
+</style>
+
+<style>
+  .record-sign .ui-input .text.suffix input {
+    padding-right: 60px;
+  }
 </style>

+ 4 - 0
src/views/record/style.scss

@@ -18,6 +18,7 @@
 
 .tree {
   margin-top: 20px;
+  padding-bottom: 100px;
 }
 
 .header-btns {
@@ -54,6 +55,7 @@
     color: #fff;
     font-size: 16px;
     margin-right: 10px;
+    flex: none;
 
     img,
     &::before {
@@ -99,6 +101,8 @@
 .action {
   color: #fff;
   font-size: 14px;
+  flex: none;
+  margin-left: 10px;
 }
 
 .countdown {

+ 1 - 2
src/views/view/show.vue

@@ -13,10 +13,9 @@
 
 <script setup lang="ts">
 import Sign from './sign.vue'
-import { views, initialViews } from '@/store'
+import { views } from '@/store'
 import { LeftPano } from '@/layout'
 
-initialViews()
 </script>
 
 <style lang="scss" scoped>