From 8c1b3d5463802ce43400fc83479641af9a298a38 Mon Sep 17 00:00:00 2001 From: donghao <donghao@supervision.ltd> Date: Thu, 15 Aug 2024 18:00:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=BE=E5=A4=87=E5=85=B3=E8=81=94?= =?UTF-8?q?=E5=B8=83=E7=82=B9=E6=8E=A5=E5=8F=A3=E8=81=94=E8=B0=83=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/workshops.ts | 16 +- src/core/plugin/ControlsPlugin.ts | 14 +- src/core/plugin/DeleteHotKeyPlugin.ts | 3 +- .../deviceSetting/components/deviceAttr.vue | 104 +++++++++---- .../deviceSetting/components/deviceSelect.vue | 140 +++++++++++------- .../deviceSetting/hooks/useDeviceObject.ts | 47 +++--- .../deviceSetting/hooks/usePointObject.ts | 23 ++- src/views/deviceSetting/index.scss | 15 +- src/views/deviceSetting/index.vue | 131 +++++++++++----- 9 files changed, 338 insertions(+), 155 deletions(-) diff --git a/src/api/workshops.ts b/src/api/workshops.ts index 642716d..e5bda0a 100644 --- a/src/api/workshops.ts +++ b/src/api/workshops.ts @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-08-02 10:40:49 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-08-14 17:09:46 + * @LastEditTime: 2024-08-15 16:14:24 * @FilePath: \General-AI-Platform-Web-Client\src\api\workshops.ts * @Description: 布点 */ @@ -75,3 +75,17 @@ export const addWorkshopDevicesApi = (data?: object) => { data }); }; + +/** 编辑布点设备 data有id */ +export const editWorkshopDevicesApi = (data?: object) => { + return http.request<Result>("post", baseUrlApi("workshop_devices/"), { + data + }); +}; + +/** 删除布点设备 status: 1 */ +export const deleteWorkshopDevicesApi = (data?: object) => { + return http.request<Result>("post", baseUrlApi("workshop_devices/"), { + data: { ...data, status: 1 } + }); +}; diff --git a/src/core/plugin/ControlsPlugin.ts b/src/core/plugin/ControlsPlugin.ts index 13df367..284b8cf 100644 --- a/src/core/plugin/ControlsPlugin.ts +++ b/src/core/plugin/ControlsPlugin.ts @@ -2,7 +2,7 @@ * @Author: 秦少卫 * @Date: 2023-06-13 23:00:43 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-08-07 17:17:54 + * @LastEditTime: 2024-08-15 16:28:40 * @Description: 控制条插件 */ @@ -174,9 +174,15 @@ function deleteControl(canvas: fabric.Canvas) { if (target.action === "rotate") return true; const activeObject = canvas.getActiveObjects(); if (activeObject) { - activeObject.map(item => canvas.remove(item)); - canvas.requestRenderAll(); - canvas.discardActiveObject(); + // 发送删除事件 + canvas.fire("object:deleteObject", { + ...activeObject, + deleteCallback: () => { + activeObject.map(item => canvas.remove(item)); + canvas.requestRenderAll(); + canvas.discardActiveObject(); + } + }); } return true; } diff --git a/src/core/plugin/DeleteHotKeyPlugin.ts b/src/core/plugin/DeleteHotKeyPlugin.ts index c839510..29fb60b 100644 --- a/src/core/plugin/DeleteHotKeyPlugin.ts +++ b/src/core/plugin/DeleteHotKeyPlugin.ts @@ -2,12 +2,13 @@ * @Author: 秦少卫 * @Date: 2023-06-20 12:57:35 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-08-06 17:14:38 + * @LastEditTime: 2024-08-15 15:51:16 * @Description: 删除快捷键 */ import { fabric } from "fabric"; import Editor from "../core"; + type IEditor = Editor; // import { v4 as uuid } from 'uuid'; diff --git a/src/views/deviceSetting/components/deviceAttr.vue b/src/views/deviceSetting/components/deviceAttr.vue index 32f385e..3b604ca 100644 --- a/src/views/deviceSetting/components/deviceAttr.vue +++ b/src/views/deviceSetting/components/deviceAttr.vue @@ -6,34 +6,45 @@ import { textTypeConf } from "@/config/attribute/baseType"; import video_type_1 from "@/assets/modelSetting/video_type_1.png"; import video_type_2 from "@/assets/modelSetting/video_type_2.png"; import video_type_3 from "@/assets/modelSetting/video_type_3.png"; +import { + deleteWorkshopDevicesApi, + editWorkshopDevicesApi +} from "@/api/workshops"; +import { isSuccessApi } from "@/utils/forApi"; + +const props = defineProps({ + pointInfo: { + type: Object as Record<string, any> + } +}); const event = inject("event"); const update = getCurrentInstance(); const { mixinState, canvasEditor } = useSelect(); /**业务属性 */ const formData = ref({ - iconType: 1 + icon: 1 }); const rules = { - iconType: [{ required: true, message: "请选择图标类型", trigger: "change" }] + icon: [{ required: true, message: "请选择图标类型", trigger: "change" }] }; const iconOptions = ref([ { - value: 1, + value: "1", label: "图标1", type: "1", url: video_type_1 }, { - value: 2, + value: "2", label: "图标2", type: "2", url: video_type_2 }, { - value: 3, + value: "3", label: "图标3", type: "3", url: video_type_3 @@ -181,10 +192,43 @@ const getObjectAttr = e => { const animateObject = activeObject.get("animation"); animationAttr.type = animateObject.type; } + // 设备相关属性 + if (activeObject.get("deviceInfo")) { + formData.value = activeObject.get("deviceInfo"); + } } }; +// 删除当前集合 +async function deleteDeviceObject(deleteObject) { + const currDeviceInfo = deleteObject[0].get("deviceInfo"); + console.log(currDeviceInfo, "deleteDeviceObject", deleteObject); + const resp = await deleteWorkshopDevicesApi({ + id: currDeviceInfo.id + }); + if (isSuccessApi(resp)) { + deleteObject.deleteCallback(); + } +} -const selectCancel = () => { +// 编辑当前集合 +async function editDeviceObject(callback) { + const activeObject = canvasEditor.canvas.getActiveObject(); + const currDeviceInfo = activeObject.get("deviceInfo"); + console.log(activeObject, "editDeviceObject_activeObject", currDeviceInfo); + const resp = await editWorkshopDevicesApi({ + id: currDeviceInfo.id, + device_id: currDeviceInfo.device_id, + workshop_id: currDeviceInfo.workshop_id, + x_ordinate: activeObject.get("left"), + y_ordinate: activeObject.get("top"), + icon: formData.value.icon + }); + if (isSuccessApi(resp)) { + console.log("编辑完成"); + callback(resp); + } +} +const selectCancel = e => { baseAttr.fill = ""; update?.proxy?.$forceUpdate(); }; @@ -193,10 +237,15 @@ const init = () => { // 获取字体数据 event.on("selectCancel", selectCancel); event.on("selectOne", getObjectAttr); + canvasEditor.canvas.on("object:deleteObject", deleteDeviceObject); + canvasEditor.canvas.on("mouse:up", () => { + editDeviceObject(); + }); canvasEditor.canvas.on("object:modified", getObjectAttr); // 监听 object:moving 事件以限制移动范围 canvasEditor.canvas.on("object:moving", e => { const activeObject = e.target; + // console.log(activeObject, "activeObject_moving"); if (activeObject) { constrainObjectWithinCanvas(activeObject); canvasEditor.canvas.renderAll(); @@ -238,7 +287,7 @@ const changeCommon = (key, value) => { canvasEditor.canvas.renderAll(); return; } - if (key === "iconType") { + if (key === "icon") { // 在 group 对象中查找唯一的 fabric.Image 对象 const imageObject = activeObject._objects[1]; @@ -250,16 +299,18 @@ const changeCommon = (key, value) => { if (targetIcon) { // 修改图片路径 - imageObject.setSrc( - targetIcon.url, - () => { - // 刷新画布 - console.log("Image loaded successfully activeObject_iconType"); - activeObject.addWithUpdate(); // 更新对象的坐标和边界框 - canvasEditor.canvas.renderAll(); - }, - { crossOrigin: "anonymous" } - ); + editDeviceObject(() => { + imageObject.setSrc( + targetIcon.url, + () => { + // 刷新画布 + console.log("Image loaded successfully activeObject_iconType"); + activeObject.addWithUpdate(); // 更新对象的坐标和边界框 + canvasEditor.canvas.renderAll(); + }, + { crossOrigin: "anonymous" } + ); + }); // 加载新的图片并替换旧的图片对象 // fabric.Image.fromURL( @@ -302,12 +353,14 @@ onMounted(init); onBeforeUnmount(() => { event.off("selectCancel", selectCancel); event.off("selectOne", getObjectAttr); + canvasEditor.canvas.off("object:deleteObject"); + canvasEditor.canvas.off("mouse:up"); canvasEditor.canvas.off("object:modified", getObjectAttr); canvasEditor.canvas.off("object:moving"); }); </script> <template> - <div class="box" v-if="mixinState.mSelectMode === 'one'"> + <div class="deviceAtrr_toolbar" v-if="mixinState.mSelectMode === 'one'"> <!-- 字体属性 --> <div v-show="textTypeConf.includes(mixinState.mSelectOneType)"> <!-- 字体属性 --> @@ -334,20 +387,21 @@ onBeforeUnmount(() => { class="demo-form-inline" label-position="top" > - <el-form-item label="选择图标" class="w-full" prop="iconType"> + <el-form-item label="选择图标" class="w-full" prop="icon"> <el-radio-group - v-model="formData.iconType" - @change="changeCommon('iconType', formData.iconType)" + v-model="formData.icon" + @change="changeCommon('icon', formData.icon)" > <el-radio v-for="option in iconOptions" :key="option.value" :label="option.value" > - <i> - <!-- 图标 --> - </i> - {{ option.label }} + <el-image + :src="option?.url || ''" + :fit="'contain'" + class="w-[24px]" + /> </el-radio> </el-radio-group> </el-form-item> diff --git a/src/views/deviceSetting/components/deviceSelect.vue b/src/views/deviceSetting/components/deviceSelect.vue index 380dcb2..15c3150 100644 --- a/src/views/deviceSetting/components/deviceSelect.vue +++ b/src/views/deviceSetting/components/deviceSelect.vue @@ -1,40 +1,10 @@ <!-- * @Description: 设备选择 --> - -<template> - <div v-if="!mixinState.mSelectMode"> - <div class="px-[12px] deviceSelect_toolbar"> - <div> - <h4 class="hf-1 py-[12px]">设备列表</h4> - <p class="pf-2"> - 可直接点击拖拽设备名称至图中目标位置,鼠标悬停可查看设备详情 - </p> - <ul class="mt-[8px] deviceSelect_list"> - <li - class="flex items-center px-[16px] mb-[12px]" - :class="detailInfo?.id === info.id ? 'active' : ''" - v-for="(info, i) in props.deviceList" - :key="`${i}-logo1-button`" - :draggable="true" - @click="addItem(info)" - @dragend="event => dragItem(event, info)" - > - <span> - {{ info.name }} - </span> - </li> - </ul> - </div> - </div> - </div> -</template> - <script setup name="CanvasSize" lang="ts"> // import { Modal } from "view-ui-plus"; import useSelect from "@/hooks/select"; // import { cloneDeep } from "lodash-es"; -import { v4 as uuid } from "uuid"; // import { useI18n } from "vue-i18n"; import { useDeviceObject } from "../hooks/useDeviceObject"; @@ -48,6 +18,8 @@ const props = defineProps({ } }); +const emit = defineEmits(["addDevice"]); + const { fabric, mixinState, canvasEditor } = useSelect(); const { initDeviceGroupObjects } = useDeviceObject(); // const { t } = useI18n(); @@ -104,6 +76,7 @@ canvasEditor.getMaterialType("svg").then((list: materialTypeI[]) => { function fetchDetail(record) { detailInfo.value = record; console.log(detailInfo.value, "fetchDetail"); + emit("addDevice", record); } /** @@ -126,7 +99,6 @@ const dragItem = (event, deviceItem) => { ...defaultPosition, shadow: "", fontFamily: "arial", - id: uuid(), name: "svg元素", ...initDeviceGroupObjects(deviceItem) } @@ -143,7 +115,8 @@ const dragItem = (event, deviceItem) => { // var canvas = new fabric.Canvas('canvas-id'); // canvas.add(group); canvasEditor.dragAddItem(event, item); - fetchDetail(deviceItem); + console.log(event, item, "dragItem"); + // fetchDetail(deviceItem); // 更新Canvas以确保更改生效 // canvas.renderAll(); } @@ -155,16 +128,15 @@ const addItem = deviceItem => { if (isValidAdd(deviceItem)) { return; } + console.log(deviceItem, "addItem_deviceItem"); fabric.util.enlivenObjects( [ { ...defaultPosition, - id: uuid(), // name: "svg元素", ...initDeviceGroupObjects(deviceItem) } ], - function (objects) { // objects 包含从JSON还原的对象,这里我们期望是一个Group对象 const item = objects[0]; @@ -189,13 +161,43 @@ const addItem = deviceItem => { // const item = fabric.util.groupSVGElements(objects, { // ...options, // ...defaultPosition, - // id: uuid(), // name: "svg元素" // }); // }); }; +// 渲染设备到点位图上 +function renderDeviceToCanvas(record) { + const startArr = record; + + const finalArr = []; + startArr.map(deviceItem => { + const fullDeviceItem = { + ...defaultPosition, + ...deviceItem, + left: Number(deviceItem.x_ordinate), + top: Number(deviceItem.y_ordinate), + name: deviceItem.device_name + }; + finalArr.push({ + ...fullDeviceItem, + ...initDeviceGroupObjects(fullDeviceItem) + }); + }); + fabric.util.enlivenObjects([...finalArr], function (enlivenedObjects) { + enlivenedObjects.forEach(groupObject => { + if (groupObject.type === "group") { + // 如果对象是 group 类型,将其添加到 canvas 中 + canvasEditor.canvas.add(groupObject); + } + }); + // objects 包含从JSON还原的对象,这里我们期望是一个Group对象 + const item = enlivenedObjects[0]; + canvasEditor.canvas.setActiveObject(item); + canvasEditor.canvas.requestRenderAll(); + }); +} // const DefaultSize = { // width: 1200, // height: 900 @@ -234,17 +236,16 @@ const addItem = deviceItem => { // height: 1200 // } // ]); -const DefaultSize = { - width: 947, - height: 642 -}; +// const DefaultSize = { +// width: 977, +// height: 670 +// }; onMounted(() => { - canvasEditor.setSize(DefaultSize.width, DefaultSize.height); - canvasEditor.on("sizeChange", (width, height) => { - width.value = width; - height.value = height; - }); - + // canvasEditor.setSize(DefaultSize.width, DefaultSize.height); + // canvasEditor.on("sizeChange", (width, height) => { + // width.value = width; + // height.value = height; + // }); // canvas.editor.editorWorkspace.setSize(width.value, height.value); // canvas.editor.editorWorkspace = new EditorWorkspace(canvas.c, { // width: width.value, @@ -272,17 +273,45 @@ onMounted(() => { // handleClose(); // }; -watch( - () => props.deviceList, - () => { - console.log(props.deviceList, "watch_deviceList"); - }, - { - immediate: true, - deep: true - } -); +// watch( +// () => props.deviceList, +// () => { +// console.log(props.deviceList, "watch_deviceList"); +// }, +// { +// immediate: true, +// deep: true +// } +// ); +defineExpose({ renderDeviceToCanvas }); </script> +<template> + <div v-if="!mixinState.mSelectMode"> + <div class="px-[12px] deviceSelect_toolbar"> + <div> + <h4 class="hf-1 py-[12px]">设备列表</h4> + <p class="pf-2"> + 可直接点击拖拽设备名称至图中目标位置,鼠标悬停可查看设备详情 + </p> + <ul class="mt-[8px] deviceSelect_list"> + <li + class="flex items-center px-[16px] mb-[12px]" + :class="detailInfo?.id === info.id ? 'active' : ''" + v-for="(info, i) in props.deviceList" + :key="`${i}-logo1-button`" + :draggable="true" + @click="addItem(info)" + @dragend="event => dragItem(event, info)" + > + <span> + {{ info.name }} + </span> + </li> + </ul> + </div> + </div> + </div> +</template> <style scoped lang="scss"> .search-box { @@ -312,4 +341,3 @@ watch( margin-bottom: 10px; } </style> -../hooks/useWatchModels../hooks/useDeviceObject diff --git a/src/views/deviceSetting/hooks/useDeviceObject.ts b/src/views/deviceSetting/hooks/useDeviceObject.ts index 2ffe938..945b9e6 100644 --- a/src/views/deviceSetting/hooks/useDeviceObject.ts +++ b/src/views/deviceSetting/hooks/useDeviceObject.ts @@ -4,31 +4,32 @@ */ // https://t7.baidu.com/it/u=2757924858,1404466263&fm=193 import video_type_1 from "@/assets/modelSetting/video_type_1.png"; +import video_type_2 from "@/assets/modelSetting/video_type_2.png"; +import video_type_3 from "@/assets/modelSetting/video_type_3.png"; +import { v4 as uuid } from "uuid"; export const useDeviceObject = () => { - const initDeviceGroupObjects: Record<string, any> = (record: { - id: string; - value: string; - }) => { + const initDeviceGroupObjects: Record<string, any> = record => { console.log(record, "initDeviceGroupObjects"); // const { value } = record; - // let watchIconObject = watchIcon2; - // switch (value) { - // case "watchError": - // watchIconObject = watchIcon1; - // break; - // case "watchOnline": - // watchIconObject = watchIcon2; - // break; - // case "watchOutline": - // watchIconObject = watchIcon3; - // break; - // case "watchWarn": - // default: - // watchIconObject = watchIcon4; - // break; - // } + let iconObjectSrc = video_type_1; + switch (record?.icon) { + case "3": + iconObjectSrc = video_type_3; + break; + case "2": + iconObjectSrc = video_type_2; + break; + case "1": + default: + iconObjectSrc = video_type_1; + break; + } return { + id: uuid(), + deviceInfo: record, // 设备信息 + left: record?.x_ordinate ? Number(record?.x_ordinate) : 0, + top: record?.y_ordinate ? Number(record?.y_ordinate) : 0, selectable: true, hasControls: true, lockUniScaling: true, // 当设置为true,Object将无法被锁定比例进行缩放。默认值为false。 @@ -39,8 +40,7 @@ export const useDeviceObject = () => { version: "5.3.0", originX: "left", originY: "top", - left: 87.4695, - top: 85.8002, + width: 113, height: 66, fill: "rgb(0,0,0)", @@ -66,7 +66,6 @@ export const useDeviceObject = () => { globalCompositeOperation: "source-over", skewX: 0, skewY: 0, - id: "520579bf-b8b3-451b-b3aa-5b8a9d6cd1a8", objects: [ { type: "image", @@ -144,7 +143,7 @@ export const useDeviceObject = () => { cropY: 0, selectable: false, hasControls: false, - src: video_type_1, + src: iconObjectSrc, crossOrigin: null, filters: [] }, diff --git a/src/views/deviceSetting/hooks/usePointObject.ts b/src/views/deviceSetting/hooks/usePointObject.ts index 23352de..30b610b 100644 --- a/src/views/deviceSetting/hooks/usePointObject.ts +++ b/src/views/deviceSetting/hooks/usePointObject.ts @@ -1,5 +1,14 @@ +/* + * @Author: donghao donghao@supervision.ltd + * @Date: 2024-08-14 11:26:47 + * @LastEditors: donghao donghao@supervision.ltd + * @LastEditTime: 2024-08-15 13:25:48 + * @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\hooks\usePointObject.ts + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ export const usePointObject = () => { - function getPointObject(record) { + function getPointObject(record, objectOptions) { + const { width, height } = objectOptions; const { picture } = record; // TODO: 获取点位对象 return JSON.stringify({ @@ -12,9 +21,9 @@ export const usePointObject = () => { originY: "top", left: 0, top: 0, - width: 947, - height: 610, - fill: "rgba(255,35,255,1)", + width: width, + height: height, + fill: "rgba(21, 77, 221, 0.1)", stroke: null, strokeWidth: 0, strokeDashArray: null, @@ -48,8 +57,10 @@ export const usePointObject = () => { version: "5.3.0", originX: "left", originY: "top", - width: 947, - height: 610, + left: 0, + top: 0, + width: width, + height: height, fill: "rgb(0,0,0)", stroke: null, strokeWidth: 0, diff --git a/src/views/deviceSetting/index.scss b/src/views/deviceSetting/index.scss index a6f29a0..189a67f 100644 --- a/src/views/deviceSetting/index.scss +++ b/src/views/deviceSetting/index.scss @@ -60,12 +60,12 @@ padding-top: 40px; .bg_preview { height: 412px; - background-color: red; + border: 1px dashed #ddd; } } .point_detail_wrap { .deviceOfPoint_wrap { - background-color: goldenrod; + border: 1px dashed #ddd; height: calc(100vh - 290px); } .footer_btns { @@ -78,8 +78,8 @@ .right-bar { margin-left: 16px; width: 241px; - height: 100%; - overflow-y: auto; + height: calc(100vh - 300px); + overflow-y: scroll; } #workspace { flex: 1; @@ -100,3 +100,10 @@ } } } +/* 设备属性栏位 */ +.deviceAtrr_toolbar { + .el-radio__label { + display: flex; + align-items: center; + } +} diff --git a/src/views/deviceSetting/index.vue b/src/views/deviceSetting/index.vue index 5eacb40..aa4ee13 100644 --- a/src/views/deviceSetting/index.vue +++ b/src/views/deviceSetting/index.vue @@ -2,7 +2,7 @@ * @Author: donghao donghao@supervision.ltd * @Date: 2024-08-02 10:52:32 * @LastEditors: donghao donghao@supervision.ltd - * @LastEditTime: 2024-08-14 17:10:19 + * @LastEditTime: 2024-08-15 17:11:29 * @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\index.vue * @Description: 设备点位管理设置 @ 交互说明 @@ -19,7 +19,13 @@ import DeviceSettingAdd from "./components/add.vue"; import DeviceSelect from "./components/deviceSelect.vue"; import { IsDelete } from "@/components/Action"; import { usePointObject } from "./hooks/usePointObject"; -import { getWorkshopsApi, deleteWorkshopsApi } from "@/api/workshops"; + +import { + getWorkshopsApi, + deleteWorkshopsApi, + addWorkshopDevicesApi, + getWorkshopDevicesApi +} from "@/api/workshops"; import { getLinkDevicesApi } from "@/api/device"; import { isSuccessApi } from "@/utils/forApi"; @@ -68,30 +74,37 @@ const state = reactive({ * @设备点位 */ const { getPointObject } = usePointObject(); + const pointList = ref([]); const deviceSettingAddRef = ref(""); +const deviceSelectRef = ref(""); const activePointId = ref(""); const activePoint = ref({ name: "" }); -const deviceList = ref([]); +const deviceList = ref([]); // 所有设备列表 +const currDeviceList = ref([]); // 当前点位下设备列表 const isDeleteVisible = ref(false); -// 插入文件 -const initFile = () => { - // console.log("canvasEditor"); - canvasEditor.insertSvgFile(getPointObject(toRaw(activePoint.value))); +// 插入文件绘制图 +const refreshCanvas = () => { + const currWorkSpace = document.getElementById("workspace"); + canvasEditor.insertSvgFile( + getPointObject(toRaw(activePoint.value), { + width: currWorkSpace.clientWidth, + height: currWorkSpace.clientHeight + }) + ); + fetchDeviceByPoint(); + + console.log("插入文件"); }; // 初始化fabric&编辑器 const initFabric = () => { const canvas = new fabric.Canvas("canvas", { - fireRightClick: true, // 启用右键,button的数字为3 + fireRightClick: false, // 启用右键,button的数字为3 stopContextMenu: true, // 禁止默认右键菜单 controlsAboveOverlay: true // 超出clipPath后仍然展示控制条 }); - canvas.loadFromJSON( - getPointObject(toRaw(activePoint.value)), - canvas.renderAll.bind(canvas) - ); // 初始化编辑器 canvasEditor.init(canvas); canvasEditor.use(DringPlugin); @@ -116,7 +129,7 @@ const initFabric = () => { event.init(canvas); state.showFabric = true; nextTick(() => { - initFile(); + refreshCanvas(); }); }; @@ -157,10 +170,12 @@ async function fetchPointList() { } // 获取设备列表 async function fetchDeviceList() { - const { data } = await getLinkDevicesApi(); - // TODO 未使用判空和loading效果 - deviceList.value = data; - console.log(deviceList.value, "fetchDeviceList_data", data); + const { data, ...resp } = await getLinkDevicesApi(); + if (isSuccessApi(resp)) { + // TODO 未使用loading效果 + deviceList.value = data; + console.log(deviceList.value, "fetchDeviceList_data", data); + } } // 切换点位 function tabPoint(tab) { @@ -168,7 +183,7 @@ function tabPoint(tab) { activePoint.value = selectedTab; console.log(tab.props.name, "tabPoint", activePoint.value); nextTick(() => { - initFile(); + refreshCanvas(); }); } @@ -185,7 +200,7 @@ function afterFinishAdd(record) { activePoint.value = record; console.log("afterFinishAdd", record); nextTick(() => { - initFile(); + refreshCanvas(); }); } @@ -193,11 +208,11 @@ function afterFinishAdd(record) { function editPoint() { deviceSettingAddRef.value?.openDialog(); } -// 删除点位 +// 开始删除点位 function beforeDeletePoint() { isDeleteVisible.value = true; } - +// 完成删除点位 function afterFinishDelete() { // 查找目标对象在 pointList 中的索引 const currPointList = toRaw(pointList.value); @@ -220,10 +235,10 @@ function afterFinishDelete() { activePointId.value = currPointList[0].id; } nextTick(() => { - initFile(); + refreshCanvas(); }); } - +// 删除点位 async function deletePoint() { const resp = await deleteWorkshopsApi({ id: activePointId.value @@ -235,6 +250,53 @@ async function deletePoint() { // 执行删除操作 } +// 获取点位下的已绑定设备 +async function fetchDeviceByPoint() { + const resp = await getWorkshopDevicesApi({ + workshop_id: activePointId.value, + is_binding: true + }); + if (isSuccessApi(resp)) { + currDeviceList.value = resp.data.results; + } + console.log("fetchDeviceByPoint_resp", resp); + deviceSelectRef.value?.renderDeviceToCanvas(resp.data.results); +} + +// 新增设备 +async function addDevice(record) { + const resp = await addWorkshopDevicesApi({ + workshop_id: activePointId.value, + device_id: record.id, + x_ordinate: record?.x_ordinate || 0, + y_ordinate: record?.y_ordinate || 0, + icon: record?.type || 1 + }); + if (isSuccessApi(resp)) { + // isAddDeviceVisible.value = false; + // afterFinishAddDevice(); + } +} + +// // +// async function deleteDevice(record) { +// const resp = await deleteWorkshopDeviceApi({ +// id: record.id +// }); +// if (isSuccessApi(resp)) { +// isDeleteDeviceVisible.value = false; +// afterFinishDeleteDevice(); +// } +// } + +// // +// async function updateDevice(record) { +// const resp = await updateWorkshopDeviceApi({ +// id: record.id, + +// }); +// } + // 有点位了再初始化 watch( () => pointList.value, @@ -254,7 +316,7 @@ watch( // console.log("activePoint", activePoint); // if (activePoint.value?.id) { // nextTick(() => { -// initFile(); +// refreshCanvas(); // }); // } // } @@ -311,20 +373,20 @@ provide("canvasEditor", canvasEditor); <div class="flex w-full h-full"> <!-- 左侧画布区域 --> <div id="workspace" class="h-full deviceOfPoint_wrap"> - <div class="canvas-box"> - <!-- <div class="inside-shadow"></div> --> - <canvas - id="canvas" - :class="state.ruler ? 'design-stage-grid' : ''" - /> - <!-- <dragMode v-if="state.showFabric"></dragMode> + <!-- <div class="inside-shadow"></div> --> + <canvas id="canvas" /> + <!-- <dragMode v-if="state.showFabric"></dragMode> <zoom></zoom> --> - <!-- <mouseMenu></mouseMenu> --> - </div> + <!-- <mouseMenu></mouseMenu> --> </div> <!-- 右侧属性区域--> <div class="right-bar" v-if="state.showFabric"> - <DeviceSelect :deviceList="deviceList" /> + <DeviceSelect + ref="deviceSelectRef" + :deviceList="deviceList" + @addDevice="addDevice" + :pointInfo="activePoint" + /> <DeviceAttr /> </div> </div> @@ -339,6 +401,7 @@ provide("canvasEditor", canvasEditor); v-if="pointList.length" >删除位置</el-button > + <!-- //TODO 完善删除交互效果 --> <IsDelete v-model="isDeleteVisible" @update:visible="val => (isDeleteVisible = val)"