Explorar o código

Merge branch 'v1.7.0' of http://192.168.0.115:3000/bill/fuse-code into v1.7.0

xzw hai 1 ano
pai
achega
d710de209e

+ 9 - 0
src/api/guide-path.ts

@@ -17,6 +17,7 @@ interface ServiceGuidePath {
   time: number
   sort: number
   speed: number
+  panoInfo?: string
   cover: string
 }
 
@@ -25,6 +26,12 @@ export interface GuidePath {
   guideId: Guide['id'],
   position: SceneLocalPos
   target: SceneLocalPos
+  panoInfo?: {
+    panoId: any,
+    modelId: string,
+    posInModel: SceneLocalPos,
+    rotInModel: SceneLocalPos
+  },
   time: number
   sort: number
   speed: number
@@ -39,10 +46,12 @@ const serviceToLocal = (servicePath: ServiceGuidePath): GuidePath => ({
   target: JSON.parse(servicePath.target),
   position: JSON.parse(servicePath.position),
   id: servicePath.guidePathId.toString(),
+  panoInfo: servicePath.panoInfo && JSON.parse(servicePath.panoInfo)
 })
 
 const localToService = (path: GuidePath): ServiceGuidePath => ({
   ...path,
+  panoInfo: path.panoInfo && JSON.stringify(path.panoInfo),
   guideId: Number(path.guideId),
   target: JSON.stringify(path.target),
   position: JSON.stringify(path.position),

+ 36 - 34
src/api/setting.ts

@@ -1,58 +1,60 @@
-import { GET_SETTING, UPDATE_SETTING } from './constant'
-import defaultCover from '@/assets/pic.jpg'
-import { params } from '@/env'
-import axios from './instance'
-import { uploadFile } from './sys'
-
+import { GET_SETTING, UPDATE_SETTING } from "./constant";
+import defaultCover from "@/assets/pic.jpg";
+import { params } from "@/env";
+import axios from "./instance";
 
 type ServeSetting = {
-  settingsId?: string,
-  pose?: string
+  settingsId?: string;
+  pose?: string;
   lonlat?: number[];
-  cover?: string,
-  back?: string
-}
+  cover?: string;
+  back?: string;
+};
 
 export type Setting = {
-  id?: string,
+  id?: string;
   pose?: {
-    position: SceneLocalPos
-    target: SceneLocalPos
-  },
-  cover: string,
-  back: string,
+    position: SceneLocalPos;
+    target: SceneLocalPos;
+    panoInfo?: {
+      panoId: any,
+      modelId: string,
+      posInModel: SceneLocalPos,
+      rotInModel: SceneLocalPos
+    },
+  };
+  cover: string;
+  back: string;
   lonlat: number[];
   fov?: number;
   openCompass?: boolean;
-}
-
+};
 
-const toLocal = (serviceSetting: ServeSetting) : Setting => ({
+const toLocal = (serviceSetting: ServeSetting): Setting => ({
   id: serviceSetting.settingsId,
   pose: serviceSetting.pose && JSON.parse(serviceSetting.pose),
   cover: serviceSetting.cover || defaultCover,
-  lonlat: serviceSetting.lonlat || [113.600356,22.364093],
-  back: serviceSetting.back || 'none'
-})
+  lonlat: serviceSetting.lonlat || [113.600356, 22.364093],
+  back: serviceSetting.back || "none",
+});
 
 const toService = (setting: Setting): ServeSetting => ({
   settingsId: setting.id,
   pose: setting.pose && JSON.stringify(setting.pose),
   cover: setting.cover,
-  back: setting.back
-})
-
-
+  back: setting.back,
+});
 
 export const fetchSetting = async () => {
-  const data = await axios.get<ServeSetting[]>(GET_SETTING, { params: { caseId: params.caseId } })
-  return toLocal(data[0] || {})
-}
+  const data = await axios.get<ServeSetting[]>(GET_SETTING, {
+    params: { caseId: params.caseId },
+  });
+  return toLocal(data[0] || {});
+};
 
 export const updateSetting = async (setting: Setting) => {
   await axios.post(UPDATE_SETTING, {
     caseId: params.caseId,
-    ...toService(setting)
-  })
-  
-}
+    ...toService(setting),
+  });
+};

+ 70 - 37
src/layout/model-list/index.vue

@@ -6,62 +6,95 @@
     <template #atom="{ item }">
       <ModelSign
         :canChange="canChange"
-        :model="item.raw" 
-        @delete="modelDelete(item.raw)" 
-        @click="modelChangeSelect(item.raw)"
+        :model="item.raw"
+        @delete="modelDelete(item.raw)"
+        @click="(mode: any) => modelChangeSelect(item.raw, mode)"
       />
     </template>
   </List>
+
+  <Teleport to="#left-pano" v-if="panoModel">
+    <div class="mode-tab strengthen">
+      <div
+        class="mode-icon-layout"
+        @click="modelChangeSelect(panoModel, 'fuse')"
+        :class="{ active: custom.showMode === 'fuse' }"
+      >
+        <ui-icon type="show_3d_n" class="icon" ctrl />
+      </div>
+      <div
+        class="mode-icon-layout"
+        @click="modelChangeSelect(panoModel, 'pano')"
+        :class="{ active: custom.showMode === 'pano' }"
+      >
+        <ui-icon type="show_roaming_n" class="icon" ctrl />
+      </div>
+    </div>
+  </Teleport>
 </template>
 
 <script lang="ts" setup>
-import { computed, watchEffect } from 'vue'
-import { custom } from '@/env'
-import { getSceneModel } from '@/sdk'
-import List from '@/components/list/index.vue'
-import ModelSign from './sign.vue'
-import { fuseModels, getFuseModelShowVariable } from '@/store'
+import { computed, watchEffect } from "vue";
+import { custom } from "@/env";
+import List from "@/components/list/index.vue";
+import ModelSign from "./sign.vue";
+import { getSupperPanoModel } from "@/sdk/association";
+import { fuseModels, getFuseModelShowVariable } from "@/store";
 
-import type { FuseModel } from '@/store'
-import { currentModel, fuseModel } from '@/model'
+import type { FuseModel } from "@/store";
+import { currentModel, fuseModel } from "@/model";
 
-export type ModelListProps = { 
-  title?: string, 
-  canChange?: boolean,
-  showContent?: boolean
-}
-withDefaults(
-  defineProps<ModelListProps>(),
-  { title: '数据列表', change: false, showContent: true }
-)
+export type ModelListProps = {
+  title?: string;
+  canChange?: boolean;
+  showContent?: boolean;
+};
+withDefaults(defineProps<ModelListProps>(), {
+  title: "数据列表",
+  change: false,
+  showContent: true,
+});
 defineEmits<{
-  (e: 'deleteModel', model: FuseModel): void,
-  (e: 'clickModel', model: FuseModel): void
-}>()
+  (e: "deleteModel", model: FuseModel): void;
+  (e: "clickModel", model: FuseModel): void;
+}>();
+
+const panoModel = getSupperPanoModel();
+watchEffect(() => console.error(panoModel.value));
 
