ソースを参照

对接热点接口

bill 3 年 前
コミット
9b0ba10c53

+ 2 - 2
src/api/constant.ts

@@ -25,10 +25,10 @@ export const DELETE_MODEL = `/laser/sceneFusion/${params.m}/del`
 export const TAGGING_LIST = `/laser/sceneTag/${params.m}/list/${params.fushId}`
 export const INSERT_TAGGING = `/laser/sceneTag/${params.m}/add`
 export const UPDATE_TAGGING = `/laser/sceneTag/${params.m}/edit`
-export const DELETE_TAGGING = `/laser/sceneTag/delete`
+export const DELETE_TAGGING = `/laser/sceneTag/${params.m}/delete`
 
 // 标注放置列表
-export const TAGGING_POINT_LIST = `/laser/caseTagPoint/${params.m}/list/:id`
+export const TAGGING_POINT_LIST = `/laser/caseTagPoint/${params.m}/list/`
 export const INSERT_TAGGING_POINT = `/laser/caseTagPoint/${params.m}/place`
 export const UPDATE_TAGGING_POINT = `/laser/sceneTag/${params.m}/edit`
 export const DELETE_TAGGING_POINT = `/laser/caseTagPoint/${params.m}/delete`

+ 1 - 0
src/api/index.ts

@@ -7,5 +7,6 @@ export * from './instance'
 export * from './model'
 export * from './tagging'
 export * from './tagging-style'
+export * from './tagging-position'
 export * from './guide'
 export * from './sys'

+ 4 - 0
src/api/instance.ts

@@ -48,6 +48,10 @@ addUnsetTokenURLS(
   URL.DELETE_TAGGING,
   URL.INSERT_TAGGING,
   URL.UPDATE_TAGGING,
+  URL.TAGGING_POINT_LIST,
+  URL.INSERT_TAGGING_POINT,
+  URL.UPDATE_TAGGING_POINT,
+  URL.DELETE_TAGGING_POINT,
 )
 setDefaultURI('/api')
 

+ 1 - 31
src/api/model.ts

