浏览代码

修改架构

bill 3 年之前
父节点
当前提交
ac4e9b4021

+ 1 - 0
src/api/constant.ts

@@ -20,6 +20,7 @@ export const FUSE_UPDATE_MODEL = `/fusion/caseFusion/update`
 export const FUSE_DELETE_MODEL = `/fusion/caseFusion/delete`
 // 场景列表
 export const MODEL_LIST = `/fusion/case/sceneList`
+export const MODEL_SIGN = `/fusion/model/getInfo`
 
 // 标注列表
 export const TAGGING_LIST = `/fusion/caseTag/allList`

+ 6 - 1
src/api/scene.ts

@@ -1,5 +1,5 @@
 import axios from './instance'
-import { MODEL_LIST } from './constant'
+import { MODEL_LIST, MODEL_SIGN } from './constant'
 import { params } from '@/env'
 
 export enum SceneType {
@@ -47,3 +47,8 @@ export const fetchScenes = async () => {
   const scenes = await axios.post<Scenes>(MODEL_LIST, { caseId: params.caseId })
   return scenes.map(toLocalScene)
 }
+
+export const fetchScene = async (modelId: Scene['modelId']) => {
+  const scene = await axios.get<Scene>(MODEL_SIGN, { params: { modelId } })
+  return toLocalScene(scene)
+}

+ 0 - 1
src/api/tagging-position.ts

@@ -47,7 +47,6 @@ export const fetchTaggingPositions = async (taggingId: Tagging['id']) => {
 }
 
 export const postAddTaggingPosition = async (position: TaggingPosition) => {
-  console.error(position, localToService(position))
   const servicePosition = await axios.post<ServicePosition>(INSERT_TAGGING_POINT, localToService(position))
   return serviceToLocal(servicePosition)
 }

+ 84 - 23
src/app.vue

@@ -1,32 +1,93 @@
 <template>
-  <component :is="Component" v-if="Component" />
+  <ui-editor-layout 
+    @click.stop 
+    id="layout-app" 
+    class="editor-layout" 
+    :style="layoutStyles" 
+    :class="layoutClassNames"
+  >
+    <div :ref="el => appEl = (el as HTMLDivElement)">
+      <router-view v-slot="{ Component }">
+        <keep-alive>
+          <component :is="Component" />
+        </keep-alive>
+      </router-view>
+    </div>
+  </ui-editor-layout>
 </template>
 
 <script lang="ts" setup>
-import { computed, ref } from 'vue'
-import { initialFuseModels, initialScenes } from '@/store'
-import { loadComponent, loadPack } from '@/utils'
-
-const loaded = ref(false)
-const error = ref(false)
-loadPack(async () => {
-  try {
-    await Promise.all([
-      initialFuseModels(),
-      initialScenes()
-    ])
-    loaded.value = true
-  } catch {
-    error.value = true
+import { custom } from '@/env'
+import { computed } from 'vue'
+import { isEdit, appEl } from '@/store'
+
+const layoutClassNames = computed(() => {
+  return {
+    [`sys-view-${custom.viewMode}`]: true,
+    'edit-mode': isEdit.value || custom.showToolbar,
+    'setting-mode': custom.showToolbar,
+    'hide-right-box-mode': !custom.showRightPano,
+    'hide-left-box-mode': !custom.showLeftPano,
+    'show-bottom-box-mode': custom.showBottomBar,
+    'hide-top-bar-mode': !custom.showHeadBar
   }
 })
 
-const Main = loadComponent(() => import('@/layout/main.vue'))
-const Err = loadComponent(() => import('@/components/error/index.vue'))
-
-const Component = computed(() => {
-  if (loaded.value) {
-    return error.value ? Err : Main
+const layoutStyles = computed(() => {
+  const styles: {[key in string]: string} = {}
+  if (custom.showBottomBar) {
+    styles['--editor-menu-bottom'] = custom.bottomBarHeight
   }
+
+  return styles
 })
-</script>
+
+</script>
+
+<style scoped lang="scss">
+.editor-layout {
+  --editor-menu-bottom: 0px;
+  --left-pano-left: calc(var(--editor-menu-left) + var(--editor-menu-width));
+}
+
+.sys-view-full {
+  --header-top: var(--hide-header-top);
+  --editor-menu-right: calc(-1 * var(--editor-toolbox-width)) !important;
+  --editor-menu-left: calc(-1 * var(--editor-menu-width));
+  --search-left: 52px;
+}
+
+
+.sys-view-auto {
+  --header-top: var(--show-header-top);
+  --search-left: 0px;
+}
+
+
+.hide-top-bar-mode {
+  --header-top: var(--hide-header-top);
+}
+
+.hide-right-box-mode {
+  --editor-menu-right: calc(-1 * var(--editor-toolbox-width)) !important;
+}
+
+.hide-left-box-mode {
+  --left-pano-left: calc(var(--editor-menu-left) + var(--editor-menu-width) - var(--left-pano-width)) !important;
+}
+.edit-mode {
+  --editor-menu-left: calc(-1 * var(--editor-menu-width));
+}
+
+.laser-layer {
+  position: absolute;
+  z-index: 1;
+  inset: 0;
+
+  .scene {
+    width: 100%;
+    height: 100%;
+    background-color: #ccc;
+  }
+}
+</style>

+ 1 - 5
src/components/tagging/list.vue

@@ -31,11 +31,7 @@ const isShowSign = (modelId: string) => {
   return model?.loaded && getFuseModelShowVariable(model).value
 }
 
-const positions = computed(() => {
-  const positions = getTaggingPositions(props.tagging)
-  console.error(positions)
-  return positions
-})
+const positions = computed(() => getTaggingPositions(props.tagging))
 
 const deletePosition = (pos: TaggingPosition) => {
   const index = taggingPositions.value.indexOf(pos)

+ 17 - 8
src/layout/edit/fuse-edit.vue

@@ -19,6 +19,8 @@ import {
   enterEdit, 
   isOld, 
   save, 
+  initialFuseModels,
+  initialScenes,
   initialTaggingStyles, 
   initialTaggings, 
   initialGuides, 
@@ -28,14 +30,21 @@ import {
 import Header from './header/index.vue'
 
 const loaded = ref(false)
-Promise.all([
-  initialTaggingStyles(),
-  initialTaggings(),
-  initialGuides(),
-  initialMeasures()
-])
-.then(() => loadModel(fuseModel))
-.then(() => loaded.value = true)
+const initialSys = async () => {
+  await Promise.all([
+    initialFuseModels(),
+    initialScenes()
+  ])
+  await Promise.all([
+    initialTaggingStyles(),
+    initialTaggings(),
+    initialGuides(),
+    initialMeasures()
+  ])
+  await loadModel(fuseModel)
+  loaded.value = true
+}
+initialSys()
 
 router.beforeEach(async (to, from, next) => {
   if (to.params.save && isOld.value) {

+ 2 - 13
src/layout/edit/fuse-left-pano.vue

@@ -16,19 +16,14 @@
     </ModelList>
   </LeftPano>
 
-  <SelectModel 
-    :select-ids="fuseModels.map(item => item.modelId)"
-    @close="insertMode = false" 
-    @select="addModelsHandler"
-    v-if="insertMode" 
-  />
+  <SelectModel @close="insertMode = false" v-if="insertMode" />
 </template>
 
 <script lang="ts" setup>
 import { watchEffect, ref } from 'vue'
 import { custom } from '@/env'
 import { getSceneModel } from '@/sdk'
-import { fuseModels, getFuseModelShowVariable, createFuseModels, Scene, addFuseModel } from '@/store'
+import { fuseModels, getFuseModelShowVariable } from '@/store'
 
 import ModelList from '../model-list/index.vue'
 import SelectModel from './scene-select.vue'
@@ -63,10 +58,4 @@ const modelDelete = (model: FuseModel) => {
   console.log(fuseModels.value.length)
 }
 
-const addModelsHandler = (modelIds: Scene['modelId'][]) => {
-  modelIds
-    .filter(modelId => !fuseModels.value.some(model => model.modelId === modelId))
-    .map(modelId => createFuseModels({ modelId }))
-    .forEach(addFuseModel)
-}
 </script>

+ 24 - 11
src/layout/edit/scene-edit.vue

@@ -1,15 +1,16 @@
 <template>
-  <Header></Header>
-  <LeftPano>
-    <SceneList :current="currentModel" @update:current="loadModel" />
-  </LeftPano>
+  <template v-if="loaded">
+    <Header></Header>
+    <LeftPano>
+      <SceneList :current="currentModel" @update:current="loadModel" />
+    </LeftPano>
 
-  <router-view v-slot="{ Component }">
-    <keep-alive>
-      <component :is="Component" />
-    </keep-alive>
-  </router-view>
-  
+    <router-view v-slot="{ Component }">
+      <keep-alive>
+        <component :is="Component" />
+      </keep-alive>
+    </router-view>
+  </template>
 </template>
 
 <script setup lang="ts">
@@ -17,8 +18,20 @@ import Header from './header/index.vue'
 import SceneList from '../scene-list/index.vue'
 import { LeftPano } from '@/layout'
 import { custom } from '@/env'
-import { onMounted } from 'vue'
+import { onMounted, ref } from 'vue'
 import { currentModel, loadModel, fuseModel } from '@/model'
+import { initialFuseModels, initialScenes } from '@/store'
+
+
+const loaded = ref(false)
+const initialSys = async () => {
+  await Promise.all([
+    initialFuseModels(),
+    initialScenes()
+  ])
+  loaded.value = true
+}
+initialSys()
 
 onMounted(() => loadModel(fuseModel))
 custom.showLeftPano = true

+ 31 - 10
src/layout/edit/scene-select.vue

@@ -30,8 +30,10 @@
 
 <script lang="ts" setup>
 import { Modal, Input, Table } from 'ant-design-vue'
-import { computed, ref } from 'vue';
-import { scenes } from '@/store'
+import { computed, nextTick, ref, watchEffect } from 'vue';
+import { scenes, save } from '@/store'
+import { createLoadPack } from '@/utils'
+import { fuseModels, createFuseModels, addFuseModel, fuseModelsLoaded } from '@/store'
 
 import type { Scene } from '@/api'
 
@@ -39,21 +41,23 @@ type Key = Scene['modelId']
 
 const Search = Input.Search
 
-const props = defineProps<{selectIds: Key[]}>()
 const emit = defineEmits<{
   (e: 'close'): void
   (e: 'select', ids: Key[]): void
 }>()
 
+const selectIds = computed(() => fuseModels.value.map(item => item.modelId))
+
 const keyword = ref('')
 const filterScenes = computed(
   () => scenes.value.filter(item => item.name && item.modelId && item.name.includes(keyword.value))
 )
-
-const selects = ref<Key[]>(props.selectIds)
+const selects = ref<Key[]>(selectIds.value)
 const rowSelection: any = ref({
   selectedRowKeys: selects,
-  onChange: (ids: number[]) => selects.value = ids
+  onChange: (ids: number[]) => {
+    selects.value = Array.from(new Set(ids.concat(selectIds.value)))
+  }
 })
 const cloumns = [
   {
@@ -68,11 +72,28 @@ const cloumns = [
   }
 ]
 
-const okHandler = () => {
-  emit('select', selects.value)
-  emit('close')
-}
+const okHandler = createLoadPack(async () => {
+  const addPromises = selects.value
+    .filter(modelId => !fuseModels.value.some(model => model.modelId === modelId))
+    .map(modelId => createFuseModels({ modelId }))
+    .map(addFuseModel)
 
+  await Promise.all(addPromises)
+
+  await new Promise<void>((resolve) => {
+    nextTick(() => {
+      const stop = watchEffect(() => {
+        if (fuseModelsLoaded.value) {
+          nextTick(() => stop())
+          resolve()
+        }
+      })
+    })
+  })
+  await save()
+
+  emit('close')
+})
 </script>
 
 <style lang="scss" scoped>

+ 0 - 93
src/layout/main.vue

@@ -1,93 +0,0 @@
-<template>
-  <ui-editor-layout 
-    @click.stop 
-    id="layout-app" 
-    class="editor-layout" 
-    :style="layoutStyles" 
-    :class="layoutClassNames"
-  >
-    <div :ref="el => appEl = el as HTMLDivElement">
-      <router-view v-slot="{ Component }">
-        <keep-alive>
-          <component :is="Component" />
-        </keep-alive>
-      </router-view>
-    </div>
-  </ui-editor-layout>
-</template>
-
-<script lang="ts" setup>
-import { custom } from '@/env'
-import { computed } from 'vue'
-import { isEdit, appEl } from '@/store'
-
-const layoutClassNames = computed(() => {
-  return {
-    [`sys-view-${custom.viewMode}`]: true,
-    'edit-mode': isEdit.value || custom.showToolbar,
-    'setting-mode': custom.showToolbar,
-    'hide-right-box-mode': !custom.showRightPano,
-    'hide-left-box-mode': !custom.showLeftPano,
-    'show-bottom-box-mode': custom.showBottomBar,
-    'hide-top-bar-mode': !custom.showHeadBar
-  }
-})
-
-const layoutStyles = computed(() => {
-  const styles: {[key in string]: string} = {}
-  if (custom.showBottomBar) {
-    styles['--editor-menu-bottom'] = custom.bottomBarHeight
-  }
-
-  return styles
-})
-
-</script>
-
-<style scoped lang="scss">
-.editor-layout {
-  --editor-menu-bottom: 0px;
-  --left-pano-left: calc(var(--editor-menu-left) + var(--editor-menu-width));
-}
-
-.sys-view-full {
-  --header-top: var(--hide-header-top);
-  --editor-menu-right: calc(-1 * var(--editor-toolbox-width)) !important;
-  --editor-menu-left: calc(-1 * var(--editor-menu-width));
-  --search-left: 52px;
-}
-
-
-.sys-view-auto {
-  --header-top: var(--show-header-top);
-  --search-left: 0px;
-}
-
-
-.hide-top-bar-mode {
-  --header-top: var(--hide-header-top);
-}
-
-.hide-right-box-mode {
-  --editor-menu-right: calc(-1 * var(--editor-toolbox-width)) !important;
-}
-
-.hide-left-box-mode {
-  --left-pano-left: calc(var(--editor-menu-left) + var(--editor-menu-width) - var(--left-pano-width)) !important;
-}
-.edit-mode {
-  --editor-menu-left: calc(-1 * var(--editor-menu-width));
-}
-
-.laser-layer {
-  position: absolute;
-  z-index: 1;
-  inset: 0;
-
-  .scene {
-    width: 100%;
-    height: 100%;
-    background-color: #ccc;
-  }
-}
-</style>

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

@@ -1,21 +1,34 @@
 <template>
-  <SlideMenu />
-  
-  <router-view v-slot="{ Component }">
-    <keep-alive>
-      <component :is="Component" />
-    </keep-alive>
-  </router-view>
+  <template v-if="loaded">
+    <SlideMenu />
+    
+    <router-view v-slot="{ Component }">
+      <keep-alive>
+        <component :is="Component" />
+      </keep-alive>
+    </router-view>
+  </template>
 </template>
 
 <script lang="ts" setup>
 import { custom } from '@/env'
-import { onMounted } from 'vue'
+import { ref } from 'vue'
 import { loadModel, fuseModel } from '@/model'
 import SlideMenu from './slide-menu.vue'
+import { initialFuseModels, initialScenes } from '@/store'
 
-onMounted(() => loadModel(fuseModel))
-custom.showLeftPano = true
+
+const loaded = ref(false)
+const initialSys = async () => {
+  await Promise.all([
+    initialFuseModels(),
+    initialScenes()
+  ])
+  loaded.value = true
+  loadModel(fuseModel)
+  custom.showLeftPano = true
+}
+initialSys()
 </script>
 
 <style>

+ 7 - 6
src/sdk/association.ts

@@ -200,14 +200,13 @@ const associationTaggings = (el: HTMLDivElement) => {
 
 // -----------------测量关联--------------------
 
-const sceneMeasureMap = new Map<Measure , SceneMeasure>()
+const sceneMeasureMap = new WeakMap<Measure , SceneMeasure>()
 export const getSceneMeasure = (measure?: Measure | null) => measure && sceneMeasureMap.get(toRaw(measure))
 
 export const associationMessaure = <T extends MeasureType>(smMeasure: SceneMeasure<T>, measure: Measure<T>) => {
   smMeasure.bus.on('update', ([points, modelIds]) => {
     unSet(() => {
       measure.positions = points.map((point, i) => ({ point, modelId: modelIds[i] }))
-      console.log('update messaure', measure.positions)
       const length = measure.type === MeasureType.area
       ? (smMeasure as unknown as SceneMeasure<MeasureType.area>).getArea()
       : (smMeasure as unknown as SceneMeasure<MeasureType.free>).getDistance()
@@ -230,12 +229,14 @@ const associationMessaures = (sdk: SDK) => {
         item.positions.map(position => ({...position.point})),
         item.positions.map(position => position.modelId),
       )
-      associationMessaure(sceneMeasure, item)
-      sceneMeasureMap.set(toRaw(item), sceneMeasure)
+      if (sceneMeasure.destroy) {
+        associationMessaure(sceneMeasure, item)
+        sceneMeasureMap.set(toRaw(item), sceneMeasure)
+      }
     }
     for (const item of deleted) {
       const sceneMeasure = getSceneMeasure(item)
-      sceneMeasure && sceneMeasure.destroy()
+      sceneMeasure && sceneMeasure.destroy!()
     }
   })
 
@@ -339,7 +340,7 @@ export const setupAssociation = (mountEl: HTMLDivElement) => {
     if (fuseModelsLoaded.value) {
       associationTaggings(mountEl)
       associationMessaures(sdk)
-      stopWatch()
+      nextTick(() => stopWatch())
     }
   })
 }

+ 1 - 1
src/sdk/sdk.ts

@@ -81,7 +81,7 @@ export type CalcPathProps = [[SceneGuidePath, SceneGuidePath], Partial<Pick<Scen
 
 
 export interface MeasureBase {
-  destroy: () => void
+  destroy?: () => void
   show: () => void
   hide: () => void
   fly: () => void

+ 18 - 3
src/store/fuse-model.ts

@@ -1,4 +1,4 @@
-import { computed, ref, watchPostEffect } from 'vue'
+import { computed, ref, watch, watchEffect, watchPostEffect } from 'vue'
 import { autoSetModeCallback, unSetModelUpdate, createTemploraryID } from './sys'
 import { custom } from '@/env'
 import { 
@@ -16,6 +16,8 @@ import {
   saveStoreItems,
   recoverStoreItems
 } from '@/utils'
+import { initialTaggings } from './tagging'
+import { initialMeasures } from './measure'
 
 import type { FuseModel as SModel, FuseModelAttrs } from '@/api'
 
@@ -61,6 +63,12 @@ export const getFuseModelShowVariable = (model: FuseModel) =>
     }
   })
   
+watchEffect(() => {
+  for (const model of fuseModels.value) {
+    custom.showModelsMap.set(model, model.show)
+  }
+})
+
 export const fuseModelsLoaded = ref(false)
 watchPostEffect(() => {
   const loaded = fuseModels.value.every(model => model.loaded || model.error)
@@ -99,6 +107,7 @@ export const addFuseModel = async (model: FuseModel) => {
   unSetModelUpdate(() => fuseModels.value.push(addModel))
 }
 
+
 export const initialFuseModels = fetchStoreItems(
   fuseModels, 
   fetchFuseModels, 
@@ -121,8 +130,14 @@ export const saveFuseModels = saveStoreItems(
 
 
 export const autoSaveFuseModels = autoSetModeCallback(fuseModels, {
+  isUpdate: () => fuseModelsLoaded.value,
   backup: backupFuseModels,
   recovery: recoverFuseModels,
-  save: saveFuseModels,
-  isUpdate: () => fuseModelsLoaded.value,
+  save: async () => {
+    await saveFuseModels()
+    await Promise.all([
+      initialTaggings(),
+      initialMeasures()
+    ])
+  },
 })

+ 3 - 1
src/store/measure.ts

@@ -50,7 +50,9 @@ export const backupMeasures = () => {
 export const recoverMeasures = recoverStoreItems(measures, getBackupMeasures)
 
 
-export const initialMeasures = fetchStoreItems(measures, () => fetchMeasures(fuseModels.value[0].fusionId), backupMeasures)
+export const initialMeasures = fetchStoreItems(measures, async () => {
+  return fuseModels.value.length ? await fetchMeasures(fuseModels.value[0].fusionId) : []
+}, backupMeasures)
 export const addMeasure = addStoreItem(measures, postAddMeasure)
 export const updateMeasure = updateStoreItem(measures, postUpdateMeasure)
 export const deleteMeasure = deleteStoreItem(measures, measure => postDeleteMeasure(measure.id))

+ 3 - 3
src/views/sign-model/index.vue

@@ -5,7 +5,8 @@
 <script setup lang="ts">
 import { ref } from 'vue'
 import { loadModel, fuseModel as FModel } from '@/model'
-import { initialScenes, createFuseModels, fuseModels, scenes } from '@/store'
+import { fetchScene } from '@/api'
+import { createFuseModels, fuseModels } from '@/store'
 import { params, showModelsMapStack } from '@/env'
 import { Dialog } from 'bill/index'
 import { useViewStack, useActive } from '@/hook';
@@ -14,8 +15,7 @@ import { sdk } from '@/sdk'
 const active = useActive()
 let pop: () => void
 const loadSignModel = async () => {
-  await initialScenes()
-  const scene = params.modelId && scenes.value.find(scene => scene.modelId === Number(params.modelId))
+  const scene = await fetchScene(Number(params.modelId))
   if (!scene) {
     return Dialog.alert(`模型不存在!`)
   }