-const modelList = computed(() => 
-  fuseModels.value.map(model => ({
+const modelList = computed(() =>
+  fuseModels.value.map((model) => ({
     raw: model,
-    select: custom.currentModel === model && currentModel.value === fuseModel
+    select: custom.currentModel === model && currentModel.value === fuseModel,
   }))
-)
+);
 
-const modelChangeSelect = (model: FuseModel) => {
+const modelChangeSelect = (model: FuseModel, mode: "pano" | "fuse") => {
+  console.error(getFuseModelShowVariable(model).value);
   if (getFuseModelShowVariable(model).value) {
-    custom.currentModel = custom.currentModel !== model ? model : null
+    console.log(custom.currentModel, model);
+    if (custom.currentModel === model && mode === custom.showMode) {
+      custom.currentModel = null;
+      custom.showMode = "fuse";
+      console.log("a?");
+    } else {
+      custom.currentModel = model;
+      custom.showMode = mode;
+    }
   }
-}
+};
 
 watchEffect(() => {
   if (custom.currentModel && !getFuseModelShowVariable(custom.currentModel).value) {
-    custom.currentModel = null
+    custom.currentModel = null;
   }
-})
-
+});
 const modelDelete = (model: FuseModel) => {
-  const index = fuseModels.value.indexOf(model)
+  const index = fuseModels.value.indexOf(model);
   if (~index) {
-    fuseModels.value.splice(index, 1)
+    fuseModels.value.splice(index, 1);
   }
-}
-</script>
+};
+</script>
+
+<style lang="scss" scoped src="./style.scss"></style>

+ 9 - 44
src/layout/model-list/sign.vue

@@ -1,26 +1,14 @@
 <template>
-  <div
-    @click="!model.error && !active && $emit('click')"
-    class="sign-layout"
-    :class="{ disabled: model.error }"
-  >
+  <div @click="!model.error && $emit('click', 'fuse')" class="sign-layout" :class="{ disabled: model.error }">
     <div class="model-header">
       <p>{{ model.title }}</p>
       <div class="model-action">
-        <ui-input
-          type="checkbox"
-          v-model="show"
-          @click.stop
-          :class="{
-            disabled: model.error || custom.showMode === 'pano',
-          }"
-        />
-        <ui-icon
-          v-if="custom.modelsChangeStore"
-          type="del"
-          ctrl
-          @click="$emit('delete')"
-        />
+        <ui-icon ctrl type="show_roaming_n" @click.stop="$emit('click', 'pano')" class="icon"
+          v-if="getSceneModel(props.model)?.supportPano()" />
+        <ui-input type="checkbox" v-model="show" @click.stop :class="{
+    disabled: model.error || custom.showMode === 'pano',
+  }" />
+        <ui-icon v-if="custom.modelsChangeStore" type="del" ctrl @click="$emit('delete')" />
       </div>
     </div>
     <div class="model-desc" v-if="active">
@@ -29,30 +17,11 @@
       <p><span>拍摄时间:</span>{{ model.time }}</p>
     </div>
   </div>
-
-  <Teleport to="#left-pano" v-if="active && supperPano">
-    <div class="mode-tab strengthen">
-      <div
-        class="mode-icon-layout"
-        @click="custom.showMode = 'fuse'"
-        :class="{ active: custom.showMode === 'fuse' }"
-      >
-        <ui-icon type="show_3d_n" class="icon" />
-      </div>
-      <div
-        class="mode-icon-layout"
-        @click="custom.showMode = 'pano'"
-        :class="{ active: custom.showMode === 'pano' }"
-      >
-        <ui-icon type="show_roaming_n" class="icon" />
-      </div>
-    </div>
-  </Teleport>
 </template>
 
 <script lang="ts" setup>
 import { getFuseModelShowVariable, SceneTypeDesc, SceneType } from "@/store";
-import { custom, showModeStack } from "@/env";
+import { custom } from "@/env";
 import { getSceneModel } from "@/sdk";
 
 import type { FuseModel } from "@/store";
@@ -65,15 +34,11 @@ const props = defineProps<ModelProps>();
 const active = computed(
   () => custom.currentModel === props.model && currentModel.value === fuseModel
 );
-const supperPano = computed(() => {
-  console.log(props.model.title, getSceneModel(props.model)?.supportPano());
-  return getSceneModel(props.model)?.supportPano();
-});
 
 type ModelEmits = {
   (e: "changeSelect", selected: boolean): void;
   (e: "delete"): void;
-  (e: "click"): void;
+  (e: "click", mode: "pano" | "fuse"): void;
 };
 defineEmits<ModelEmits>();
 

+ 1 - 1
src/layout/model-list/style.scss

@@ -55,7 +55,7 @@
     padding: 0 8px;
 
     &.active .icon {
-      color: var(--color-main-normal);
+      color: var(--color-main-normal) !important;
     }
   }
 

+ 21 - 29
src/sdk/association/fuseMode.ts

@@ -1,5 +1,5 @@
 import { SDK, SceneModel, ModelAttrRange } from "../sdk";