@@ -98,36 +98,6 @@ export type Models = Model[]
 export const fetchModels = async () => {
   const serviceModels = await axios.post<ServiceModel[]>(MODEL_LIST)
   return serviceModels.map(serviceToLocal)
-  return [
-    {
-      id: '123',
-      url: 'SS-t-7DUfWAUZ3V',
-      type: ModelType.SWSS,
-      title: 'SS-t-7DUfWAUZ3V',
-      size: 1000,
-      time: '2012-02-05',
-      rotation: { x: 1, y: 1, z: 1},
-      position: { x: 1, y: 1, z: 1},
-      opacity: 0.1,
-      scale: 1,
-      bottom: 1,
-      show: false
-    },
-    {
-      id: '124',
-      url: '/lib/resources/models/glb/coffeemat.glb',
-      type: ModelType.SWMX,
-      title: '某安外',
-      size: 1000,
-      time: '2012-02-05',
-      scale: 1,
-      rotation: { x: 1, y: 1, z: 1},
-      position: { x: 1, y: 1, z: 1},
-      opacity: 0.1,
-      bottom: 1,
-      show: true
-    }
-  ]
 } 
 
 export const postAddModel = async (file: File) => {
@@ -151,7 +121,7 @@ export const postUpdateModels = (model: Model) => {
 
 export const postDeleteModel = (id: Model['id']) => {
   console.log('delete')
-  return axios.post<undefined>(DELETE_MODEL)
+  return axios.post<undefined>(DELETE_MODEL, {ids: [id]})
 }
 
   

+ 5 - 5
src/api/setup.ts

@@ -132,11 +132,11 @@ export const axiosFactory = () => {
 
       if (!matchURL(axiosConfig.unTokenSet, config)) {
         if (!axiosConfig.token) {
-          if (!matchURL(axiosConfig.unReqErrorSet, config)) {
-            const error = new Error('缺少token')
-            callErrorHandler('req', error, config)
-            throw error
-          }
+          // if (!matchURL(axiosConfig.unReqErrorSet, config)) {
+          //   const error = new Error('缺少token')
+          //   callErrorHandler('req', error, config)
+          //   throw error
+          // }
         } else {
           config.headers = {
             ...config.headers,

+ 0 - 0
src/api/tagging-point.ts


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

@@ -0,0 +1,62 @@
+import axios from './instance'
+import { 
+  TAGGING_POINT_LIST,
+  DELETE_TAGGING_POINT,
+  UPDATE_TAGGING_POINT,
+  INSERT_TAGGING_POINT
+} from './constant'
+
+import type { Model } from './model'
+import type { Tagging } from './tagging'
+
+interface ServicePosition {
+  "id": number,
+  "tagId": number,
+  "modelId": number
+  "tagPoint": SceneLocalPos,
+}
+
+export interface TaggingPosition {
+  id: string,
+  taggingId: Tagging['id']
+  modelId: Model['id']
+  localPos: SceneLocalPos
+}
+
+export type TaggingPositions = TaggingPosition[]
+
+
+const serviceToLocal = (position: ServicePosition, taggingId?: Tagging['id']): TaggingPosition => ({
+  id: position.id.toString(),
+  modelId: position.modelId.toString(),
+  taggingId: taggingId || position.tagId.toString(),
+  localPos: position.tagPoint
+})
+
+const localToService = (position: TaggingPosition, update = false): PartialProps<ServicePosition, 'id'> => ({
+  "id": update ? Number(position.id) : undefined,
+  "tagId": Number(position.taggingId),
+  "modelId": Number(position.modelId),
+  "tagPoint": position.localPos,
+})
+
+
+export const fetchTaggingPositions = async (taggingId: Tagging['id']) => {
+  const positions = await axios.post<ServicePosition[]>(`${TAGGING_POINT_LIST}${taggingId}`, {})
+  return positions.map(position => serviceToLocal(position, taggingId))
+}
+
+export const postAddTaggingPosition = async (position: TaggingPosition) => {
+  const servicePosition = await axios.post<ServicePosition>(INSERT_TAGGING_POINT, localToService(position))
+  return serviceToLocal(servicePosition)
+}
+
+export const postUpdateTaggingPosition = (position: TaggingPosition) => {
+  return axios.post<undefined>(UPDATE_TAGGING_POINT, localToService(position, true))
+}
+  
+export const postDeleteTaggingPosition = (position: TaggingPosition) => {
+  return axios.post<undefined>(DELETE_TAGGING_POINT, { ids: [position.id] })
+}
+
+  

+ 13 - 3
src/api/tagging-style.ts

@@ -1,5 +1,6 @@
 import axios from './instance'
-import { TAGGING_STYLE_LIST } from './constant'
+import { TAGGING_LIST } from './constant'
+import { fetchTaggings } from './tagging'
 
 export interface TaggingStyle {
   id: string
@@ -10,5 +11,14 @@ export interface TaggingStyle {
 
 export type TaggingStyles = TaggingStyle[]
 
-export const getTaggingStyles = () => 
-  axios.post<TaggingStyles>(TAGGING_STYLE_LIST)
+export const getTaggingStyles = async () => {
+  // axios.post<TaggingStyles>(TAGGING_LIST)
+  return [
+    {
+      id: '1', 
+      icon: 'static/img_default/lQLPDhrvVzvNvTswMLAOU-UNqYnnZQG1YPJUwLwA_48_48.png',
+      name: '111',
+      default: true
+    }
+  ]
+}

+ 10 - 12
src/api/tagging.ts

@@ -1,4 +1,5 @@
 import axios from './instance'
+import { params } from '@/env'
 import { 
   TAGGING_LIST,
   DELETE_TAGGING,
@@ -7,6 +8,8 @@ import {
 } from './constant'
 
 import type { Model } from './model'
+import type { TaggingPosition } from './tagging-position'
+import type { TaggingStyle } from './tagging-style'
 
 interface ServerTagging {
   "hotIconId": number,
@@ -20,20 +23,15 @@ interface ServerTagging {
   "tagTitle": string,
 }
 
-export interface TaggingPosition {
-  modelId: Model['id']
-  localPos: SceneLocalPos
-}
 export interface Tagging {
   id: string
-  styleId: string
+  styleId: TaggingStyle['id']
   title: string,
   desc: string
   part: string
   method: string
   principal: string
   images: string[],
-  positions: TaggingPosition[]
 }
 
 
@@ -49,15 +47,15 @@ const serviceToLocal = (serviceTagging: ServerTagging): Tagging => ({
   method: serviceTagging.getMethod,
   principal: serviceTagging.getUser,
   images: serviceTagging.meta.map(({url}) => url),
-  positions: []
 })
 
-const localToService = (tagging: Tagging): ServerTagging => ({
+const localToService = (tagging: Tagging, update = false): PartialProps<ServerTagging, 'id' | 'hotIconUrl'> & { fusionId: number } => ({
   "hotIconId": Number(tagging.styleId),
-  "hotIconUrl": tagging.styleId,
+  "fusionId": params.fushId,
   "getMethod": tagging.method,
   "getUser": tagging.principal,
-  "id": Number(tagging.id),
+  "hotIconUrl": "static/img_default/lQLPDhrvVzvNvTswMLAOU-UNqYnnZQG1YPJUwLwA_48_48.png",
+  "id": update ? Number(tagging.id) : undefined,
   "meta": tagging.images.map(((item, i) => ({ "name": item, "url": item }))),
   "remark": tagging.part,
   "tagDescribe": tagging.desc,
@@ -71,12 +69,12 @@ export const fetchTaggings = async () => {
 }
 
 export const postAddTagging = async (tagging: Tagging) => {
-  const stagging = await axios.post<ServerTagging>(INSERT_TAGGING, tagging)
+  const stagging = await axios.post<ServerTagging>(INSERT_TAGGING, localToService(tagging))
   return serviceToLocal(stagging)
 }
 
 export const postUpdateTagging = (tagging: Tagging) => {
-  return axios.post<undefined>(UPDATE_TAGGING, localToService(tagging))
+  return axios.post<undefined>(UPDATE_TAGGING, localToService(tagging, true))
 }
   
 

+ 9 - 3
src/components/tagging/list.vue

@@ -1,6 +1,6 @@
 <template>
   <template v-if="custom.showTaggings">
-    <template v-for="(pos, index) in tagging.positions" :key="pos.id">
+    <template v-for="(pos, index) in positions" :key="pos.id">
       <Sign 
         v-if="isShowSign(pos.modelId)"
         :tagging="tagging"
@@ -11,15 +11,21 @@
 </template>
 
 <script lang="ts" setup>
+import { computed } from 'vue'
 import Sign from './sign.vue'
-import { Tagging, models, getModelShowVariable, getModel } from '@/store';
+import { Tagging, getModelShowVariable, getModel, getTaggingPositions } from '@/store';
 import { custom } from '@/env'
 
-defineProps<{ tagging: Tagging }>()
+const props = defineProps<{ tagging: Tagging }>()
 
 const isShowSign = (modelId: string) => {
   const model = getModel(modelId)
   return model?.loaded && getModelShowVariable(model).value
 }
 
+const positions = computed(() => {
+  const positions = getTaggingPositions(props.tagging)
+  return positions
+})
+
 </script>

+ 11 - 4
src/components/tagging/sign.vue

@@ -6,7 +6,11 @@
     @mouseenter="isHover = true"
     @mouseleave="isHover = false"
   >
-    <img :src="taggingStyle?.icon" @click="iconClickHandler" />
+    <img 
+      :src="getResource(taggingStyle.icon)" 
+      @click="iconClickHandler" 
+      v-if="taggingStyle" 
+    />
     <div @click.stop>
       <UIBubble
         class="hot-bubble pc" 
@@ -43,12 +47,14 @@ import { computed, ref, watchEffect, watch } from 'vue'
 import UIBubble from 'bill/components/bubble/index.vue'
 import Images from '@/views/tagging/images.vue'
 import Preview, { MediaType } from '../static-preview/index.vue'
-import { Tagging, getTaggingStyle, getModel } from '@/store';
+import { getTaggingStyle, getModel } from '@/store';
 import { getFileUrl } from '@/utils'
 import { sdk } from '@/sdk'
-import { custom } from '@/env'
+import { custom, getResource } from '@/env'
 
-export type SignProps = { tagging: Tagging, scenePos: Tagging['positions'][number], show?: boolean }
+import type { Tagging, TaggingPosition } from '@/store';
+
+export type SignProps = { tagging: Tagging, scenePos: TaggingPosition, show?: boolean }
 
 
 const props = defineProps<SignProps>()
@@ -71,6 +77,7 @@ model && watch(model, updatePosStyle, { deep: true })
 
 
 const showContent = computed(() => {
+  console.error(!~pullIndex.value , (isHover.value || custom.showTaggingPositions.has(props.scenePos)))
   return !~pullIndex.value 
     && (isHover.value || custom.showTaggingPositions.has(props.scenePos))
 })

+ 11 - 2
src/env/index.ts

@@ -31,10 +31,19 @@ export const custom = flatStacksValue({
 })
 
 
-export const params = strToParams(location.search) as Params
+export const params = strToParams(location.search) as unknown as Params
+params.fushId = Number(params.fushId)
 export type Params = { 
   m: string,
   id: string,
-  fushId: string,
+  fushId: number,
   token?: string
+}
+
+
+export const getResource = (uri: string) => {
+  if (~uri.indexOf('base64') || ~uri.indexOf('bolb') || ~uri.indexOf('//')) return uri
+  // const url = new URL(uri, '/api')
+  // return url.href
+  return `/api/profile/${uri}`
 }

+ 5 - 2
src/sdk/association.ts

@@ -1,7 +1,7 @@
 import { sdk } from './sdk'
 import { models, taggings, isEdit, sysBus, getModelShowVariable } from '@/store'
 import { toRaw, watchEffect, ref, watch } from 'vue'
-import { viewModeStack, custom } from '@/env'
+import { viewModeStack, custom, getResource } from '@/env'
 import { 
   mount, 
   diffArrayChange, 
@@ -27,7 +27,10 @@ const associationModels = (sdk: SDK) => {
       }
 
       const itemRaw = toRaw(item)
-      const sceneModel = sdk.addModel(itemRaw)
+      const sceneModel = sdk.addModel({
+        ...itemRaw,
+        url: getResource(item.url)
+      })
       sceneModelMap.set(itemRaw, sceneModel)
 
       sceneModel.bus.on('transformChanged', transform => {

+ 4 - 3
src/store/index.ts

@@ -1,7 +1,7 @@
 import { ref } from 'vue'
 import { initialModels } from './model'
 import { initialTaggings } from './tagging'
-import { initialTaggingStyles } from './taging-style'
+import { initialTaggingStyles } from './tagging-style'
 import { initialGuides } from './guide'
 
 export const loaded = ref(false)
@@ -25,5 +25,6 @@ export const initialStore = async () => {
 export * from './sys'
 export * from './model'
 export * from './tagging'
-export * from './taging-style'
-export * from './guide'
+export * from './tagging-style'
+export * from './guide'
+export * from './tagging-positions'

+ 66 - 0
src/store/tagging-positions.ts

@@ -0,0 +1,66 @@
+import { ref } from 'vue'
+import { autoSetModeCallback, createTemploraryID } from './sys'
+import { 
+  fetchTaggingPositions, 
+  postAddTaggingPosition,
+  postDeleteTaggingPosition,
+  postUpdateTaggingPosition,
+} from '@/api'
+import { 
+  deleteStoreItem, 
+  addStoreItem, 
+  updateStoreItem, 
+  saveStoreItems,
+  recoverStoreItems
+} from '@/utils'
+
+import type { TaggingPosition, TaggingPositions } from '@/api'
+import type { Tagging } from './tagging'
+
+export type { TaggingPosition, TaggingPositions }
+
+export const taggingPositions = ref<TaggingPositions>([])
+export const createTaggingPosition = (position: Partial<TaggingPosition> = {}): TaggingPosition => ({
+  id: createTemploraryID(),
+  taggingId: '',
+  modelId: '',
+  localPos: { x: 0, y: 0, z: 0 },
+  ...position
+})
+
+export const getTaggingPositions = (tagging: Tagging) => 
+  taggingPositions.value.filter(position => position.taggingId === tagging.id) || []
+
+let bcPositions: TaggingPositions = []
+export const getBackupTaggingPositions = () => bcPositions
+export const backupTaggingPositions = () => {
+  bcPositions = taggingPositions.value.map(position => ({
+    ...position,
+    localPos: { ...position.localPos },
+  }))
+}
+
+export const initTaggingPositionsByTagging = async (tagging: Tagging) => {
+  const positions = await fetchTaggingPositions(tagging.id)
+  taggingPositions.value.push(...positions)
+  backupTaggingPositions()
+}
+
+export const recoverTaggingPositions = recoverStoreItems(taggingPositions, getBackupTaggingPositions)
+export const addTaggingPosition = addStoreItem(taggingPositions, postAddTaggingPosition)
+export const updateTaggingPosition = updateStoreItem(taggingPositions, postUpdateTaggingPosition)
+export const deleteTaggingPosition = deleteStoreItem(taggingPositions, postDeleteTaggingPosition)
+export const saveTaggingPositions = saveStoreItems(
+  taggingPositions, 
+  getBackupTaggingPositions,
+  {
+    add: addTaggingPosition,
+    update: updateTaggingPosition,
+    delete: deleteTaggingPosition,
+  }
+)
+export const autoSaveTaggingPositions = autoSetModeCallback(taggingPositions, {
+  backup: backupTaggingPositions,
+  recovery: recoverTaggingPositions,
+  save: saveTaggingPositions,
+})

+ 3 - 10
src/store/taging-style.ts

@@ -1,23 +1,16 @@
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import { getTaggingStyles } from '@/api'
 
 import type { TaggingStyles, TaggingStyle } from '@/api'
 
 export const taggingStyles = ref<TaggingStyles>([])
+export const defaultStyle = computed(() => taggingStyles.value.find(style => style.default))
 
 export const getTaggingStyle = (id: TaggingStyle['id']) => 
   taggingStyles.value.find(style => style.id === id)
 
 export const initialTaggingStyles = async () => {
-  // taggings.value = await getTaggingStyles()
-  taggingStyles.value = [
-    {
-      id: '1231',
-      name: 'aaa',
-      icon: 'https://gw.alicdn.com/tps/TB1W_X6OXXXXXcZXVXXXXXXXXXX-400-400.png',
-      default: true
-    }
-  ]
+  taggingStyles.value = await getTaggingStyles()
 }
 
 

+ 32 - 10
src/store/tagging.ts

@@ -1,5 +1,15 @@
 import { ref } from 'vue'
+import { togetherCallback } from '@/utils'
 import { autoSetModeCallback, createTemploraryID } from './sys'
+import { defaultStyle } from './tagging-style'
+import { 
+  initTaggingPositionsByTagging, 
+  saveTaggingPositions,
+  recoverTaggingPositions,
+  backupTaggingPositions,
+  taggingPositions,
+  getTaggingPositions
+} from './tagging-positions'
 import { 
   fetchTaggings, 
   postAddTagging,
@@ -21,20 +31,18 @@ import type { Tagging as STagging } from '@/api'
 
 export type Tagging = LocalMode<STagging, 'images'>
 export type Taggings = Tagging[]
-export type { TaggingPosition } from '@/api'
 
 export const taggings = ref<Taggings>([])
 
 export const createTagging = (tagging: Partial<Tagging> = {}): Tagging => ({
   id: createTemploraryID(),
   title: ``,
-  styleId: '',
+  styleId: defaultStyle.value?.id || '',
   desc: '',
   part: '',
   method: '',
   principal: '',
   images: [],
-  positions: [],
   ...tagging
 })
 
@@ -45,7 +53,6 @@ export const backupTaggings = () => {
   bcTaggings = taggings.value.map(tagging => ({
     ...tagging,
     images: [...tagging.images],
-    positions: [...tagging.positions]
   }))
 }
 
@@ -60,10 +67,21 @@ export const transformTagging = async (tagging: Tagging): Promise<STagging> => {
 }
 
 export const recoverTaggings = recoverStoreItems(taggings, () => bcTaggings)
-export const addTagging = addStoreItem(taggings, postAddTagging, transformTagging)
+export const addTagging = addStoreItem(taggings, async (localTagging) => {
+  const serviceTagging = await postAddTagging(localTagging)
+  const positions = getTaggingPositions(localTagging)
+  for (const position of positions) {
+    position.taggingId = serviceTagging.id
+  }
+  return serviceTagging
+}, transformTagging)
 export const updateTagging = updateStoreItem(taggings, postUpdateTagging, transformTagging)
 export const deleteTagging = deleteStoreItem(taggings, tagging => postDeleteTagging(tagging.id))
-export const initialTaggings = fetchStoreItems(taggings, fetchTaggings, backupTaggings)
+export const initialTaggings = fetchStoreItems(taggings, async () => {
+  const taggings = await fetchTaggings()
+  await Promise.all(taggings.map(initTaggingPositionsByTagging))
+  return taggings
+}, backupTaggings)
 export const saveTaggings = saveStoreItems(
   taggings, 
   getBackupTaggings,
@@ -73,8 +91,12 @@ export const saveTaggings = saveStoreItems(
     delete: deleteTagging,
   }
 )
-export const autoSaveTaggings = autoSetModeCallback(taggings, {
-  backup: backupTaggings,
-  recovery: recoverTaggings,
-  save: saveTaggings,
+
+export const autoSaveTaggings = autoSetModeCallback([taggings, taggingPositions], {
+  backup: togetherCallback([backupTaggings, backupTaggingPositions]),
+  recovery: togetherCallback([recoverTaggings, recoverTaggingPositions]),
+  save: async () => {
+    await saveTaggings()
+    await saveTaggingPositions()
+  },
 })

+ 12 - 4
src/views/tagging/index.vue

@@ -62,7 +62,10 @@ import {
   enterEdit, 
   Model,
   getModel,
-getModelShowVariable
+  getModelShowVariable,
+  getTaggingPositions,
+  taggingPositions,
+createTaggingPosition
 } from '@/store'
 import { 
   custom, 
@@ -93,15 +96,16 @@ const deleteTagging = (tagging: Tagging) => {
 
 let stopFlyTaggingPositions: () => void
 const flyTaggingPositions = (tagging: Tagging) => {
+  const positions = getTaggingPositions(tagging)
   stopFlyTaggingPositions && stopFlyTaggingPositions()
 
   let isStop = false
 
   const flyIndex = (i: number) => {
-    if (isStop || i >= tagging.positions.length) {
+    if (isStop || i >= positions.length) {
       return;
     }
-    const position = tagging.positions[i]
+    const position = positions[i]
     const model = getModel(position.modelId)
     if (!model || !getModelShowVariable(model).value) {
       flyIndex(i + 1)
@@ -169,7 +173,11 @@ watch(selectTagging, (a, b, onCleanup) => {
       if (!position) {
         Message.error('当前位置无法添加')
       } else if (selectTagging.value) {
-        selectTagging.value.positions.push(position)
+        const storePosition = createTaggingPosition({
+          ...position,
+          taggingId: selectTagging.value.id
+        })
+        taggingPositions.value.push(storePosition)
         leave()
       }
     }

+ 8 - 6
src/views/tagging/sign.vue

@@ -1,10 +1,10 @@
 <template>
   <ui-group-option class="sign-tagging" :class="{active: selected}" @click="emit('select')">
     <div class="info">
-      <img :src="getFileUrl(tagging.images[0])">
+      <img :src="getResource(getFileUrl(style.icon))" v-if="style">
       <div>
         <p>{{ tagging.title }}</p>
-        <a @click.stop="$emit('flyPositions')">放置:{{ tagging.positions.length }}</a>
+        <a @click.stop="$emit('flyPositions')">放置:{{ positions.length }}</a>
       </div>
     </div>
     <div class="actions" @click.stop>
@@ -19,12 +19,14 @@
 </template>
 
 <script setup lang="ts">
-import { Tagging } from '@/store'
-import { getFileUrl, asyncTimeout } from '@/utils'
-import { sdk } from '@/sdk'
-
+import { Tagging, getTaggingStyle, getTaggingPositions } from '@/store'
+import { getFileUrl } from '@/utils'
+import { computed } from 'vue';
+import { getResource } from '@/env'
 
 const props = defineProps<{ tagging: Tagging, selected?: boolean }>()
+const style = computed(() => getTaggingStyle(props.tagging.styleId))
+const positions = computed(() => getTaggingPositions(props.tagging))
 
 const emit = defineEmits<{ 
   (e: 'delete'): void 

+ 0 - 1
src/views/tagging/style.scss

@@ -28,7 +28,6 @@
       object-fit: cover;
       border-radius: 4px;
       overflow: hidden;
-      background-color: rgba(255,255,255,.6);
       display: block;
     }
 

+ 3 - 0
vite.config.ts

@@ -24,6 +24,9 @@ export default defineConfig({
     host: '0.0.0.0',
     port: 5173,
     open: true,
+    watch: {
+      usePolling: true
+    },
     proxy: {
       '/api': {
         target: 'http://192.168.0.152:8088/',