Browse Source

feat(views): 暖通图元支持绑定设备

wangcong 3 weeks ago
parent
commit
9920c9ea2e

+ 13 - 0
src/services/common.ts

@@ -16,6 +16,8 @@ import { useSelection } from '@/services/selections';
 import { rootDomain } from './defaults';
 import { updateObject } from './object';
 import i18n from '../i18n';
+import { HvacDevicePen, IframeMsg } from '@/types';
+import { getVisual2DMsgType, Visual2DMsgType } from '@/views';
 const $t = i18n.global.t;
 const { select } = useSelection();
 
@@ -458,6 +460,17 @@ export const save = async (
   }
 
   notice && MessagePlugin.success($t('保存成功!'));
+  
+  const msg: IframeMsg = {
+    msgType: getVisual2DMsgType(Visual2DMsgType.SendDeviceIds),
+    deviceIds: data.pens
+      .filter((item) => (item as HvacDevicePen).hvacDeviceInfo?.id)
+      .map((item) => (item as HvacDevicePen).hvacDeviceInfo.id)
+      .join(","),
+  };
+
+  window.parent.postMessage(msg, "*");
+
   meta2d.emit('business-save', vType);
   dot.value = false;
   localforage.removeItem(localStorageName);

+ 41 - 0
src/types/index.ts

@@ -1,4 +1,5 @@
 import { IconfontIcon } from "@/icons/fonts/iconfont";
