Forráskód Böngészése

feat(views): 环境监控区域支持浏览画布

wangcong 2 hónapja
szülő
commit
3949c13f18

+ 4 - 0
src/utils/env-area.ts

@@ -12,6 +12,10 @@ export const enum EnvAreaMsgType {
   EditOutdoorTempHumidity = 'edit-outdoor-temp-humidity',
   SubmitEditArea = 'submit-edit-area',
   CancelEditArea = 'cancel-edit-area',
+  PreviewLoaded = 'preview-loaded',
+  PreviewArea = 'preview-area',
+  HighlightEnvMonitorPoint = 'highlight-env-monitor-point',
+  HighlightCanvasMonitorPoint = 'highlight-canvas-monitor-point',
 }
 
 export const getEnvAreaMsgType = (type: EnvAreaMsgType) => {

+ 87 - 0
src/views/env-monitor/AreaPreview.vue

@@ -0,0 +1,87 @@
+<script setup lang="ts">
+import { onMounted, onUnmounted, useTemplateRef, watch } from 'vue';
+
+import { EnvAreaMsgType, getEnvAreaMsgType } from '@/utils/env-area';
+
+import type { IframeMsg, RegionsPointsItem } from '@/types';
+
+interface Props {
+  areaData?: RegionsPointsItem;
+}
+
+const props = defineProps<Props>();
+
+const emit = defineEmits<{
+  highlightEnvPoint: [id: number];
+}>();
+
+const iframeRef = useTemplateRef('previewIframe');
+let isIframeLoaded = false;
+
+onMounted(() => {
+  window.addEventListener('message', handleIframeMsg);
+});
+
+onUnmounted(() => {
+  window.removeEventListener('message', handleIframeMsg);
+});
+
+watch(
+  () => props.areaData,
+  () => {
+    if (isIframeLoaded) {
+      sendAreaData();
+    }
+  },
+);
+
+const handleIframeMsg = (e: MessageEvent<IframeMsg>) => {
+  const { msgType } = e.data;
+
+  if (msgType === getEnvAreaMsgType(EnvAreaMsgType.PreviewLoaded)) {
+    isIframeLoaded = true;
+    sendAreaData();
+  } else if (msgType === getEnvAreaMsgType(EnvAreaMsgType.HighlightEnvMonitorPoint)) {
+    emit('highlightEnvPoint', e.data.monitorPointId);
+  }
+};
+
+const sendAreaData = () => {
+  if (props.areaData) {
+    const msg: IframeMsg = {
+      msgType: getEnvAreaMsgType(EnvAreaMsgType.PreviewArea),
+      ...JSON.parse(JSON.stringify(props.areaData)),
+    };
+
+    iframeRef.value?.contentWindow?.postMessage(msg, '*');
+  }
+};
+
+const highlightCanvasPoint = (id: number) => {
+  const msg: IframeMsg = {
+    msgType: getEnvAreaMsgType(EnvAreaMsgType.HighlightCanvasMonitorPoint),
+    monitorPointId: id,
+  };
+
+  iframeRef.value?.contentWindow?.postMessage(msg, '*');
+};
+
+defineExpose({
+  highlightCanvasPoint,
+});
+</script>
+
+<template>
+  <iframe class="env-area-preview" ref="previewIframe" src="http://localhost:88/env-area/preview"></iframe>
+</template>
+
+<style lang="scss" scoped>
+.env-area-preview {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  background: transparent;
+  border: none;
+  border-radius: 12px;
+}
+</style>

+ 12 - 1
src/views/env-monitor/EnvMonitor.vue

@@ -28,6 +28,7 @@ import { HumitureType } from '@/constants';
 import envMonitorBgc from '@/assets/img/env-monitor-bgc.png';
 
 import AreaEditor from './AreaEditor.vue';
+import AreaPreview from './AreaPreview.vue';
 import EnvMonitorList from './EnvMonitorList.vue';
 import HumitureCurve from './HumitureCurve.vue';
 
@@ -545,6 +546,7 @@ onMounted(() => {
 });
 
 const areaEditorRef = useTemplateRef('areaEditor');
+const areaPreviewRef = useTemplateRef('areaPreview');
 const currentAreaData = computed(() => {
   return monitoringList.value.find((item) => item.id === selectId.value);
 });
@@ -568,6 +570,10 @@ const saveAreaCanvas = (canvas: string) => {
     }
   });
 };
+
+const highlightEnvPoint = () => {
+  return;
+};
 </script>
 
 <template>
@@ -619,7 +625,11 @@ const saveAreaCanvas = (canvas: string) => {
       </div>
       <AFlex class="content-monitoring-canvas">
         <div class="content-monitoring-canvas-left">
-          <div v-for="item in monitoringPointData" :key="item.id">
+          <div
+            v-for="item in monitoringPointData"
+            :key="item.id"
+            @click="areaPreviewRef?.highlightCanvasPoint(item.id)"
+          >
             <LineChart
               :data="item"
               :icon-show="true"
@@ -663,6 +673,7 @@ const saveAreaCanvas = (canvas: string) => {
                 <SvgIcon name="outdoor" />
                 22.9℃|60.6%
               </AButton>
+              <AreaPreview ref="areaPreview" :area-data="currentAreaData" @highlight-env-point="highlightEnvPoint" />
             </div>
           </div>
         </AFlex>