123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- <template>
- <a-spin :spinning="spinning">
- <a-alert
- v-if="areaAvailable"
- message="检测区域范围未配置或数值较小,请在设备配置调整参数!"
- banner
- />
- <div class="viewer">
- <div class="viewer-header">
- <div class="viewer-header-title">家具与子区域配置</div>
- <div class="viewer-header-extra">
- <a-space>
- <span v-if="props.online === 0" style="color: red">⚠️设备离线,不允许编辑保存</span>
- <a-switch
- :checked="isEditDraggable"
- checked-children="启用"
- un-checked-children="禁用"
- :disabled="props.online === 0"
- @change="isEditDraggable = !isEditDraggable"
- />
- <a-button
- type="primary"
- size="small"
- :disabled="!isEditDraggable"
- @click="saveAllConfig"
- >保存配置</a-button
- >
- </a-space>
- </div>
- </div>
- <RadarEditor
- v-if="!areaAvailable"
- ref="radarEditorRef"
- :coordinates="props.ranges"
- :angle="props.angle"
- :disabled="!isEditDraggable"
- />
- </div>
- </a-spin>
- </template>
- <script setup lang="ts">
- import { ref, computed } from 'vue'
- import * as roomApi from '@/api/room'
- import { message } from 'ant-design-vue'
- import RadarEditor from '@/components/RadarEditor/index.vue'
- import { useRoomStore } from '@/stores/room'
- import {
- convert_furniture_r2c,
- convert_region_c2r,
- convert_region_r2c,
- rotateRect_ccw,
- rotateRect_cw,
- } from '@/utils/coordTransform'
- defineOptions({
- name: 'deviceAreaConfig',
- })
- type Props = {
- devId: string // 设备id,用于获取房间布局
- // x,y的范围,用于初始化画布的大小
- length: number
- width: number
- ranges: [number, number, number, number] // 区域范围
- angle: number // 设备角度,用于初始化画布的旋转角度
- online?: SwitchType | 9 // 设备在线状态,用于判断是否可以保存配置
- }
- const emit = defineEmits<{
- (e: 'success', value: void): void
- }>()
- const props = withDefaults(defineProps<Props>(), {
- devId: '',
- length: 0, // 区域宽度
- width: 0, // 区域高度
- ranges: () => [Infinity, Infinity, Infinity, Infinity], // 区域范围
- online: 0,
- })
- const deviceRoomId = ref('')
- const roomStore = useRoomStore()
- // 检测区域宽度 length
- const areaWidth = computed(() => {
- return Math.abs(props.length)
- })
- // 检测区域高度 width
- const areaHeight = computed(() => {
- return Math.abs(props.width)
- })
- // 检测区域是否可用,小于50cm的区域,不可用
- const areaAvailable = computed(() => {
- return areaWidth.value < 50 || areaHeight.value < 50
- })
- const spinning = ref(false)
- // 获取房间布局
- const fetchRoomLayout = async () => {
- console.log('fetchRoomLayout', props, props.devId)
- if (!props.devId) {
- message.error('设备ID不能为空')
- return
- }
- try {
- spinning.value = true
- const res = await roomApi.queryRoomInfo({
- devId: props.devId,
- })
- console.log('✅获取到房间布局信息', res)
- if (!res) {
- spinning.value = false
- return
- }
- const { furnitures, roomId, subRegions } = res.data
- deviceRoomId.value = roomId || ''
- roomStore.cacheFurniture(furnitures ?? [])
- roomStore.cacheSubRegion(subRegions ?? [])
- spinning.value = false
- roomStore.localFurnitureItems = roomStore.localFurnitureItems.map((item) => {
- const itemConvert = convert_furniture_r2c(
- {
- x: item.x,
- y: item.y,
- width: item.width,
- height: item.length,
- },
- {
- x_radar: 250,
- y_radar: 250,
- }
- )
- const rotatedRect = rotateRect_cw(
- {
- left: itemConvert.left,
- top: itemConvert.top,
- width: item.width,
- height: item.length,
- },
- {
- x: 250,
- y: 250,
- },
- props.angle
- )
- return {
- ...item,
- left: rotatedRect.left,
- top: rotatedRect.top,
- width: rotatedRect.width,
- length: rotatedRect.height,
- }
- })
- } catch (error) {
- console.error('❌获取房间布局信息失败', error)
- spinning.value = false
- roomStore.cacheFurniture([])
- roomStore.cacheSubRegion([])
- }
- }
- fetchRoomLayout()
- const radarEditorRef = ref<InstanceType<typeof RadarEditor>>()
- // 画布上的家具列表
- const isEditDraggable = ref(false)
- // 保存所有配置
- const saveAllConfig = () => {
- console.log('保存所有配置', {
- furnitureItems: roomStore.localFurnitureItems,
- subRegions: roomStore.localSubRegions,
- })
- const furnitureItems = roomStore.localFurnitureItems.map((item) => {
- return {
- name: item.name,
- type: item.type,
- width: item.width,
- length: item.length,
- rotate: item.rotate,
- x: item?.x || 0,
- y: item?.y || 0,
- }
- })
- console.log('保存的家具数据📚📚📚📚📚📚furnitureItems', furnitureItems)
- const subRegions = roomStore.localSubRegions.map((item) => {
- const pRadar = {
- x: 250,
- y: 250,
- }
- const rectRotatedBefore = convert_region_r2c(
- {
- x_cm_start: Number(item.startXx),
- x_cm_stop: Number(item.stopXx),
- y_cm_start: Number(item.startYy),
- y_cm_stop: Number(item.stopYy),
- },
- {
- x_radar: 250,
- y_radar: 250,
- }
- )
- const rectRotatedBack = rotateRect_ccw(rectRotatedBefore, pRadar, props.angle)
- const newRegion = convert_region_c2r(rectRotatedBack, {
- x_radar: 250,
- y_radar: 250,
- })
- return {
- startXx: newRegion.x_cm_start,
- stopXx: newRegion.x_cm_stop,
- startYy: newRegion.y_cm_start,
- stopYy: newRegion.y_cm_stop,
- startZz: item.startZz,
- stopZz: item.stopZz,
- isLowSnr: Number(item.isBed),
- isDoor: item.isDoor,
- presenceEnterDuration: item.presenceEnterDuration,
- presenceExitDuration: item.presenceExitDuration,
- trackPresence: Number(item.isTracking),
- excludeFalling: Number(item.isFalling),
- }
- })
- try {
- const res = roomApi.saveRoomInfo({
- roomId: deviceRoomId.value,
- devId: props.devId,
- furnitures: furnitureItems,
- subRegions,
- })
- console.log('保存所有配置 ✅', res)
- message.success('保存成功')
- emit('success')
- } catch (error) {
- console.error('保存所有配置 ❌', error)
- }
- }
- </script>
- <style scoped lang="less">
- .viewer {
- flex-shrink: 0;
- &-header {
- display: flex;
- justify-content: space-between;
- padding-bottom: 20px;
- &-title {
- font-size: 16px;
- font-weight: 600;
- line-height: 24px;
- }
- }
- &-content {
- display: flex;
- gap: 20px;
- }
- }
- </style>
|