浏览代码

新增定位内容

wangfumin 6 天之前
父节点
当前提交
ec9c894db1

+ 5 - 1
src/api/constant.ts

@@ -131,4 +131,8 @@ export const UPDATE_AM_MODEL = `${namespace}/caseAnimation/addOrUpdate`
 export const DELETE_AM_MODEL = `${namespace}/caseAnimation/delete`
 
 
-export const MAP_TILE_LIST = `${namespace}/notAuth/getMapConfig`
+export const MAP_TILE_LIST = `${namespace}/notAuth/getMapConfig`
+
+// 定位模块
+export const POSITION_LIST = `${namespace}/caseDevice/list`
+export const SAVE_DEVICE = `${namespace}/caseDevice/update`

+ 2 - 1
src/api/index.ts

@@ -37,4 +37,5 @@ export * from './floder'
 export * from './setting'
 export * from './path'
 export * from './animation'
-export * from './monitor'
+export * from './monitor'
+export * from './position'

+ 51 - 0
src/api/position.ts

@@ -0,0 +1,51 @@
+import axios from './instance'
+import { params } from '@/env'
+
+import { POSITION_LIST, SAVE_DEVICE } from './constant'
+
+
+interface ServicePosition {
+    fusionGuideId: number
+    cover: string
+    title: string
+    showTaggings?: boolean
+    showMeasure?: boolean
+    showMonitor?: boolean
+    showPath?: boolean
+  }
+
+interface DeviceData {
+  caseIde: string,
+  macId: string,
+  deviceName: string,
+  characterModelId: string
+}
+
+// interface characterModelList []
+  
+  export interface Position {
+    id: number
+    macId: string
+    deviceName: string
+    modelName?: string
+    createTime: string
+    updateTime: string
+    recStatus: string
+    
+    characterModel?: {
+      id: string
+      fileUrl: string
+      useDevice: string
+    }
+  }
+  
+  export type Positions = Position[]
+  
+  
+  export const fetchPositionList = async () => {
+    const positions = await axios.get<ServicePosition[]>(POSITION_LIST, { params: { caseId: params.caseId } })
+    return positions
+  }
+  export const saveDevice = async (data: any) => {
+    return axios.post<undefined>(SAVE_DEVICE, { data })
+  }

+ 5 - 1
src/api/setting.ts

