ソースを参照

feat: 调整设备区域的家具配置交互界面;

liujia 3 週間 前
コミット
c7d19fe

+ 0 - 1
src/api/room/types.ts

@@ -1,4 +1,3 @@
-import type { FurnitureItem } from '@/types/radar'
 /**
  * 房间信息请求参数
  * @param devId 设备ID

+ 193 - 8
src/components/RadarEditor/index.vue

@@ -12,15 +12,65 @@
           @delete="deleteFurniture"
         />
       </template>
+
+      <template #subregion> </template>
     </RadarView>
+
+    <div v-if="!disabled && showPanel" class="options">
+      <div class="close" @click="showPanel = false">×</div>
+      <div class="header">
+        <a-radio-group v-model:value="modeRadio" button-style="solid" size="small">
+          <a-radio-button :value="1">家具</a-radio-button>
+          <!-- <a-radio-button :value="2">子区域</a-radio-button> -->
+          <!-- <a-radio-button :value="3">信息面板</a-radio-button> -->
+        </a-radio-group>
+      </div>
+
+      <div v-if="modeRadio === 1" class="furniture">
+        <a-radio-group v-model:value="sideRadio" size="small">
+          <a-radio-button :value="1">客厅</a-radio-button>
+          <a-radio-button :value="2">餐厅</a-radio-button>
+          <a-radio-button :value="3">卧室</a-radio-button>
+          <a-radio-button :value="4">卫生间</a-radio-button>
+        </a-radio-group>
+
+        <furniture-list v-if="sideRadio === 1" :icons="livingroomIcons" @add="add"></furniture-list>
+        <furniture-list v-if="sideRadio === 2" :icons="diningroomIcons" @add="add"></furniture-list>
+        <furniture-list v-if="sideRadio === 3" :icons="bedroomIocns" @add="add"></furniture-list>
+        <furniture-list v-if="sideRadio === 4" :icons="bathroomIocns" @add="add"></furniture-list>
+      </div>
+
+      <div v-if="modeRadio === 2" class="subregion">
+        <div class="subregion-header">
+          <div class="title">区域列表</div>
+          <a-button size="small">新建区域</a-button>
+        </div>
+
+        <div class="subregion-list">
+          <div class="list-item">区域1 包含床</div>
+          <div class="list-item">区域2</div>
+          <div class="list-item">区域3</div>
+          <div class="list-item">区域4</div>
+        </div>
+      </div>
+
+      <div v-if="modeRadio === 3" class="infoPanel"> 信息展示 </div>
+    </div>
+
+    <a-button v-else type="link" @click="showPanel = true">开始配置</a-button>
   </div>
 </template>
 
 <script setup lang="ts">
-import { defineOptions, ref, watch } from 'vue'
+import { ref, watch } from 'vue'
 import type { FurnitureItem } from '@/types/radar'
 import RadarView from '../RadarView/index.vue'
 import EditableFurniture from '../EditableFurniture/index.vue'
+import type { FurnitureIconType } from '@/types/furniture'
+import { message } from 'ant-design-vue'
+import { nanoid } from 'nanoid'
+import type { FurnitureType } from '@/api/room/types'
+import { furnitureIconNameMap, furnitureIconSizeMap } from '@/const/furniture'
 
 defineOptions({ name: 'RadarEditor' })
 
@@ -45,16 +95,14 @@ watch(
   { deep: true }
 )
 
-function updateFurniture(updated: FurnitureItem) {
-  const list = localFurniture.value.map((i) => (i.nanoid === updated.nanoid ? updated : i))
-  localFurniture.value = list
-  emit('update:furnitureItems', list)
+function updateFurniture(item: FurnitureItem) {
+  localFurniture.value = localFurniture.value.map((i) => (i.nanoid === item.nanoid ? item : i))
+  emit('update:furnitureItems', localFurniture.value)
 }
 
 function deleteFurniture(nanoid: string) {
-  const list = localFurniture.value.filter((i) => i.nanoid !== nanoid)
-  localFurniture.value = list
-  emit('update:furnitureItems', list)
+  localFurniture.value = localFurniture.value.filter((i) => i.nanoid !== nanoid)
+  emit('update:furnitureItems', localFurniture.value)
 }
 
 function addFurniture(item: FurnitureItem) {
@@ -63,6 +111,65 @@ function addFurniture(item: FurnitureItem) {
 }
 
 defineExpose({ addFurniture })
+
+const modeRadio = ref<1 | 2 | 3>(1)
+const sideRadio = ref<1 | 2 | 3 | 4>(1)
+
+// 客厅图标
+const livingroomIcons = [
+  'living_sofa',
+  'living_sofa_single',
+  'living_tea_table',
+  'living_bookcase',
+  'living_tv_stand',
+]
+
+// 餐厅图标
+const diningroomIcons = [
+  'dining_table',
+  'dining_table_rect',
+  'dining_fridge',
+  'dining_chair',
+  'bath_door',
+]
+
+// 卧室图标
+const bedroomIocns = [
+  'bed',
+  'bed_table',
+  'bed_dressing_chair',
+  'bed_dressing_mirror',
+  'bed_cabinet',
+]
+
+// 卫生间图标
+const bathroomIocns = ['bath_basin', 'bath_shower', 'bath_toilet', 'bath_floor']
+
+// 添加家具
+const add = (icon: FurnitureIconType) => {
+  // emit('add', icon)
+  console.log('add', icon)
+  const originWidth = furnitureIconSizeMap[icon].width || 30
+  const originHeight = furnitureIconSizeMap[icon].height || 30
+
+  const newItem: FurnitureItem = {
+    name: furnitureIconNameMap[icon],
+    type: icon as FurnitureType,
+    width: originWidth,
+    length: originHeight,
+    top: 0,
+    left: 0,
+    rotate: 0,
+    x: 0,
+    y: 0,
+    nanoid: nanoid(),
+  }
+
+  addFurniture(newItem)
+  message.success('已添加家具')
+}
+
+const showPanel = ref(true)
 </script>
 
 <style scoped lang="less">
@@ -74,4 +181,82 @@ defineExpose({ addFurniture })
     opacity: 0.85;
   }
 }
+
+.radarEditor {
+  position: relative;
+  display: flex;
+  gap: 8px;
+
+  .radar-view {
+    flex-shrink: 0;
+  }
+
+  .options {
+    width: 220px;
+    background-color: #fefefe;
+    border-radius: 10px;
+    padding: 12px;
+    position: relative;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+
+    .close {
+      position: absolute;
+      top: 8px;
+      right: 12px;
+      font-size: 22px;
+      font-weight: 600;
+      line-height: 1;
+      color: #999;
+      cursor: pointer;
+      transition: color 0.2s;
+    }
+
+    .header {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      margin-bottom: 12px;
+    }
+
+    .furniture {
+      display: flex;
+      flex-direction: column;
+      gap: 12px;
+    }
+
+    .subregion {
+      display: flex;
+      flex-direction: column;
+      gap: 12px;
+
+      &-header {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+
+        .title {
+          font-weight: 600;
+          color: #666;
+        }
+      }
+
+      &-list {
+        display: flex;
+        flex-direction: column;
+        gap: 8px;
+        gap: 8px;
+
+        .list-item {
+          display: flex;
+          align-items: center;
+          justify-content: space-between;
+          padding: 8px 12px;
+          border-radius: 8px;
+          background-color: #f5f5f5;
+          cursor: pointer;
+        }
+      }
+    }
+  }
+}
 </style>

+ 29 - 27
src/components/RadarView/index.vue

@@ -14,24 +14,28 @@
       }"
       :draggable="false"
     />
-    <div class="furnitures" :style="{ overflow: !!slots.furnitures ? 'visible' : 'hidden' }">
-      <slot name="furnitures">
-        <furniture-icon
-          v-for="item in filteredFurniture"
-          :key="item.nanoid"
-          :icon="item.type"
-          :width="item.width"
-          :height="item.length"
-          :style="{
-            left: `${item.left}px`,
-            top: `${item.top}px`,
-            position: 'absolute',
-            rotate: `${item.rotate}deg`,
-            cursor: 'default',
-          }"
-          :draggable="false"
-        />
-      </slot>
+    <div class="content">
+      <div class="furnitures" :style="{ overflow: !!slots.furnitures ? 'visible' : 'hidden' }">
+        <slot name="furnitures">
+          <furniture-icon
+            v-for="item in filteredFurniture"
+            :key="item.nanoid"
+            :icon="item.type"
+            :width="item.width"
+            :height="item.length"
+            :style="{
+              left: `${item.left}px`,
+              top: `${item.top}px`,
+              position: 'absolute',
+              rotate: `${item.rotate}deg`,
+              cursor: 'default',
+            }"
+            :draggable="false"
+          />
+        </slot>
+      </div>
+
+      <div class="subregion"><slot name="subregion"></slot></div>
     </div>
 
     <div v-if="targets && Object.keys(targets).length > 0" class="targets">
@@ -314,25 +318,23 @@ function getAxisDotStyle(axis: 'x' | 'y') {
     overflow: hidden;
     position: absolute;
     top: 0;
-    // z-index: 1;
   }
 
-  // 点位
-  .targets {
-    width: 100%;
-    height: 100%;
+  // 子区域
+  .subregion {
+    width: 0%;
+    height: 0%;
     position: absolute;
     top: 0;
-    z-index: 2;
   }
 
-  // 内容层 插槽
-  .content {
+  // 点位层
+  .targets {
     width: 100%;
     height: 100%;
     position: absolute;
     top: 0;
-    z-index: 3;
+    z-index: 2;
   }
 
   // 信息展示按钮

+ 67 - 67
src/views/device/detail/components/deviceAreaConfig/index.vue

@@ -5,12 +5,12 @@
       message="检测区域范围未配置或数值较小,请在设备配置调整参数!"
       banner
     />
-    <furnitureCard
+    <!-- <furnitureCard
       v-if="isEditDraggable"
       v-model:is-edit="isEditDraggable"
       :style="{ marginTop: '30px' }"
       @add="addHandler"
-    ></furnitureCard>
+    ></furnitureCard> -->
 
     <div class="viewer">
       <div class="viewer-header">
@@ -245,13 +245,13 @@ import type { FurnitureType, Furniture } from '@/api/room/types'
 import { message } from 'ant-design-vue'
 import { nanoid } from 'nanoid'
 import { useDropZone } from '@vueuse/core'
-import { furnitureIconNameMap, furnitureIconSizeMap } from '@/const/furniture'
-import type { FurnitureIconType } from '@/types/furniture'
-import furnitureCard from '../furnitureCard/index.vue'
+// import { furnitureIconNameMap, furnitureIconSizeMap } from '@/const/furniture'
+// import type { FurnitureIconType } from '@/types/furniture'
+// import furnitureCard from '../furnitureCard/index.vue'
 import RadarEditor from '@/components/RadarEditor/index.vue'
 import { DeleteOutlined, CloseOutlined } from '@ant-design/icons-vue'
 import { getOriginPosition } from '@/utils'
-import type { FurnitureItem } from '@/types/radar'
+// import type { FurnitureItem } from '@/types/radar'
 
 defineOptions({
   name: 'deviceAreaConfig',
@@ -413,67 +413,67 @@ const radarEditorRef = ref<InstanceType<typeof RadarEditor>>()
 const mapCanvasList = ref<CanvaseItem[]>([])
 const isEditDraggable = ref(false)
 // 家具列表添加
-const addHandler = (icon: FurnitureIconType) => {
-  console.log('addHandler', icon)
-
-  if (icon === 'bed') {
-    const isExist = mapCanvasList.value.some((item) => item.type === icon)
-    if (isExist) {
-      message.error('床已经添加过了,不可重复添加')
-      return
-    }
-  }
-
-  const originWidth = furnitureIconSizeMap[icon].width || 30
-  const originHeight = furnitureIconSizeMap[icon].height || 30
-
-  const newItem: FurnitureItem = {
-    name: furnitureIconNameMap[icon],
-    type: icon as FurnitureType,
-    width: originWidth,
-    length: originHeight,
-    top: 0,
-    left: 0,
-    rotate: 0,
-    x: 0,
-    y: 0,
-    nanoid: nanoid(),
-  }
-
-  radarEditorRef.value?.addFurniture(newItem)
-  message.success('已添加家具')
-
-  if (icon === 'bed') {
-    blocks.value.unshift({
-      id: nanoid(),
-      x: 20,
-      y: 15,
-      ox: -150,
-      oy: 180,
-      width: originWidth,
-      height: originHeight,
-      isDragging: false,
-      isResizing: false,
-      isActice: false,
-      isTracking: false,
-      isFalling: false,
-      isBed: true,
-      startXx: -150,
-      stopXx: -100,
-      startYy: 180,
-      stopYy: 120,
-      startZz: 0,
-      stopZz: 0,
-      isLowSnr: 1,
-      isDoor: 0,
-      presenceEnterDuration: 3,
-      presenceExitDuration: 3,
-      trackPresence: 0,
-      excludeFalling: 0,
-    })
-    message.success('已添加子区域')
-  }
-}
+// const addHandler = (icon: FurnitureIconType) => {
+//   console.log('addHandler', icon)
+
+//   if (icon === 'bed') {
+//     const isExist = mapCanvasList.value.some((item) => item.type === icon)
+//     if (isExist) {
+//       message.error('床已经添加过了,不可重复添加')
+//       return
+//     }
+//   }
+
+//   const originWidth = furnitureIconSizeMap[icon].width || 30
+//   const originHeight = furnitureIconSizeMap[icon].height || 30
+
+//   const newItem: FurnitureItem = {
+//     name: furnitureIconNameMap[icon],
+//     type: icon as FurnitureType,
+//     width: originWidth,
+//     length: originHeight,
+//     top: 0,
+//     left: 0,
+//     rotate: 0,
+//     x: 0,
+//     y: 0,
+//     nanoid: nanoid(),
+//   }
+
+//   radarEditorRef.value?.addFurniture(newItem)
+//   message.success('已添加家具')
+
+//   if (icon === 'bed') {
+//     blocks.value.unshift({
+//       id: nanoid(),
+//       x: 20,
+//       y: 15,
+//       ox: -150,
+//       oy: 180,
+//       width: originWidth,
+//       height: originHeight,
+//       isDragging: false,
+//       isResizing: false,
+//       isActice: false,
+//       isTracking: false,
+//       isFalling: false,
+//       isBed: true,
+//       startXx: -150,
+//       stopXx: -100,
+//       startYy: 180,
+//       stopYy: 120,
+//       startZz: 0,
+//       stopZz: 0,
+//       isLowSnr: 1,
+//       isDoor: 0,
+//       presenceEnterDuration: 3,
+//       presenceExitDuration: 3,
+//       trackPresence: 0,
+//       excludeFalling: 0,
+//     })
+//     message.success('已添加子区域')
+//   }
+// }
 
 const contentEl = ref<HTMLElement>()
 const currentDragItem = ref<CanvaseItem | null>(null)