+import { Pen } from "@meta2d/core";
 
 export interface IconObject {
   name: IconfontIcon;
@@ -48,4 +49,44 @@ export interface MonitoringPointData {
 export interface CurvedData {
   time: string;
   value: number;
+}
+
+export interface DeviceItem {
+  id: number;
+  createTime: string;
+  updateTime: string;
+  createUserId: number;
+  updateUserId: number;
+  deviceName: string;
+  groupId: number;
+  deviceType: number;
+  userId: number;
+  brand: number;
+  model: number;
+  modelType: number;
+  controlType: number;
+  compressionLevel: number;
+  voltageLevel: number;
+  powerRating: number;
+  powerUnload: number;
+  maximumFlow: number;
+  pressure: number;
+  pressureMax: number;
+  productionDate: string;
+  productionNum: string;
+  mainTechData: string;
+  mountedPosition: string;
+  department: string;
+  respPerson: string;
+  phone: string;
+  serviceLife: number;
+  status: number;
+  remarks: string;
+  deleted: number;
+  deviceNum: string;
+  runningStatus: string;
+}
+
+export interface HvacDevicePen extends Pen {
+  hvacDeviceInfo: Partial<DeviceItem>;
 }

+ 10 - 4
src/views/Index.vue

@@ -8,7 +8,7 @@
       <div style="border-left: 1px solid var(--color-border);">
         <FitProps v-if="selections.mode === SelectionMode.Fit" />
         <FileProps v-else-if="selections.mode === SelectionMode.File" />
-        <PenProps v-else-if="selections.mode === SelectionMode.Pen" />
+        <PenProps v-else-if="selections.mode === SelectionMode.Pen" :device-list="currentDevices" />
         <PensProps v-else />
       </div>
     </div>
@@ -25,10 +25,12 @@ import PensProps from './components/PensProps.vue';
 import FitProps from './components/FitProps.vue';
 
 import { useSelection, SelectionMode } from '@/services/selections';
-import { onMounted, onUnmounted } from "vue";
-import { IframeMsg } from '@/types';
+import { onMounted, onUnmounted, ref } from "vue";
+import { DeviceItem, IframeMsg } from '@/types';
 import { getVisual2DMsgType, Visual2DMsgType } from '.';
 
+const currentDevices = ref<DeviceItem[]>([]);
+
 onMounted(()=>{
   selections.mode = SelectionMode.File
 
@@ -46,7 +48,11 @@ onUnmounted(() => {
 });
 
 const handleMsg = (e: MessageEvent<IframeMsg>) => {
-  // const { msgType } = e.data;
+  const { msgType, deviceList } = e.data;
+  
+  if (msgType === getVisual2DMsgType(Visual2DMsgType.SendDeviceData)) {
+    currentDevices.value = deviceList as DeviceItem[];
+  }
 };
 
 const { selections } = useSelection();

+ 12 - 1
src/views/Preview.vue

@@ -14,7 +14,7 @@ import { Meta2d, Options, Pen } from '@meta2d/core';
 import { registerBasicDiagram } from '@/services/register';
 import { cdn, getLe5leV,getComponents } from '@/services/api';
 import { getDownloadList, getPayList,getFrameDownloadList, Frame} from '@/services/download';
-import { IframeMsg } from '@/types';
+import { HvacDevicePen, IframeMsg } from '@/types';
 import { getVisual2DMsgType, Visual2DMsgType } from '.';
 const route = useRoute();
 
@@ -53,6 +53,7 @@ onMounted(() => {
   }
   open();
   meta2d.on('opened', opened);
+  meta2d.on('openDeviceCtrlModal', openHvacDevCtrlModal);
   window.addEventListener('click', handlePreviewClick)
   window.addEventListener('message', handleMsg);
   window.addEventListener('message', dealWithMessage);
@@ -65,6 +66,15 @@ onMounted(() => {
   window.parent.postMessage(msg, "*");
 });
 
+const openHvacDevCtrlModal = ({ pen }: { pen: HvacDevicePen }) => {
+  const msg: IframeMsg = {
+    msgType: getVisual2DMsgType(Visual2DMsgType.OpenDevCtrlModal),
+    hvacDeviceId: pen.hvacDeviceInfo.id
+  };
+
+  window.parent.postMessage(msg, "*");
+}
+
 const handleMsg = (e: MessageEvent<IframeMsg>) => {
   // const { msgType } = e.data;
 };
@@ -268,6 +278,7 @@ onUnmounted(() => {
   watcher();
   if (meta2d) {
     meta2d.off('opened', opened);
+    meta2d.off('openDeviceCtrlModal', openHvacDevCtrlModal);
     meta2d.destroy();
   }
   window.removeEventListener('click', handlePreviewClick)

+ 21 - 1
src/views/components/Graphics.vue

@@ -396,7 +396,7 @@ import { onMounted, onUnmounted, reactive, ref } from 'vue';
 import { useRouter, useRoute } from 'vue-router';
 import { MessagePlugin } from 'tdesign-vue-next';
 import axios from 'axios';
-import { deepClone } from '@meta2d/core';
+import { deepClone, EventAction } from '@meta2d/core';
 
 import { cases, shapes, formComponents, templates } from '@/services/defaults';
 import { charts } from '@/services/echarts';
@@ -1372,6 +1372,26 @@ const dragStart = async (event: DragEvent | MouseEvent|TouchEvent, item: any) =>
       ratio: true,
       lockedOnCombine,
     };
+
+    if (data.image.includes('2.5D-采暖系统')) {
+      Object.assign(data, {
+        description: item.image.match(/2\.5D-采暖系统\/([^\/]+)\.[^.]+$/)?.[1],
+        hvacDeviceInfo: {},
+        events: [
+          {
+            name: "click",
+            conditions: [],
+            actions: [
+              {
+                action: EventAction.Emit,
+                value: "openDeviceCtrlModal",
+              }
+            ],
+            hideInPanel: true
+          },
+        ],
+      })
+    }
   } else {
     return;
   }

+ 1 - 1
src/views/components/PenEvents.vue

@@ -7,7 +7,7 @@
         :expand-on-row-click="true"
         expand-icon-placement="left"
       >
-        <t-collapse-panel v-for="(item, i) in props.pen.events" :value="i">
+        <t-collapse-panel v-for="(item, i) in props.pen.events" v-show="!item.hideInPanel" :value="i">
           <template #header>
             <div @click.stop class="head flex">
               <t-select

+ 26 - 1
src/views/components/PenProps.vue

@@ -41,6 +41,19 @@
               </template>
             </t-select-input>
           </div>
+          <div v-if="data.pen.hvacDeviceInfo" class="form-item px-12" style="margin-top: -12px">
+            <label style="width: 50px">{{$t('设备')}}</label>
+            <t-cascader
+              v-model="data.pen.hvacDeviceInfo.id"
+              :keys="{ value: 'id' }"
+              :options="deviceList"
+              :placeholder="$t('请选择设备')"
+              filterable
+              clearable
+              :show-all-levels="false"
+              @change="handleDeviceChange"
+            />
+          </div>
           <div v-if="isDom" class="form-item px-12" style="margin-top: -12px">
             <label style="width: 50px">z-index</label>
             <t-input-number
@@ -1287,7 +1300,7 @@ import Custom from './Custom.vue';
 import { useSelection } from '@/services/selections';
 import { autoSave, fonts, inTreePanel } from '@/services/common';
 import { updatePen } from './pen';
-import { MessagePlugin } from 'tdesign-vue-next';
+import { CascaderChangeContext, CascaderValue, MessagePlugin } from 'tdesign-vue-next';
 import { useUser } from '@/services/user';
 import { getter, queryURLParams, isDomShapes } from '@meta2d/core';
 import { defaultGradientColor, defaultPureColor, fromArrows, toArrows } from '@/services/defaults';
@@ -1296,6 +1309,13 @@ import { s8 } from '@/services/random';
 import { EllipsisIcon, LinkIcon, LinkUnlinkIcon, ChevronDownIcon, FormatVerticalAlignLeftIcon, FormatHorizontalAlignCenterIcon, FormatVerticalAlignCenterIcon, FormatVerticalAlignRightIcon, FormatHorizontalAlignTopIcon, FormatHorizontalAlignBottomIcon  } from 'tdesign-icons-vue-next';
 import { getToken  } from '@le5le/auth-token';
 import { getImgUrl } from '@/services/utils';
+import { DeviceItem } from '@/types';
+
+interface Props {
+  deviceList: DeviceItem[];
+}
+
+const props = defineProps<Props>();
 
 const { user } = useUser();
 const headers = {
@@ -1564,6 +1584,11 @@ const changeValue = (prop: string) => {
   }
 };
 
+const handleDeviceChange = (value: CascaderValue<DeviceItem>, context: CascaderChangeContext<DeviceItem>) => {
+  data.pen.description = context.node.label
+  Object.assign(data.pen.hvacDeviceInfo, context.node.data)
+}
+
 const getThumbImg = async () => {
   //改iframe地址后
   let arr = data.pen.iframe.split('?');

+ 2 - 0
src/views/index.ts

@@ -10,6 +10,8 @@ export const enum Visual2DMsgType {
   EditLoaded = 'edit-loaded',
   CloseEditor = 'close-editor',
   SendDeviceData = 'send-device-data',
+  SendDeviceIds = 'send-device-ids',
+  OpenDevCtrlModal = 'open-dev-ctrl-modal',
   PreviewLoaded = 'preview-loaded',
   PreviewClicked = 'preview-clicked',
 }