-import { toRaw, watch, reactive } from "vue";
+import { toRaw, watch, reactive, ref } from "vue";
 import { custom, getResource } from "@/env";
 import {
   diffArrayChange,
@@ -30,7 +30,7 @@ export const modelRange: ModelAttrRange = {
   scaleRange: { min: 0, max: 200, step: 0.1 },
 };
 
-const sceneModelMap = reactive(new WeakMap<FuseModel, SceneModel>());
+export const sceneModelMap = reactive(new Map<FuseModel, SceneModel>());
 export const getSceneModel = (model?: FuseModel | null) =>
   model && sceneModelMap.get(toRaw(model));
 
@@ -76,7 +76,6 @@ const setModels = (sdk: SDK, models: FuseModels, oldModels: FuseModels) => {
     let changeId: NodeJS.Timeout;
     sceneModel.bus.on("transformChanged", (transform) => {
       clearTimeout(changeId);
-
       changeId = setTimeout(() => {
         transform = { ...transform };
         if (transform.rotation) {
@@ -141,9 +140,11 @@ const setModels = (sdk: SDK, models: FuseModels, oldModels: FuseModels) => {
   for (const item of deleted) {
     console.error("销毁", item);
     getSceneModel(item)?.destroy();
+    sceneModelMap.delete(item);
   }
 };
 
+
 export const associationModels = (sdk: SDK) => {
   // watch(
   //   () => custom.currentModel === item,
@@ -158,39 +159,30 @@ export const associationModels = (sdk: SDK) => {
       active: custom.currentModel,
     }),
     (status, oldStatus, onCleanup) => {
-      if (!status.active) return;
-      const sceneModel = getSceneModel(status.active)!;
+      const model = status.active && getSceneModel(status.active)!;
+      const oldModel = oldStatus.active && getSceneModel(oldStatus.active)!;
 
-      onCleanup(() => {
-        console.log(status.active!.title, "noAcitve");
-        sceneModel.changeSelect(false);
-      });
+      if (status.showMode !== 'pano' && model) {
+        model && model.changeSelect(true);
+      }
 
-      if (status.showMode === "pano") {
-        if (sceneModel.supportPano()) {
-          sceneModel.changeSelect(true);
-          sceneModel.flyInPano();
-          onCleanup(() => {
-            console.log(status.active!.title, "flyOutPano");
-            sceneModel.changeSelect(false);
-            sceneModel.flyOutPano();
-          });
+      if (model && status.active === oldStatus.active) {
+        if (status.showMode === "pano") {
+          model && model.flyInPano();
         } else {
-          custom.showMode = "fuse";
-          onCleanup(() => {});
+          model && model.flyOutPano();
         }
       } else {
-        if (oldStatus.showMode === "pano") {
-          setTimeout(() => {
-            sceneModel.changeSelect(true);
-          }, 100);
+        if (oldStatus.showMode !== status.showMode) {
+          if (oldStatus.showMode === "pano") {
+            oldModel && oldModel.flyOutPano();
+          }
+        }
+        if (status.showMode === "pano") {
+          model && model.flyInPano();
         } else {
-          sceneModel.changeSelect(true);
+          console.log('select')
         }
-        onCleanup(() => {
-          console.log(status.active!.title, "noAcitve");
-          sceneModel.changeSelect(false);
-        });
       }
     }
   );

+ 4 - 5
src/sdk/association/guide.ts

@@ -17,7 +17,8 @@ import {
   getGuidePaths
 } from '@/store'
 
-import type { FuseModel, FuseModels, Guide } from '@/store'
+import type { FuseModel, FuseModels, Guide, GuidePath } from '@/store'
+import { analysisPoseInfo } from '.'
 
 // -----------------导览关联--------------------
 
@@ -121,8 +122,7 @@ export enum ScenePlayIngEnum {
 }
 export const isScenePlayIng = ref<ScenePlayIngEnum>(ScenePlayIngEnum.stop)
 let pauseRecovery: () => void
-export const playSceneGuide = async (guide: Guide, changeIndexCallback?: (index: number) => void, forceFull = false) => {
-  const paths = getGuidePaths(guide)
+export const playSceneGuide = async (paths: GuidePath[], changeIndexCallback?: (index: number) => void, forceFull = false) => {
   if (isScenePlayIng.value) {
     throw new Error('导览正在播放')
   }
@@ -130,7 +130,7 @@ export const playSceneGuide = async (guide: Guide, changeIndexCallback?: (index:
   // pauseRecovery = await recovery(guide)
   isScenePlayIng.value = ScenePlayIngEnum.ing
 
-  const sceneGuide = sdk.enterSceneGuide(paths)
+  const sceneGuide = sdk.enterSceneGuide(paths.map(path => ({ ...path, ...analysisPoseInfo(path)})))
 
   changeIndexCallback && sceneGuide.bus.on('changePoint', changeIndexCallback)
 
@@ -169,7 +169,6 @@ export const playSceneGuide = async (guide: Guide, changeIndexCallback?: (index:
 }
 
 export const pauseSceneGuide = () => {
-  console.error('pause?')
   isScenePlayIng.value = ScenePlayIngEnum.stop
   pauseRecovery && pauseRecovery()
 }

+ 73 - 4
src/sdk/association/index.ts

@@ -1,11 +1,80 @@
-import { nextTick, watchEffect } from "vue"
-import { SDK } from "../sdk"
-import { associationModels } from "./fuseMode"
-import { fuseModelsLoaded, setting } from "@/store"
+import { nextTick, ref, toRaw, watchEffect } from "vue"
+import {Pose, SceneModel, sdk, SDK } from "../sdk"
+import { associationModels, sceneModelMap } from "./fuseMode"
+import { FuseModel, fuseModelsLoaded, GuidePath, setting } from "@/store"
 import { associationTaggings } from "./tagging"
 import { associationSetting } from "./setting"
 import { associationMessaures } from "./measure"
 
+
+export const getSupperPanoModel = () => {
+  const supperModel = ref<FuseModel | null>(null);
+
+  sdk.sceneBus.on("cameraChange", () => {
+    const data = sdk.canTurnToPanoMode();
+    if (data?.model) {
+      for (const [f, s] of sceneModelMap.entries()) {
+        if (toRaw(data.model) === toRaw(s)) {
+          supperModel.value = f;
+          return;
+        }
+      }
+    }
+    supperModel.value = null;
+  });
+
+  return supperModel;
+};
+
+export const analysisPose = (pose: Pose) => {
+  if ('model' in pose && pose.model) {
+    let info: GuidePath['panoInfo'] | undefined = undefined
+    let fuseMode: FuseModel
+    for (const [k, v] of Array.from(sceneModelMap.entries())) {
+      if (toRaw(v) === toRaw(pose.model)) {
+        fuseMode = toRaw(k)
+      }
+    }
+    if (fuseMode!) {
+      info = {
+        panoId: pose.panoId,
+        modelId: fuseMode.id,
+        posInModel: pose.posInModel,
+        rotInModel: pose.rotInModel
+      }
+      return {
+        position: pose.position,
+        target: pose.target,
+        panoInfo: info
+      }
+    }
+  } 
+  return pose
+}
+
+export const analysisPoseInfo = (info: ReturnType<typeof analysisPose>) => {
+  let pose: Pose = { target: info.target, position: info.position }
+  if ('panoInfo' in info && info.panoInfo) {
+    let sceneModel: SceneModel
+    for (const [k, v] of Array.from(sceneModelMap.entries())) {
+      if (k.id === info.panoInfo.modelId) {
+        sceneModel = toRaw(v)
+      }
+    }
+    
+    if (sceneModel!) {
+      pose = {
+        ...pose,
+        model: sceneModel,
+        panoId: info.panoInfo.panoId,
+        posInModel: info.panoInfo.posInModel,
+        rotInModel: info.panoInfo.rotInModel,
+      }
+    }
+  }
+  return pose
+}
+
 export const setupAssociation = (mountEl: HTMLDivElement, sdk: SDK) => {
   associationModels(sdk)
 

+ 7 - 2
src/sdk/association/setting.ts

@@ -1,7 +1,7 @@
 import { setting } from "@/store";
 import { nextTick, watchEffect } from "vue";
 import { SDK } from "../sdk";
-
+import { analysisPoseInfo } from ".";
 
 export const associationSetting = (sdk: SDK, mountEl: HTMLDivElement) => {
   watchEffect(() => {
@@ -9,7 +9,12 @@ export const associationSetting = (sdk: SDK, mountEl: HTMLDivElement) => {
   });
 
   const stopWatchPose = watchEffect(() => {
-    setting.value && setting.value.pose && sdk.comeTo(setting.value.pose);
+    if (!setting.value?.pose) return;
+    if (sdk.setPose) {
+      sdk.setPose(analysisPoseInfo(setting.value.pose))
+    } else {
+      sdk.comeTo(setting.value.pose);
+    }
     nextTick(() => stopWatchPose());
   });
 

+ 1 - 0
src/sdk/cover/index.js

@@ -863,6 +863,7 @@ export const enter = ({ dom, mapDom, isLocal, lonlat, scenes }) => {
                     }
                 },
                 changeSelect(state) {
+                    console.error('select', state)
                     if (model) {
                         let fly = viewer.images360.latestRequestMode != 'showPanos'
                         MergeEditor.selectModel(model, state, fly, true)

+ 197 - 134
src/sdk/sdk.ts

@@ -1,142 +1,205 @@
-import cover from './cover'
-import { createLoadPack, loadLib } from '@/utils'
-
-import { FuseModelAttrs, FuseModel, GuidePath, MeasureType, Measure as StoreMeasure, MeasurePosition, SceneType, scenes, Scene } from '@/store'
-import type { Emitter } from 'mitt'
-import { SettingResourceType } from '@/api/setting-resource'
-
-
-type SceneModelAttrs = FuseModelAttrs & { select: boolean }
-export type SceneModel = ToChangeAPI<SceneModelAttrs>
-  & { 
-    bus: Emitter<
-      Pick<SceneModelAttrs, 'select'> & 
-      { 
-        loadError: void,
-        loadDone: void, 
-        loadProgress: number,
-        changeSelect: boolean,
-        transformChanged: {
-          position?: SceneLocalPos,
-          scale?: number,
-          rotation?: SceneLocalPos,
-          bottom?: number
-        }
-      }
-    > 
-    destroy: () => void 
-    enterRotateMode: () => void
-    enterMoveMode: () => void
-    leaveTransform: () => void
-    enterAlignment: () => void
-    leaveAlignment: () => void
-    enterScaleSet:() => ScaleSet
-    leaveScaleSet: () => void
-
-    supportPano: () => boolean;
-    flyInPano: () => void;
-    flyOutPano: () => void;
-  }
+import cover from "./cover/index";
+import { createLoadPack, loadLib } from "@/utils";
+
+import {
+  FuseModelAttrs,
+  FuseModel,
+  GuidePath,
+  MeasureType,
+  Measure as StoreMeasure,
+  MeasurePosition,
+  SceneType,
+  scenes,
+  Scene,
+} from "@/store";
+import type { Emitter } from "mitt";
+export enum SettingResourceType {
+  map = "map",
+  color = "color",
+  envImage = "img",
+  bottomImage = "bimg",
+  icon = "icon",
+}
+
+type SceneModelAttrs = FuseModelAttrs & { select: boolean };
+export type SceneModel = ToChangeAPI<SceneModelAttrs> & {
+  bus: Emitter<
+    Pick<SceneModelAttrs, "select"> & {
+      loadError: void;
+      loadDone: void;
+      loadProgress: number;
+      changeSelect: boolean;
+      transformChanged: {
+        position?: SceneLocalPos;
+        scale?: number;
+        rotation?: SceneLocalPos;
+        bottom?: number;
+      };
+    }
+  >;
+  destroy: () => void;
+  enterRotateMode: () => void;
+  enterMoveMode: () => void;
+  leaveTransform: () => void;
+  enterAlignment: () => void;
+  leaveAlignment: () => void;
+  enterScaleSet: () => ScaleSet;
+  leaveScaleSet: () => void;
+
+  supportPano: () => boolean;
+  flyInPano: () => void;
+  flyOutPano: () => void;
+};
 
 export interface ScaleSet {
-  setLength: (length: number) => void,
-  startMeasure: () => void
+  setLength: (length: number) => void;
+  startMeasure: () => void;
 }
-  
 
 export type ModelAttrRange = {
-  [key in 'opacity' | 'bottom' | 'scale' as `${key}Range`]: {
-    min: number,
-    max: number,
-    step: number
-  }
-}
-
-export type AddModelProps = Pick<FuseModel, 'url' | 'id'> 
-  & FuseModelAttrs 
-  & { type: string, isDynamicAdded: boolean, mode: 'many' | 'single', fromType: any }
-  & ModelAttrRange
-
-
-export type SceneGuidePath = Pick<GuidePath, 'position' | 'target' | 'speed' | 'time'>
+  [key in "opacity" | "bottom" | "scale" as `${key}Range`]: {
+    min: number;
+    max: number;
+    step: number;
+  };
+};
+
+export type AddModelProps = Pick<FuseModel, "url" | "id"> &
+  FuseModelAttrs & {
+    type: string;
+    isDynamicAdded: boolean;
+    mode: "many" | "single";
+    fromType: any;
+  } & ModelAttrRange;
+
+export type SceneGuidePath = Pick<
+  GuidePath,
+  "speed" | "time"
+> & Pose;
 export interface SceneGuide {
-  bus: Emitter<{ changePoint: number; playComplete: void }>
-  play: () => void
-  pause: () => void
-  clear: () => void
-}
-
-export type ScenePos = { localPos: SceneLocalPos, modelId: FuseModel['id'] }
-export type ScreenPos = { 
-  trueSide: boolean,
-  pos: ScreenLocalPos, 
-  modelId: FuseModel['id'] 
+  bus: Emitter<{ changePoint: number; playComplete: void }>;
+  play: () => void;
+  pause: () => void;
+  clear: () => void;
 }
 
-export interface CameraComeToProps { 
-  position: SceneLocalPos; 
-  target?: SceneLocalPos; 
-  dur?: number, 
-  modelId?: FuseModel['id'], 
-  distance?: 1 | 2 | 3 
+export type ScenePos = { localPos: SceneLocalPos; modelId: FuseModel["id"] };
+export type ScreenPos = {
+  trueSide: boolean;
+  pos: ScreenLocalPos;
+  modelId: FuseModel["id"];
+};
+
+export interface CameraComeToProps {
+  position: SceneLocalPos;
+  target?: SceneLocalPos;
+  dur?: number;
+  modelId?: FuseModel["id"];
+  distance?: 1 | 2 | 3;
 }
 
-export type CalcPathProps = [[SceneGuidePath, SceneGuidePath], Partial<Pick<SceneGuidePath, 'time' | 'speed'>>]
-
-
+export type CalcPathProps = [
+  [SceneGuidePath, SceneGuidePath],
+  Partial<Pick<SceneGuidePath, "time" | "speed">>
+];
 
 export interface MeasureBase {
-  destroy?: () => void
-  show: () => void
-  hide: () => void
-  fly: () => void
-  bus: Emitter<{ update: [MeasurePosition['point'][], MeasurePosition['modelId'][]]; highlight: boolean }>
-  changeSelect: (isHight: boolean) => void
-  setPositions: (points: MeasurePosition['point'][], modelIds: MeasurePosition['modelId'][]) => void
-} 
-
-export type Measure<T extends StoreMeasure['type'] = StoreMeasure['type']> = MeasureBase & (
-  T extends MeasureType.area
-    ? { getArea: () => {value: number} }
-    : { getDistance: () => {value: number} }
-)
-
-
-export type StartMeasure<T extends StoreMeasure['type']> = Measure<T> & {
-  bus: Emitter<{ submit: [MeasurePosition['point'][], MeasurePosition['modelId'][]]; cancel: void; invalidPoint: string }>
+  destroy?: () => void;
+  show: () => void;
+  hide: () => void;
+  fly: () => void;
+  bus: Emitter<{
+    update: [MeasurePosition["point"][], MeasurePosition["modelId"][]];
+    highlight: boolean;
+  }>;
+  changeSelect: (isHight: boolean) => void;
+  setPositions: (
+    points: MeasurePosition["point"][],
+    modelIds: MeasurePosition["modelId"][]
+  ) => void;
 }
 
-export interface SDK {
-  layout: HTMLDivElement,
-  sceneBus: Emitter<{ 'cameraChange':  SceneLocalPos }>
-  setBackdrop: (drop: string, type: SettingResourceType, tb: {scale?: number, rotate?: number}) => void
-  compassVisibility: (visibility: boolean) => void
-  switchScene: (scene: {type: SceneType, num: string} | null) => Promise<void>
-  addModel: (props: AddModelProps) => SceneModel
-  setCameraFov: (fov: number) => void
-  enableMap(dom: HTMLDivElement, latlng: number[]): void
-  switchMapType: (type: string) => void
-  showGrid: () => void
-  hideGrid: () => void
-  calcPathInfo: (paths: CalcPathProps[0], info: CalcPathProps[1]) => Required<CalcPathProps[1]>
-  getPositionByScreen: (screenPos: ScreenLocalPos, modelId?: FuseModel['id']) => ScenePos & {worldPos: SceneLocalPos} | null
-  getScreenByPosition: (localPos: SceneLocalPos, modelId?: FuseModel['id']) => ScreenPos | null
-  screenshot: (width: number, height: number) => Promise<string>
-  getPose: () => { position: SceneLocalPos, target: SceneLocalPos }
-  comeTo: (pos: CameraComeToProps) => void
-  enterSceneGuide: (data: SceneGuidePath[]) => SceneGuide,
-
-  drawMeasure<T extends StoreMeasure['type']>(type: T, points: MeasurePosition['point'][], modelIds: MeasurePosition['modelId'][]): Measure<T>,
-  startMeasure<T extends StoreMeasure['type']>(type: T): StartMeasure<T> ,
+export type Measure<T extends StoreMeasure["type"] = StoreMeasure["type"]> =
+  MeasureBase &
+    (T extends MeasureType.area
+      ? { getArea: () => { value: number } }
+      : { getDistance: () => { value: number } });
+
+export type StartMeasure<T extends StoreMeasure["type"]> = Measure<T> & {
+  bus: Emitter<{
+    submit: [MeasurePosition["point"][], MeasurePosition["modelId"][]];
+    cancel: void;
+    invalidPoint: string;
+  }>;
+};
+
+export type Pose = {
+  position: SceneLocalPos; 
+  target: SceneLocalPos,
+} | {
+  panoId: any,
+  model: SceneModel,
+  posInModel: SceneLocalPos,
+  rotInModel: SceneLocalPos,
+  position: SceneLocalPos; 
+  target: SceneLocalPos,
 }
 
+export interface SDK {
+  layout: HTMLDivElement;
+  sceneBus: Emitter<{ cameraChange: SceneLocalPos }>;
+  setBackdrop: (
+    drop: string,
+    type: SettingResourceType,
+    tb: { scale?: number; rotate?: number }
+  ) => void;
+  compassVisibility: (visibility: boolean) => void;
+  switchScene: (
+    scene: { type: SceneType; num: string } | null
+  ) => Promise<void>;
+  addModel: (props: AddModelProps) => SceneModel;
+  setCameraFov: (fov: number) => void;
+  enableMap(dom: HTMLDivElement, latlng: number[]): void;
+  switchMapType: (type: string) => void;
+  showGrid: () => void;
+  canTurnToPanoMode: () => { model: SceneModel };
+  hideGrid: () => void;
+  calcPathInfo: (
+    paths: CalcPathProps[0],
+    info: CalcPathProps[1]
+  ) => Required<CalcPathProps[1]>;
+  getPositionByScreen: (
+    screenPos: ScreenLocalPos,
+    modelId?: FuseModel["id"]
+  ) => (ScenePos & { worldPos: SceneLocalPos }) | null;
+  getScreenByPosition: (
+    localPos: SceneLocalPos,
+    modelId?: FuseModel["id"]
+  ) => ScreenPos | null;
+  screenshot: (width: number, height: number) => Promise<string>;
+  getPose: () => Pose;
+  setPose: (pose: Pose &{dur?: number}) => void
+  comeTo: (pos: CameraComeToProps) => void;
+  enterSceneGuide: (data: SceneGuidePath[]) => SceneGuide;
+
+  drawMeasure<T extends StoreMeasure["type"]>(
+    type: T,
+    points: MeasurePosition["point"][],
+    modelIds: MeasurePosition["modelId"][]
+  ): Measure<T>;
+  startMeasure<T extends StoreMeasure["type"]>(type: T): StartMeasure<T>;
+}
 
-export let sdk: SDK
-export type InialSDKProps = { layout: HTMLDivElement, scenes: Scene[], lonlat?:number[] }
-export let initialed = false
+export let sdk: SDK;
+export type InialSDKProps = {
+  layout: HTMLDivElement;
+  scenes: Scene[];
+  lonlat?: number[];
+};
+export let initialed = false;
 export const initialSDK = async (props: InialSDKProps) => {
   if (initialed) return sdk;
-  initialed = true
+  initialed = true;
   const libs = [
     `./lib/proj4/proj4.js`,
     `./lib/jquery/jquery-3.1.1.min.js`,
@@ -148,24 +211,24 @@ export const initialSDK = async (props: InialSDKProps) => {
     `./lib/plasio/workers/laz-perf.js`,
     `./lib/Cesium/Cesium.js`,
     `./lib/shapefile/shapefile.js`,
-  ]
-  await Promise.all(libs.map(loadLib))
-  await loadLib(`./lib/potree/potree.js`)
+  ];
+  await Promise.all(libs.map(loadLib));
+  await loadLib(`./lib/potree/potree.js`);
 
-  console.log(props)
+  console.log(props);
   const localSdk = cover({
-    dom: props.layout, 
-    isLocal: false, 
+    dom: props.layout,
+    isLocal: false,
     scenes: props.scenes,
     lonlat: props.lonlat,
-    mapDom: null
-  }) as unknown as SDK
+    mapDom: null,
+  }) as unknown as SDK;
 
-  console.log(scenes.value)
-  ;(window as any).sdk = sdk = localSdk
-  sdk.layout = props.layout
+  console.log(scenes.value);
+  (window as any).sdk = sdk = localSdk;
+  sdk.layout = props.layout;
 
-  return sdk
-}
+  return sdk;
+};
 
-export default sdk!
+export default sdk!;

+ 144 - 123
src/views/guide/edit-paths.vue

@@ -1,16 +1,16 @@
 <template>
   <div class="video">
     <div class="overflow">
-      <ui-icon 
-        ctrl 
-        :type="isScenePlayIng ? 'pause' : 'preview'" 
-        :disabled="!paths.length" 
+      <ui-icon
+        ctrl
+        :type="isScenePlayIng ? 'pause' : 'preview'"
+        :disabled="!paths.length"
         @click="play"
       />
-      <ui-button 
-        type="primary" 
-        @click="addPath" 
-        width="200px" 
+      <ui-button
+        type="primary"
+        @click="addPath"
+        width="200px"
         :class="{ disabled: isScenePlayIng }"
       >
         添加视角
@@ -19,11 +19,11 @@
     <div class="info" v-if="paths.length">
       <div class="meta">
         <div class="length">
-          <span>视频时长</span>{{paths.reduce((t, c) => t + c.time, 0).toFixed(1)}}s
+          <span>视频时长</span>{{ paths.reduce((t, c) => t + c.time, 0).toFixed(1) }}s
         </div>
-        <div 
-          class="fun-ctrl clear" 
-          @click="deleteAll" 
+        <div
+          class="fun-ctrl clear"
+          @click="deleteAll"
           :class="{ disabled: isScenePlayIng }"
         >
           <ui-icon type="del" />
@@ -33,48 +33,47 @@
 
       <div class="photo-list" ref="listVm">
         <template v-for="(path, i) in paths" :key="path.id">
-          <div 
-            class="photo" 
+          <div
+            class="photo"
             :class="{ active: current === path, disabled: isScenePlayIng }"
             @click="changeCurrent(path)"
           >
-            <ui-icon 
-              type="del" 
-              ctrl 
-              @click.stop="deletePath(path)" 
-              :class="{ disabled: isScenePlayIng }" 
+            <ui-icon
+              type="del"
+              ctrl
+              @click.stop="deletePath(path)"
+              :class="{ disabled: isScenePlayIng }"
             />
             <img :src="getResource(getFileUrl(path.cover))" />
           </div>
           <div class="set-phone-attr" v-if="i !== paths.length - 1">
-            <ui-input 
-              type="number" 
-              width="54px" 
+            <ui-input
+              type="number"
+              width="54px"
               height="26px"
-              :modelValue="path.speed" 
+              :modelValue="path.speed"
               @update:modelValue="(val: number) => updatePathInfo(i, { speed: val })"
-              :ctrl="false" 
-              :min="0.1" 
+              :ctrl="false"
+              :min="0.1"
               :max="10"
             >
               <template #icon><span>m/s</span></template>
             </ui-input>
-            <ui-input 
-              type="number" 
-              width="54px" 
-              height="26px" 
-              :modelValue="path.time" 
+            <ui-input
+              type="number"
+              width="54px"
+              height="26px"
+              :modelValue="path.time"
               @update:modelValue="(val: number) => updatePathInfo(i, { time: val })"
-              :ctrl="false" 
-              :min="0.1" 
-              :max="20" 
+              :ctrl="false"
+              :min="0.1"
+              :max="20"
               class="time"
             >
               <template #icon><span class="time">s</span></template>
             </ui-input>
           </div>
         </template>
-        
       </div>
     </div>
     <p class="un-video" v-else>暂无导览</p>
@@ -82,30 +81,47 @@
 </template>
 
 <script setup lang="ts">
-import { loadPack, togetherCallback, getFileUrl, asyncTimeout } from '@/utils'
-import { sdk, playSceneGuide, pauseSceneGuide, isScenePlayIng } from '@/sdk'
-import { createGuidePath, isTemploraryID, useAutoSetMode, guides, getGuidePaths, guidePaths } from '@/store'
-import { Dialog, Message } from 'bill/index'
-import { useViewStack } from '@/hook'
-import { nextTick, ref, toRaw, watchEffect } from 'vue'
-import { showRightPanoStack, showLeftCtrlPanoStack, showLeftPanoStack, showRightCtrlPanoStack, getResource } from '@/env'
+import { loadPack, togetherCallback, getFileUrl, asyncTimeout } from "@/utils";
+import {
+  sdk,
+  playSceneGuide,
+  pauseSceneGuide,
+  isScenePlayIng,
+  analysisPose,
+  analysisPoseInfo,
+} from "@/sdk";
+import {
+  createGuidePath,
+  isTemploraryID,
+  useAutoSetMode,
+  guides,
+  getGuidePaths,
+  guidePaths,
+} from "@/store";
+import { Dialog, Message } from "bill/index";
+import { useViewStack } from "@/hook";
+import { nextTick, ref, toRaw, watchEffect } from "vue";
+import {
+  showRightPanoStack,
+  showLeftCtrlPanoStack,
+  showLeftPanoStack,
+  showRightCtrlPanoStack,
+  getResource,
+} from "@/env";
 
-import type { Guide, GuidePaths, GuidePath } from '@/store'
-import type { CalcPathProps } from '@/sdk'
+import type { Guide, GuidePaths, GuidePath } from "@/store";
+import type { CalcPathProps } from "@/sdk";
 
-const props = defineProps< { data: Guide }>()
-const paths = ref<GuidePaths>(getGuidePaths(props.data))
-const current = ref<GuidePath>(paths.value[0])
+const props = defineProps<{ data: Guide }>();
+const paths = ref<GuidePaths>(getGuidePaths(props.data));
+const current = ref<GuidePath>(paths.value[0]);
 
 const updatePathInfo = (index: number, calcInfo: CalcPathProps[1]) => {
-  const info = sdk.calcPathInfo(
-    paths.value.slice(index, index + 2) as any,
-    calcInfo
-  )
-  Object.assign(paths.value[index], info)
-}
+  const info = sdk.calcPathInfo(paths.value.slice(index, index + 2) as any, calcInfo);
+  Object.assign(paths.value[index], info);
+};
 
-useViewStack(() => 
+useViewStack(() =>
   togetherCallback([
     showRightPanoStack.push(ref(false)),
     showLeftCtrlPanoStack.push(ref(false)),
@@ -114,97 +130,105 @@ useViewStack(() =>
   ])
 );
 
-useAutoSetMode(paths, {
-  save() {
-    if (!paths.value.length) {
-      Dialog.alert('无法保存空路径导览!')
-      throw '无法保存空路径导览!'
-    }
-    const oldPaths = getGuidePaths(props.data)
-    props.data.cover = paths.value[0].cover
-    guidePaths.value = guidePaths.value
-      .filter(path => !oldPaths.includes(path))
-      .concat(paths.value)
-    if (isTemploraryID(props.data.id)) {
-      console.error("现在才保存?")
-      guides.value.push(props.data)
-    }
+useAutoSetMode(
+  paths,
+  {
+    save() {
+      if (!paths.value.length) {
+        Dialog.alert("无法保存空路径导览!");
+        throw "无法保存空路径导览!";
+      }
+      const oldPaths = getGuidePaths(props.data);
+      props.data.cover = paths.value[0].cover;
+      guidePaths.value = guidePaths.value
+        .filter((path) => !oldPaths.includes(path))
+        .concat(paths.value);
+      if (isTemploraryID(props.data.id)) {
+        console.error("现在才保存?");
+        guides.value.push(props.data);
+      }
+    },
   },
-}, false)
+  false
+);
 
 const addPath = () => {
   loadPack(async () => {
-    const dataURL = await sdk.screenshot(260, 160)
-    const res = await fetch(dataURL)
-    const blob = await res.blob()
+    const dataURL = await sdk.screenshot(260, 160);
+    const res = await fetch(dataURL);
+    const blob = await res.blob();
 
-    const pose = sdk.getPose()
-    const index = paths.value.indexOf(current.value) + 1
-    const path: GuidePath = createGuidePath({ 
-      ...pose, 
+    const pose = sdk.getPose();
+    const index = paths.value.indexOf(current.value) + 1;
+    const path: GuidePath = createGuidePath({
+      ...analysisPose(pose),
       guideId: props.data.id,
-      cover: { url: dataURL, blob } 
-    })
-    paths.value.splice(index, 0, path)
-    current.value = path
+      cover: { url: dataURL, blob },
+    });
+    paths.value.splice(index, 0, path);
+    current.value = path;
     if (paths.value.length > 1) {
-      const index = paths.value.length - 2
-      updatePathInfo(index, { time: 3 })
+      const index = paths.value.length - 2;
+      updatePathInfo(index, { time: 3 });
     }
-  })
-}
+  });
+};
 
 const deletePath = async (path: GuidePath, fore: boolean = false) => {
-  if (fore || (await Dialog.confirm('确定要删除此画面吗?'))) {
-    const index = paths.value.indexOf(path)
+  if (fore || (await Dialog.confirm("确定要删除此画面吗?"))) {
+    const index = paths.value.indexOf(path);
     if (~index) {
-      paths.value.splice(index, 1)
+      paths.value.splice(index, 1);
     }
     if (path === current.value) {
-      current.value = paths.value[index + (index === 0 ? 0 : -1)]
+      current.value = paths.value[index + (index === 0 ? 0 : -1)];
     }
   }
-}
+};
 
 const deleteAll = async () => {
-  if (await Dialog.confirm('确定要清空画面吗?')) {
-    paths.value.length = 0
-    current.value = paths.value[0]
+  if (await Dialog.confirm("确定要清空画面吗?")) {
+    paths.value.length = 0;
+    current.value = paths.value[0];
   }
-}
+};
 
 const changeCurrent = (path: GuidePath) => {
-  sdk.comeTo({ dur: 300, ...path })
-  current.value = path
-}
+  if (sdk.setPose) {
+    sdk.setPose({ dur: 300, ...path, ...analysisPoseInfo(path) });
+  } else {
+    sdk.comeTo({ dur: 300, ...path });
+  }
+  current.value = path;
+};
 
 const play = async () => {
   if (isScenePlayIng.value) {
-    pauseSceneGuide()
+    pauseSceneGuide();
   } else {
-    changeCurrent(paths.value[0])
-    await asyncTimeout(400)
-    playSceneGuide(toRaw(paths.value), (index) => {
-      current.value = paths.value[index - 1]
-    })
+    changeCurrent(paths.value[0]);
+    await asyncTimeout(400);
+    playSceneGuide(paths.value, (index) => {
+      current.value = paths.value[index - 1];
+    });
   }
-}
+};
 
-const listVm = ref<HTMLDivElement>()
+const listVm = ref<HTMLDivElement>();
 watchEffect(async () => {
-  const index = paths.value.indexOf(current.value)
+  const index = paths.value.indexOf(current.value);
   if (~index && listVm.value) {
-    await nextTick()
-    const scrollWidth = listVm.value.scrollWidth / paths.value.length
-    const centerWidth = listVm.value.offsetWidth / 2
-    const offsetLeft = scrollWidth * index - centerWidth
+    await nextTick();
+    const scrollWidth = listVm.value.scrollWidth / paths.value.length;
+    const centerWidth = listVm.value.offsetWidth / 2;
+    const offsetLeft = scrollWidth * index - centerWidth;
 
     listVm.value.scroll({
       left: offsetLeft,
       top: 0,
-    })
+    });
   }
-})
+});
 </script>
 
 <style lang="scss" scoped>
@@ -229,11 +253,11 @@ watchEffect(async () => {
 
   .meta {
     font-size: 12px;
-    border-bottom: 1px solid rgba(255,255,255,.16);
+    border-bottom: 1px solid rgba(255, 255, 255, 0.16);
     padding: 10px 20px;
     display: flex;
     justify-content: space-between;
-    
+
     .length span {
       margin-right: 10px;
     }
@@ -248,7 +272,6 @@ watchEffect(async () => {
     }
   }
 
-
   .photo-list {
     padding: 10px 20px 20px;
     overflow-x: auto;
@@ -264,8 +287,8 @@ watchEffect(async () => {
 
       &::before,
       &::after {
-        content: '';
-        color: rgba(255,255,255,.6);
+        content: "";
+        color: rgba(255, 255, 255, 0.6);
         position: absolute;
         top: 50%;
         transform: translateY(-50%);
@@ -284,12 +307,11 @@ watchEffect(async () => {
         border-left: 7px solid currentColor;
       }
     }
-    
+
     .photo {
       cursor: pointer;
       flex: none;
       position: relative;
-      
 
       &.active {
         outline: 2px solid var(--colors-primary-base);
@@ -302,8 +324,8 @@ watchEffect(async () => {
         width: 24px;
         font-size: 12px;
         height: 24px;
-        background-color: rgba(0,0,0,0.6);
-        color: rgba(255,255,255,.6);
+        background-color: rgba(0, 0, 0, 0.6);
+        color: rgba(255, 255, 255, 0.6);
         display: flex;
         align-items: center;
         justify-content: center;
@@ -311,7 +333,6 @@ watchEffect(async () => {
         border-radius: 50%;
       }
 
-
       img {
         width: 230px;
         height: 160px;
@@ -324,7 +345,7 @@ watchEffect(async () => {
   height: 100px;
   line-height: 100px;
   text-align: center;
-  color: rgba(255,255,255,0.6);
+  color: rgba(255, 255, 255, 0.6);
   font-size: 1.2em;
 }
 </style>
@@ -349,4 +370,4 @@ watchEffect(async () => {
     text-align: right;
   }
 }
-</style>
+</style>

+ 93 - 61
src/views/setting/index.vue

@@ -3,7 +3,7 @@
     <ui-group title="初始画面" borderBottom>
       <ui-group-option>
         <div class="init-pic" :class="{ disabled: isEdit }">
-          <img :src="getFileUrl(setting!.cover)" class="init-puc-cover">
+          <img :src="getFileUrl(setting!.cover)" class="init-puc-cover" />
           <div class="init-pic-set" @click="enterSetPic">设置</div>
         </div>
       </ui-group-option>
@@ -12,16 +12,16 @@
     <ui-group title="设置天空">
       <ui-group-option>
         <div class="back-layout">
-          <div 
-            v-for="back in backs" 
-            :key="back.value" 
-            class="back-item" 
+          <div
+            v-for="back in backs"
+            :key="back.value"
+            class="back-item"
             :class="{ [back.type]: true, active: setting!.back === back.value}"
             @click="setting!.back !== back.value && changeBack(back.value)"
           >
-            <img :src="back.image" v-if="back.type === 'img'">
+            <img :src="back.image" v-if="back.type === 'img'" />
             <i class="iconfont" :class="back.image" v-else-if="back.type === 'icon'" />
-            <span :style="{background: back.image}" v-else></span>
+            <span :style="{ background: back.image }" v-else></span>
             <p class="back-item-desc">{{ back.label }}</p>
           </div>
         </div>
@@ -31,28 +31,58 @@
 </template>
 
 <script lang="ts" setup>
-import { RightFillPano } from '@/layout'
-import { enterEdit, enterOld, setting, isEdit, updataSetting } from '@/store'
-import { reactive, ref, watchEffect } from 'vue'
-import { togetherCallback, getFileUrl, loadPack } from '@/utils'
-import { showRightPanoStack, showRightCtrlPanoStack } from '@/env'
-import { sdk } from '@/sdk'
-
-const backs = ref<{ label: string, type: string, image: string, value: string}[]>([])
+import { RightFillPano } from "@/layout";
+import { enterEdit, enterOld, setting, isEdit, updataSetting } from "@/store";
+import { ref, watchEffect } from "vue";
+import { togetherCallback, getFileUrl, loadPack } from "@/utils";
+import { showRightPanoStack, showRightCtrlPanoStack, custom } from "@/env";
+import { analysisPose, sdk, SettingResourceType } from "@/sdk";
+
+const backs = ref<{ label: string; type: string; image: string; value: string }[]>([]);
 watchEffect(async () => {
   backs.value = [
-      { label: '无', type: 'icon', image: 'icon-without', value: 'none' },
-      { label: '蓝天白云', type: 'img', image: (await import("./images/pic_ltby@2x.png")).default, value: (await import("./images/蓝天白云.jpg")).default },
-      { label: '乌云密布', type: 'img', image: (await import("./images/pic_wymb@2x.png")).default, value: (await import("./images/乌云密布.jpg")).default},
-      { label: '夜空', type: 'img', image: (await import("./images/pic_yk@2x.png")).default, value: (await import("./images/夜空.jpg")).default },
-      { label: '草地', type: 'img', image: (await import("./images/pic_cd@2x.png")).default, value: (await import("./images/草地.jpg")).default },
-      { label: '道路', type: 'img', image: (await import("./images/pic_dl@2x.png")).default, value: (await import("./images/道路.jpg")).default },
-      { label: '傍晚', type: 'img', image: (await import("./images/pic_bw@2x.png")).default, value: (await import("./images/傍晚.jpg")).default },
-      { label: '灰色', type: 'color', image: '#333333', value: '#333' },
-      { label: '黑色', type: 'color', image: '#000000', value: '#000' },
-      { label: '白色', type: 'color', image: '#ffffff', value: '#fff' },
-  ]
-})
+    { label: "无", type: "icon", image: "icon-without", value: "none" },
+    {
+      label: "蓝天白云",
+      type: "img",
+      image: (await import("./images/pic_ltby@2x.png")).default,
+      value: (await import("./images/蓝天白云.jpg")).default,
+    },
+    {
+      label: "乌云密布",
+      type: "img",
+      image: (await import("./images/pic_wymb@2x.png")).default,
+      value: (await import("./images/乌云密布.jpg")).default,
+    },
+    {
+      label: "夜空",
+      type: "img",
+      image: (await import("./images/pic_yk@2x.png")).default,
+      value: (await import("./images/夜空.jpg")).default,
+    },
+    {
+      label: "草地",
+      type: "img",
+      image: (await import("./images/pic_cd@2x.png")).default,
+      value: (await import("./images/草地.jpg")).default,
+    },
+    {
+      label: "道路",
+      type: "img",
+      image: (await import("./images/pic_dl@2x.png")).default,
+      value: (await import("./images/道路.jpg")).default,
+    },
+    {
+      label: "傍晚",
+      type: "img",
+      image: (await import("./images/pic_bw@2x.png")).default,
+      value: (await import("./images/傍晚.jpg")).default,
+    },
+    { label: "灰色", type: "color", image: "#333333", value: "#333" },
+    { label: "黑色", type: "color", image: "#000000", value: "#000" },
+    { label: "白色", type: "color", image: "#ffffff", value: "#fff" },
+  ];
+});
 
 const enterSetPic = () => {
   enterEdit(
@@ -60,44 +90,43 @@ const enterSetPic = () => {
       showRightPanoStack.push(ref(false)),
       showRightCtrlPanoStack.push(ref(false)),
     ])
-  )
+  );
   enterOld(async () => {
-    const dataURL = await sdk.screenshot(300, 150)
-    const res = await fetch(dataURL)
-    const blob = await res.blob()
+    const dataURL = await sdk.screenshot(300, 150);
+    const res = await fetch(dataURL);
+    const blob = await res.blob();
+
     setting.value = {
       ...setting.value!,
       cover: { url: dataURL, blob },
-      pose: sdk.getPose()
-    }
-    await updataSetting()
-  })
-}
-
-const initBack = setting.value!.back
-let isFirst = true
+      pose: analysisPose(sdk.getPose()),
+    };
+    await updataSetting();
+  });
+};
+
+const initBack = setting.value!.back;
+let isFirst = true;
 const changeBack = (back: string) => {
-  setting.value!.back = back
-  sdk.setBackdrop(back)
+  setting.value!.back = back;
+  sdk.setBackdrop(back, SettingResourceType.envImage, {});
 
   if (isFirst) {
-    let isSave = false
-    isFirst = false
+    let isSave = false;
+    isFirst = false;
     enterEdit(() => {
       if (!isSave) {
-        setting.value!.back = initBack
-        sdk.setBackdrop(initBack)
+        setting.value!.back = initBack;
+        sdk.setBackdrop(initBack, SettingResourceType.envImage, {});
       }
-      isFirst = true
-    })
+      isFirst = true;
+    });
     enterOld(async () => {
-      isSave = true
-
-      await loadPack(updataSetting())
-    })
+      isSave = true;
+      await loadPack(updataSetting());
+    });
   }
-}
-
+};
 </script>
 
 <style scoped lang="scss">
@@ -111,8 +140,7 @@ const changeBack = (back: string) => {
 .init-puc-cover {
   width: 100%;
   height: 100%;
-  object-fit: cover
-  
+  object-fit: cover;
 }
 
 .init-pic-set {
@@ -120,7 +148,7 @@ const changeBack = (back: string) => {
   bottom: 0;
   left: 0;
   right: 0;
-  background-color: rgba(0,0,0,0.5);
+  background-color: rgba(0, 0, 0, 0.5);
   font-size: 12px;
   color: #fff;
   line-height: 32px;
@@ -136,12 +164,14 @@ const changeBack = (back: string) => {
 }
 
 .back-item {
-  > span, .iconfont, img {
+  > span,
+  .iconfont,
+  img {
     display: block;
     height: 88px;
     cursor: pointer;
     outline: 2px solid transparent;
-    transition: all .3s;
+    transition: all 0.3s;
     border-radius: 4px;
   }
   .iconfont {
@@ -157,8 +187,10 @@ const changeBack = (back: string) => {
   }
 
   &.active {
-    > span, .iconfont, img {
-      outline-color:  #00C8AF;
+    > span,
+    .iconfont,
+    img {
+      outline-color: #00c8af;
     }
   }
 }
@@ -169,4 +201,4 @@ const changeBack = (back: string) => {
   margin-top: 10px;
   text-align: center;
 }
-</style>
+</style>