@@ -11,6 +11,7 @@ type ServeSetting = {
   mapType?: 'satellite' | 'standard',
   back?: string | null;
   mapId?: number | null
+  locationModelName?: string | null
 };
 
 export type Setting = {
@@ -30,7 +31,8 @@ export type Setting = {
   back?: string | null;
   fov?: number;
   openCompass?: boolean;
-  mapId?: number | null
+  mapId?: number | null,
+  locationModelName?: string
 };
 
 const toLocal = (serviceSetting: ServeSetting): Setting => ({
@@ -40,6 +42,7 @@ const toLocal = (serviceSetting: ServeSetting): Setting => ({
   back: serviceSetting.back || undefined,
   mapType: serviceSetting.mapType || 'satellite',
   mapId: serviceSetting.mapId || undefined,
+  locationModelName: serviceSetting.locationModelName || undefined,
 });
 
 const toService = (setting: Setting): ServeSetting => ({
@@ -49,6 +52,7 @@ const toService = (setting: Setting): ServeSetting => ({
   cover: setting.cover,
   back: setting.back  || null,
   mapType: setting.mapType,
+  locationModelName: setting.locationModelName || null,
 });
 
 export const fetchSetting = async () => {

+ 19 - 0
src/assets/equipment_e.svg

@@ -0,0 +1,19 @@
+<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g filter="url(#filter0_d_21207_259375)">
+<path d="M13 10C13.5523 10 14 10.4477 14 11V15H23C23.5523 15 24 15.4477 24 16V23C24 23.5523 23.5523 24 23 24H3C2.44772 24 2 23.5523 2 23V16C2 15.4477 2.44772 15 3 15H12V11C12 10.4477 12.4477 10 13 10ZM5.5 18C4.67157 18 4 18.6716 4 19.5C4 20.3284 4.67157 21 5.5 21C6.32843 21 7 20.3284 7 19.5C7 18.6716 6.32843 18 5.5 18ZM10.5 18C9.67157 18 9 18.6716 9 19.5C9 20.3284 9.67157 21 10.5 21C11.3284 21 12 20.3284 12 19.5C12 18.6716 11.3284 18 10.5 18Z" fill="white"/>
+<path d="M13 2C17.9706 2 22 6.02944 22 11C22 11.5523 21.5523 12 21 12C20.4477 12 20 11.5523 20 11C20 7.13401 16.866 4 13 4C9.13401 4 6 7.13401 6 11C6 11.5523 5.55228 12 5 12C4.44772 12 4 11.5523 4 11C4 6.02944 8.02944 2 13 2Z" fill="white"/>
+<path d="M13 6C15.7614 6 18 8.23858 18 11C18 11.5523 17.5523 12 17 12C16.4477 12 16 11.5523 16 11C16 9.34315 14.6569 8 13 8C11.3431 8 10 9.34315 10 11C10 11.5523 9.55228 12 9 12C8.44772 12 8 11.5523 8 11C8 8.23858 10.2386 6 13 6Z" fill="white"/>
+</g>
+<defs>
+<filter id="filter0_d_21207_259375" x="-1" y="-1" width="28" height="28" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset/>
+<feGaussianBlur stdDeviation="1"/>
+<feComposite in2="hardAlpha" operator="out"/>
+<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.8 0"/>
+<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_21207_259375"/>
+<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_21207_259375" result="shape"/>
+</filter>
+</defs>
+</svg>

文件差异内容过多而无法显示
+ 5 - 0
src/assets/orientation.svg


+ 4 - 0
src/assets/record_n.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 2.5C17.2467 2.5 21.5 6.75329 21.5 12C21.5 17.2467 17.2467 21.5 12 21.5C6.75329 21.5 2.5 17.2467 2.5 12C2.5 6.75329 6.75329 2.5 12 2.5Z" stroke="white"/>
+<path d="M17 12C17 14.7614 14.7614 17 12 17C9.23858 17 7 14.7614 7 12C7 9.23858 9.23858 7 12 7C14.7614 7 17 9.23858 17 12Z" fill="#FA3D47"/>
+</svg>

+ 4 - 0
src/assets/record_s.svg

@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21V22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22V21C16.9706 21 21 16.9706 21 12Z" fill="white"/>
+<path d="M8 8H16V16H8V8Z" fill="#FA3D47"/>
+</svg>

+ 2 - 0
src/layout/edit/fuse-edit.vue

@@ -39,6 +39,7 @@ import {
   fuseModelsLoaded,
   initialPaths,
   initMonitors,
+  initialPositionList
 } from "@/store";
 
 import Header from "./header/index.vue";
@@ -56,6 +57,7 @@ const initialSys = async () => {
     initialMeasures(),
     initMonitors(),
     initialAnimationModels(),
+    initialPositionList()
   ]);
   await loadModel(fuseModel);
   const stop = watchEffect(() => {

+ 2 - 1
src/store/index.ts

@@ -15,4 +15,5 @@ export * from './floder-type'
 export * from './setting'
 export * from './case'
 export * from './path'
-export * from './monitor'
+export * from './monitor'
+export * from './position'

+ 63 - 0
src/store/position.ts

@@ -0,0 +1,63 @@
+import { ref } from 'vue'
+import { autoSetModeCallback } from './sys'
+import { fetchPositionList, saveDevice } from '@/api'
+import { 
+    togetherCallback,
+    deleteStoreItem, 
+    addStoreItem, 
+    updateStoreItem, 
+    saveStoreItems,
+    recoverStoreItems
+  } from '@/utils'
+
+export type Position = any
+
+export const positionList = ref<any>([])
+
+export const initialPositionList = async () => {
+    positionList.value = await fetchPositionList() as Position[]
+    // positionList.value = [{
+    //     id: 1,
+    //     macId: '1234567890',
+    //     deviceName: '设备1',
+    //     modelName: '模型1',
+    //     createTime: '2021-01-01',
+    //     updateTime: '2021-01-01',
+    //     locationList: [],
+    //     characterModelList: [{
+    //         id: 12,
+    //         value: 0,
+    //         label: '女',
+    //         useDevice: 0,
+    //         name: '女',
+    //         fileUrl: 'https://www.baidu.com',
+    //     }],
+    //     characterModel:{
+    //         id: 11,
+    //         fileUrl: 'https://www.baidu.com',
+    //         useDevice: '0',
+    //     }
+    // }]
+}
+
+let bcPosition: Position[] = []
+export const getBackupPosition = () => bcPosition
+export const backupPosition = () => {
+    bcPosition = positionList.value.map((position: any) => ({...position }))
+}
+export const recoverPosition = recoverStoreItems(positionList, getBackupPosition)
+export const updatePosition = updateStoreItem(positionList, saveDevice)
+export const savePositions = saveStoreItems(
+  positionList,
+  getBackupPosition,
+  {
+    update: updatePosition,
+  }
+)
+export const autoSavePositions = autoSetModeCallback([positionList], {
+  backup: togetherCallback([backupPosition]),
+  recovery: togetherCallback([recoverPosition]),
+  save: async () => {
+    await savePositions()
+  },
+})

+ 23 - 30
src/views/positioning/components/mediaList.vue

@@ -2,24 +2,22 @@
   <div class="media-list">
     <div class="media-item">
       <div class="media-item-img">
-        <ui-group title="定位设备" style="padding-bottom: 60px">
+        <ui-group v-if="!currentPosition" title="定位设备" style="padding-bottom: 60px">
             <positionSign
-                v-for="guide in guides"
-                :key="guide.id"
-                :guide="guide"
-                @edit="edit(guide)"
-                @delete="deleteGuide(guide)"
-                @updateTitle="(title) => (guide.title = title)"
+                v-for="position in positionList"
+                :key="position.id"
+                :position="position"
+                @edit="edit(position)"
             />
         </ui-group>
         <!-- 编辑页面 -->
-         <ui-group title="编辑设备">
+         <ui-group v-if="currentPosition" title="编辑设备">
           <ui-group-option>
             <div class="model-name-input">
                 设备名称
             </div>
             <ui-input
-                v-model="deviceName"
+                v-model="currentPosition.deviceName"
                 height="40px"
             />
           </ui-group-option>
@@ -27,6 +25,12 @@
             <div class="model-name-input">
                 任务模型
             </div>
+            <ui-input
+                v-model="currentPosition.modelName"
+                type="select"
+                :options="currentPosition.characterModelList"
+                height="40px"
+            />
           </ui-group-option>
          </ui-group>
       </div>
@@ -38,35 +42,24 @@
 import positionSign from "@/views/positioning/components/sign.vue";
 import { ref, watchEffect } from "vue";
 import { useViewStack } from "@/hook";
-import { guides, createGuide, enterEdit, sysBus, autoSaveGuides } from "@/store";
+import { positionList, enterEdit, sysBus, autoSavePositions } from "@/store";
 
-import type { Guide } from "@/store";
+import type { Position } from "@/store";
 
-const currentGuide = ref<Guide | null>(null);
-const deviceName = ref<any>("");
-const taskModel = ref<any>("");
-const emit = defineEmits<{ (e: "update:current", v: Guide | null): void }>();
-watchEffect(() => emit("update:current", currentGuide.value));
+const currentPosition = ref<Position | null>(null);
+const emit = defineEmits<{ (e: "update:current", v: Position | null): void }>();
+watchEffect(() => emit("update:current", currentPosition.value));
 
-const leaveEdit = () => (currentGuide.value = null);
-const edit = (guide: Guide) => {
-  currentGuide.value = guide;
+const leaveEdit = () => (currentPosition.value = null);
+const edit = (position: Position) => {
+  currentPosition.value = position;
   enterEdit();
   sysBus.on("leave", leaveEdit);
 };
 
-const deleteGuide = (guide: Guide) => {
-  const index = guides.value.indexOf(guide);
-  guides.value.splice(index, 1);
-};
-
-useViewStack(autoSaveGuides);
+useViewStack(autoSavePositions);
 
-defineExpose({
-  add: () => {
-    edit(createGuide());
-  },
-});
+defineExpose({});
 </script>
 
 <style lang="scss" scoped>

+ 20 - 92
src/views/positioning/components/sign.vue

@@ -1,28 +1,18 @@
 <template>
-    <ui-group-option class="sign-guide" :class="{ search }">
+    <ui-group-option v-if="position" class="sign-position" :class="{ search }">
       <div class="info">
-        <div class="guide-cover">
-          <img :src="getResource(getFileUrl(guide.cover))" />
-          <ui-icon
+        <div class="position-cover">
+          <img src="@/assets/equipment_e.svg" />
+          <!-- <ui-icon
             type="preview"
             class="icon"
             ctrl
-            @click="flyPlayGuide(guide)"
-            v-if="paths.length"
-          />
+            @click="flyPlayGuide(position)"
+            v-if="positionList.length"
+          /> -->
         </div>
         <div>
-          <p>{{ guide.title }}</p>
-          <!-- <ui-input
-            class="view-title-input"
-            type="text"
-            :modelValue="guide.title"
-            :maxlength="15"
-            @update:modelValue="(title: string) => $emit('updateTitle', title.trim())"
-            v-show="isEditTitle"
-            ref="inputRef"
-            height="28px"
-          /> -->
+          <p>{{ position.deviceName }}</p>
         </div>
       </div>
       <div class="actions" v-if="edit">
@@ -36,18 +26,15 @@
   </template>
   
   <script setup lang="ts">
-  import { Guide, getGuidePaths } from "@/store";
-  import { getFileUrl, saveAs } from "@/utils";
-  import { getResource } from "@/env";
+  import { Position, positionList } from "@/store";
   import { computed, watchEffect, nextTick, ref } from "vue";
   import { playSceneGuide, isScenePlayIng, pauseSceneGuide } from "@/sdk";
-  import { VideoRecorder } from "simaqcore";
   import useFocus from "bill/hook/useFocus";
   import { Message } from "bill/expose-common";
   import { flyPlayGuide } from "@/hook/use-fly";
   
   const props = withDefaults(
-    defineProps<{ guide: Guide; edit?: boolean; search?: boolean }>(),
+    defineProps<{ position: Position; edit?: boolean; search?: boolean }>(),
     {
       edit: true,
       search: false,
@@ -57,7 +44,7 @@
   const inputRef = ref();
   const isEditTitle = useFocus(computed(() => inputRef.value?.vmRef.root));
   watchEffect(() => {
-    if (!isEditTitle.value && !props.guide.title.length) {
+    if (!isEditTitle.value && !props.position.deviceName.length) {
       isEditTitle.value = true;
       Message.warning("导览名称不可为空");
     }
@@ -70,79 +57,20 @@
     (e: "edit"): void;
     (e: "record"): void;
   }>();
-  
-//   const menus = [
-//     { label: "重命名", value: "editTitle" },
-//     { label: "编辑", value: "edit" },
-//     { label: "删除", value: "delete" },
-//   ];
-    const menus = [
-        { label: "编辑", value: "edit" },
-        { label: "录制", value: "record" },
-    ];
+  const menus = [
+      { label: "编辑", value: "edit" },
+  ];
   const actions = {
     edit: () => emit("edit"),
-    record: () => emit("record"),
-    delete: () => emit("delete"),
-    download: () => {
-      const config: any = {
-        // uploadUrl: '',
-        // resolution: '4k',
-        // autoDownload: false,
-        // systemAudio: true,
-        // debug: true,
-        resolution: "4k",
-        autoDownload: false,
-        platform: "canvas",
-  
-        config: {
-          frameRate: 60,
-          canvasId: ".scene-canvas > canvas",
-        },
-        disbaledAudio: false,
-        systemAudio: false,
-        debug: false,
-      };
-  
-      const videoRecorder = new VideoRecorder(config);
-      videoRecorder.startRecord();
-  
-      let stopWatch: () => void;
-      const stopRecord = () => {
-        stopWatch && stopWatch();
-        pauseSceneGuide();
-      };
-  
-      videoRecorder.on("record", (blob) => {
-        saveAs(
-          new File([blob], "录屏.mp4", { type: "video/mp4; codecs=h264" }),
-          props.guide.title + ".mp4"
-        );
-      });
-  
-      videoRecorder.off("*");
-      videoRecorder.on("startRecord", () => {
-        flyPlayGuide(props.guide);
-        stopWatch = watchEffect(() => {
-          if (!isScenePlayIng.value) {
-            videoRecorder.endRecord();
-            nextTick(stopWatch);
-          }
-        });
-      });
-      videoRecorder.on("cancelRecord", stopRecord);
-      videoRecorder.on("endRecord", stopRecord);
-    },
   };
-  const paths = computed(() => getGuidePaths(props.guide));
   </script>
   
   <style lang="scss" scoped>
-  .sign-guide {
+  .sign-position {
     display: flex;
     justify-content: space-between;
     align-items: center;
-    padding: 20px 0;
+    padding: 16px 0;
     border-bottom: 1px solid var(--colors-border-color);
   
     &.search {
@@ -157,7 +85,7 @@
       display: flex;
       align-items: center;
   
-      .guide-cover {
+      .position-cover {
         position: relative;
         &::after {
           content: "";
@@ -176,8 +104,8 @@
         }
   
         img {
-          width: 48px;
-          height: 48px;
+          width: 24px;
+          height: 24px;
           object-fit: cover;
           border-radius: 4px;
           overflow: hidden;
@@ -192,7 +120,7 @@
         p {
           color: #fff;
           font-size: 14px;
-          margin-bottom: 6px;
+          // margin-bottom: 6px;
         }
       }
     }

+ 92 - 28
src/views/positioning/index.vue

@@ -2,7 +2,15 @@
     <RightFillPano>
     <template #header>
       <div class="tabs">
-        <span>行动录制</span>
+        <span class="tabs-left">行动录制</span>
+        <div class="tabs-right">
+            <span v-if="!isRecord"></span>
+            <span v-else class="timer-display">{{ formatTime(recordingTime) }}</span>
+            <span class="tabs-right-img">
+                <img v-if="!isRecord" src="@/assets/record_n.svg" alt="" @click="startRecord('start')">
+                <img v-else src="@/assets/record_s.svg" alt="" @click="startRecord('stop')">
+            </span>
+        </div>
       </div>
     </template>
     <mediaList />
@@ -12,12 +20,69 @@
 <script lang="ts" setup>
 import { RightFillPano } from "@/layout";
 import mediaList from "./components/mediaList.vue";
-import { nextTick, reactive, ref, watchEffect } from "vue";
+import { nextTick, reactive, ref, watchEffect, onUnmounted } from "vue";
 import { guides, isEdit, paths, enterEdit } from "@/store";
 
+const isRecord = ref(false);
+const startTime = ref<number>(0);
+const endTime = ref<number>(0);
+const recordingTime = ref<number>(0);
+let timer: NodeJS.Timeout | null = null;
+
 nextTick(() => {
 //   enterEdit();
 });
+
+// 格式化时间为 HH:MM:SS 格式
+const formatTime = (seconds: number): string => {
+    const hours = Math.floor(seconds / 3600);
+    const minutes = Math.floor((seconds % 3600) / 60);
+    const secs = seconds % 60;
+    
+    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
+};
+
+const startRecord = (type: string) => {
+    if (type === 'start') {
+        // 开始录制
+        isRecord.value = true;
+        startTime.value = Date.now(); // 记录开始时间戳
+        recordingTime.value = 0;
+        
+        // 启动计时器,每秒更新一次
+        timer = setInterval(() => {
+            recordingTime.value = Math.floor((Date.now() - startTime.value) / 1000);
+        }, 1000);
+        
+    } else {
+        // 停止录制
+        isRecord.value = false;
+        endTime.value = Date.now(); // 记录结束时间戳
+        
+        // 清除计时器
+        if (timer) {
+            clearInterval(timer);
+            timer = null;
+        }
+        
+        // 重置录制时间
+        recordingTime.value = 0;
+        
+        console.log('录制时间段:', {
+            startTime: new Date(startTime.value),
+            endTime: new Date(endTime.value),
+            duration: endTime.value - startTime.value
+        });
+    }
+};
+
+// 组件卸载时清理计时器
+onUnmounted(() => {
+    if (timer) {
+        clearInterval(timer);
+        timer = null;
+    }
+});
 </script>
 
 <style lang="scss" scoped>
@@ -25,37 +90,36 @@ nextTick(() => {
   height: 60px;
   border-bottom: 1px solid rgba(255, 255, 255, 0.16);
   display: flex;
+  justify-content: space-between;
+  align-items: center;
   margin: -20px;
+  padding: 0 20px;
   margin-bottom: 20px;
-
-  > span {
-    flex: 1;
+  .tabs-left {
+    font-size: 16px;
+    font-weight: blod;
+    color: #fff;
+  }
+  .tabs-right {
     display: flex;
     align-items: center;
-    justify-content: center;
-    position: relative;
-    transition: color 0.3s ease;
-    cursor: pointer;
-    font-size: 16px;
-
-    &::after {
-      content: "";
-      transition: height 0.3s ease;
-      position: absolute;
-      background-color: #00c8af;
-      left: 0;
-      right: 0;
-      bottom: 0;
-      height: 0;
+    gap: 10px;
+    .timer-display {
+      font-family: 'Courier New', monospace;
+      font-weight: bold;
+      color: #ff4444;
+      font-size: 14px;
+      min-width: 65px;
+      text-align: center;
     }
-
-    &:hover,
-    &.active {
-      color: #00c8af;
-    }
-
-    &.active::after {
-      height: 3px;
+    .tabs-right-img {
+     display: flex;
+     align-items: center;
+      img {
+        width: 20px;
+        height: 20px;
+        cursor: pointer;
+      }
     }
   }
 }

+ 45 - 10
src/views/setting/index.vue

@@ -18,17 +18,21 @@
     <ui-group title="设置定位参照模型">
       <ui-group-option>
         <p class="model-name">模型名称</p>
-        <div class="model-name-input">
-          11111111111111
+        <div v-if="!isEditModelName" class="model-name-input" @click="enterSetModelName">
+          <span v-if="setting?.locationModelName"><img src="@/assets/orientation.svg" alt="未设置" />{{ setting?.locationModelName }}</span>
+          <span v-else><img src="@/assets/orientation.svg" alt="未设置" />未设置</span>
         </div>
-        <ui-input
+        <div v-else class="model-name-input">
+          <img src="@/assets/orientation.svg" alt="未设置" />
+          <ui-input
             class="view-title-input"
             type="text"
-            :modelValue="modelName"
+            :modelValue="setting?.locationModelName"
             :maxlength="100"
             height="40px"
-            @update:modelValue="(title: string) => modelName = title.trim()"
+            @update:modelValue="(locationModelName: string) => getLocationModelName(locationModelName)"
         />
+        </div>
       </ui-group-option>
     </ui-group>
   </RightFillPano>
@@ -37,7 +41,7 @@
 <script lang="ts" setup>
 import { RightFillPano } from "@/layout";
 import { enterEdit, enterOld, setting, isEdit, updataSetting } from "@/store";
-import { ref } from "vue";
+import { ref, watch } from "vue";
 import { togetherCallback, getFileUrl, loadPack } from "@/utils";
 import { showRightPanoStack, showRightCtrlPanoStack } from "@/env";
 import { analysisPose, sdk } from "@/sdk";
@@ -63,11 +67,14 @@ const enterSetPic = () => {
     await updataSetting();
   });
 };
-
+watch(() => setting.value!.locationModelName, (newVal) => {
+  locationModelName = newVal;
+});
 let initBack = setting.value!.back;
 let initMapId = setting.value!.mapId;
 let isFirst = true;
-const modelName = ref("");
+let locationModelName = setting.value!.locationModelName;
+const isEditModelName = ref<boolean>(false);
 const changeBack = ([back, mapId]: [string | null, number | null]) => {
   setting.value!.back = back;
   setting.value!.mapId = mapId;
@@ -85,12 +92,33 @@ const changeBack = ([back, mapId]: [string | null, number | null]) => {
     enterOld(async () => {
       initBack = setting.value!.back;
       initMapId = setting.value!.mapId;
+      locationModelName = setting.value!.locationModelName;
       isSave = true;
-      console.log(initBack, initMapId);
+      console.log(initBack, initMapId, locationModelName);
       await loadPack(updataSetting());
     });
   }
 };
+
+const enterSetModelName = () => {
+  isEditModelName.value = true;
+  let isSave = false;
+  enterEdit(() => {
+    if (!isSave) {
+      // 不保存重置
+      setting.value!.locationModelName = locationModelName;
+    }
+    isEditModelName.value = false;
+  });
+};
+
+const getLocationModelName = (locationModelName: string) => {
+  setting.value!.locationModelName = locationModelName;
+  enterOld(async () => {
+    await loadPack(updataSetting());
+  });
+};
+
 </script>
 
 <style scoped lang="scss">
@@ -121,11 +149,18 @@ const changeBack = ([back, mapId]: [string | null, number | null]) => {
   cursor: pointer;
 }
 .model-name{
-  margin-bottom: 20px;
+  margin-bottom: 10px;
 }
 .model-name-input{
   height: 40px;
   display: flex;
   align-items: center;
+  span{
+    display: flex;
+    align-items: center;
+  }
+  img{
+    margin-right: 10px;
+  }
 }
 </style>

+ 1 - 1
vite.config.ts

@@ -6,7 +6,7 @@ import mkcert from 'vite-plugin-mkcert'
 import { resolve } from 'path'
 
 // const ip = `http://192.168.0.25`
-const ip = `https://mix3d.4dkankan.com`
+const ip = `https://test-mix3d.4dkankan.com`
 const proxy = {
   '/offlineData': {
     target: 'http://192.168.9.66:9000/',