feat: 设备布点补充编辑前预览功能

develop
donghao 10 months ago
parent 0900103bf6
commit 4c626c7136

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-01-12 14:35:28
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-03-25 11:16:58
* @LastEditTime: 2024-08-26 14:40:41
* @FilePath: \General-AI-Platform-Web-Client\index.html
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
@ -21,7 +21,7 @@
<!-- update 2024-08-14 11:05 -->
<link
rel="stylesheet"
href="//at.alicdn.com/t/c/font_4412653_5ql8iuyd77a.css"
href="//at.alicdn.com/t/c/font_4412653_jsay2r4m3wm.css"
/>
<script src="https://threejs.org/build/three.js"></script>

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-02 10:40:49
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-15 16:14:24
* @LastEditTime: 2024-08-28 16:58:13
* @FilePath: \General-AI-Platform-Web-Client\src\api\workshops.ts
* @Description:
*/
@ -83,9 +83,9 @@ export const editWorkshopDevicesApi = (data?: object) => {
});
};
/** 删除布点设备 status: 1 */
export const deleteWorkshopDevicesApi = (data?: object) => {
return http.request<Result>("post", baseUrlApi("workshop_devices/"), {
data: { ...data, status: 1 }
/** 删除布点设备 */
export const deleteWorkshopDevicesListApi = (data?: Array) => {
return http.request<Result>("delete", baseUrlApi("workshop_devices/"), {
data: { ids: data }
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -75,7 +75,7 @@ export default defineComponent({
<span className="hf-1 pl-[12px]">{props.title}</span>
</div>
<div className="pl-[36px] pt-[14px]">
<span className="pf-1">{props.message}</span>
<span className="pf-1" v-html={props.message}></span>
</div>
</div>
</ElDialog>

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-29 09:31:35
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-22 09:46:30
* @LastEditTime: 2024-08-26 11:50:25
* @FilePath: \vue-fabric-editor\src\core\ServersPlugin.ts
* @Description:
*/

@ -211,3 +211,16 @@
.el-popover.el-popper {
padding: 16px !important;
}
/* dialog 弹框 */
.el-dialog {
background-color: transparent !important;
background-image: url("@/assets/dialogBg.png") !important;
background-size: 100% 100% !important;
background-repeat: none-repetet !important;
}
/* button */
.el-button {
font-weight: 400 !important;
}

@ -17,6 +17,17 @@
padding: 16px 24px 0;
}
.el-dialog__body {
padding: 24px;
padding: 24px 24px 0;
}
.el-icon--upload {
font-size: 40px;
line-height: 40px;
}
.el-upload-dragger {
padding: 20px;
}
.el-upload__text {
line-height: 18px;
color: #333;
}
}

@ -2,14 +2,12 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-07 14:47:44
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-21 13:44:44
* @LastEditTime: 2024-08-26 13:59:21
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\components\add.vue
* @Description: 新建位置
-->
<script setup lang="ts">
// import type { FormInstance } from "element-plus";
import historyAlarm from "@/assets/history_alarm.png";
import { UploadFilled } from "@element-plus/icons-vue";
import { message } from "@/utils/message";
import { addWorkshopsApi } from "@/api/workshops";
import { isSuccessApi } from "@/utils/forApi";
@ -117,7 +115,7 @@ defineExpose({
>
<template #header="{ titleId, titleClass }">
<div class="flex items-center my-header">
<img :src="historyAlarm" class="w-[26px] h-[26px]" />
<img src="@/assets/addIcon.png" class="w-[26px] h-[26px]" />
<h4 :id="titleId" class="pl-[10px]" :class="titleClass">
新建布点位置
</h4>
@ -154,9 +152,11 @@ defineExpose({
>
<div>
<div v-if="!imagePreview">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<el-icon class="el-icon--upload text-[40px]">
<img src="@/assets/uploadImageIcon.png" />
</el-icon>
<div class="el-upload__text">
拖拽图片到这里或点此添加 <em>点此添加</em>
拖拽图片到这里<em>点此添加</em>
</div>
</div>
<el-image

@ -6,7 +6,7 @@ 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
deleteWorkshopDevicesListApi
// editWorkshopDevicesApi
} from "@/api/workshops";
import { isSuccessApi } from "@/utils/forApi";
@ -175,24 +175,23 @@ const getObjectAttr = e => {
async function deleteDeviceObject(deleteObject) {
const currDeviceInfo = deleteObject[0].get("deviceInfo");
console.log(currDeviceInfo, "deleteDeviceObject", deleteObject);
const resp = await deleteWorkshopDevicesApi({
id: currDeviceInfo.id
});
const resp = await deleteWorkshopDevicesListApi([currDeviceInfo.id]);
if (isSuccessApi(resp)) {
deleteObject.deleteCallback();
emit("afterDelete", currDeviceInfo);
emit("afterDelete", JSON.stringify([currDeviceInfo.id]));
}
}
function startEditDevice(callback) {
const { startLeft, startTop } = fetchViewsBoundaries(canvasEditor.canvas);
const activeObject = canvasEditor.canvas.getActiveObject();
const currDeviceInfo = activeObject.get("deviceInfo");
const editParams = {
id: currDeviceInfo.id,
device_id: currDeviceInfo.device_id,
workshop_id: props.pointInfo?.id,
x_ordinate: activeObject.get("left"),
y_ordinate: activeObject.get("top"),
x_ordinate: activeObject.get("left") - startLeft,
y_ordinate: activeObject.get("top") - startTop,
icon: formData.value?.icon
};
emit("editDevice", { editParams, callback });
@ -212,7 +211,7 @@ const init = () => {
//
activeObject &&
activeObject.get("deviceInfo") &&
isMoveDevice(activeObject) &&
isMoveDevice(activeObject, canvasEditor.canvas) &&
startEditDevice();
});
canvasEditor.canvas.on("object:modified", getObjectAttr);

@ -7,7 +7,6 @@ import useSelect from "@/hooks/select";
// import { useI18n } from "vue-i18n";
import { useDeviceObject } from "../hooks/useDeviceObject";
import { IsAction } from "@/components/Action";
import { InfoFilled } from "@element-plus/icons-vue";
const props = defineProps({
deviceList: {
@ -26,7 +25,8 @@ const { fabric, mixinState, canvasEditor } = useSelect();
const {
initDeviceGroupObjects,
isInViewBoundaries,
getDragDeviceObjectOrdinate
getDragDeviceObjectOrdinate,
fetchViewsBoundaries
} = useDeviceObject();
// const { t } = useI18n();
@ -64,7 +64,7 @@ const isUpdateBindVisible = ref<boolean>(false);
const bindDeviceData = ref<Record<string, any>>({});
const updateMessage = computed(() => {
return `${currDetailInfo.value?.name}已绑定至“${currDetailInfo.value?.workshop_name},确定解除绑定并重新配置吗?`;
return `<span class="font-bold">${currDetailInfo.value?.name}</span>已绑定至<span class="font-bold">${currDetailInfo.value?.workshop_name}</span>,确定解除绑定并重新配置吗?`;
});
//
canvasEditor.getMaterialType("svg").then((list: materialTypeI[]) => {
@ -75,6 +75,7 @@ canvasEditor.getMaterialType("svg").then((list: materialTypeI[]) => {
* 处理添加设备&重复添加设备同点位不同点位
*/
function deviceSelected(callback, options) {
const { startLeft, startTop } = fetchViewsBoundaries(canvasEditor.canvas);
const { targetDeviceItem } = options;
console.log(targetDeviceItem, "deviceSelected", props.currDeviceList);
currDetailInfo.value = targetDeviceItem;
@ -110,8 +111,8 @@ function deviceSelected(callback, options) {
canvasEditor.canvas.getObjects().forEach(v => {
if (v?.deviceInfo?.device_id === targetDeviceItem.id) {
v.set({
left: targetDeviceItem.x_ordinate,
top: targetDeviceItem.y_ordinate
left: targetDeviceItem.x_ordinate + startLeft,
top: targetDeviceItem.y_ordinate + startTop
});
canvasEditor.canvas.renderAll();
}
@ -131,7 +132,7 @@ function updateConfirmBind() {
emit("addDevice", {
record: targetDeviceItem,
callback: () => {
canvasEditor.dragAddItem(event, item); //
// canvasEditor.dragAddItem(event, item); //
bindDeviceData.value = {}; //
isUpdateBindVisible.value = false;
}
@ -175,11 +176,11 @@ const dragItem = (event, deviceItem) => {
deviceSelected(
resData => {
//
item.set({
name: resData?.device_name,
deviceInfo: resData
}); //
canvasEditor.dragAddItem(event, item);
// item.set({
// name: resData?.device_name,
// deviceInfo: resData
// }); //
// canvasEditor.dragAddItem(event, item);
},
{
targetDeviceItem,
@ -218,14 +219,16 @@ const dragItem = (event, deviceItem) => {
//
function renderDeviceToCanvas(record) {
const { startLeft, startTop } = fetchViewsBoundaries(canvasEditor.canvas);
console.log(startLeft, "renderDeviceToCanvas");
const startArr = record;
const finalArr = [];
startArr.map(deviceItem => {
const fullDeviceItem = {
...defaultPosition,
...deviceItem,
left: Number(deviceItem.x_ordinate),
top: Number(deviceItem.y_ordinate),
left: Number(deviceItem.x_ordinate) + startLeft,
top: Number(deviceItem.y_ordinate) + startTop,
name: deviceItem.device_name
};
finalArr.push({
@ -247,10 +250,7 @@ function renderDeviceToCanvas(record) {
watch(
() => props.deviceList,
() => {
allDeviceList.value = toRaw(props.deviceList).filter(item => {
// item.workshop_id = item?.wd_id;
return item;
});
allDeviceList.value = toRaw(props.deviceList);
console.log(allDeviceList.value, "allDeviceList", props.deviceList);
},
// {
@ -302,15 +302,17 @@ defineExpose({ renderDeviceToCanvas });
width: 14px;
height: 14px;
color: #154ddd;
margin-right: 2px;
margin-right: 4px;
"
><InfoFilled
/></el-icon>
>
<i class="iconfont icon-xiangqing" />
</el-icon>
<span>详情</span>
</div>
</template>
<div class="device_info_box">
<div class="pf-1 pb-[8px]">设备信息</div>
<div class="pf-1 pb-[8px] font-bold text-[16px]">设备信息</div>
<ul class="text-[16px] text-web-font1 device_info_items">
<li>
<span>设备名称</span>

@ -2,23 +2,30 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-16 14:28:49
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-21 13:50:47
* @LastEditTime: 2024-08-28 17:36:11
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\components\edit.vue
* @Description: 新建位置
-->
<script setup lang="ts">
// import type { FormInstance } from "element-plus";
import historyAlarm from "@/assets/history_alarm.png";
import { UploadFilled } from "@element-plus/icons-vue";
import { message } from "@/utils/message";
import { editWorkshopsApi } from "@/api/workshops";
import {
editWorkshopsApi,
deleteWorkshopDevicesListApi
} from "@/api/workshops";
import { isSuccessApi } from "@/utils/forApi";
// import useSelect from "@/hooks/select";
import previewCurrent from "./previewCurrent.vue";
defineOptions({
name: "DeviceSettingEdit"
});
const emit = defineEmits(["finishEdit"]);
const props = defineProps({
currDeviceList: {
type: Array as Record<string, any>[]
}
});
const formData = ref({
id: "",
name: "",
@ -26,6 +33,7 @@ const formData = ref({
});
const formRef = ref(null);
const uploadRef = ref(null);
const previewCurrentRef = ref(null);
const imagePreview = ref<string | null>(null); // URL
const dialogVisible = ref<boolean>(false);
const isChangePic = ref<boolean>(false);
@ -40,8 +48,11 @@ const openDialog = record => {
name: record.name,
picture: record.picture
};
imagePreview.value = record.picture;
imagePreview.value = record.picture; // 使
dialogVisible.value = true;
nextTick(() => {
previewCurrentRef.value.renderPreview();
});
};
const handleFileChange = (file: any) => {
@ -49,6 +60,9 @@ const handleFileChange = (file: any) => {
const reader = new FileReader();
reader.onload = e => {
imagePreview.value = e.target?.result as string;
nextTick(() => {
previewCurrentRef.value.refreshPic();
});
};
reader.readAsDataURL(file.raw);
console.log(file, "handleFileChange", fileList.value);
@ -80,17 +94,24 @@ const beforeUpload = (file: File) => {
return isJPG && isLt500K;
};
function resetFormData() {
imagePreview.value = null;
isChangePic.value = false;
}
async function fetchEditPoint() {
const formParams = new FormData();
formParams.append("id", formData.value.id);
formParams.append("name", formData.value.name);
if (isChangePic.value) {
// 使
formParams.append("picture", formData.value.picture);
}
const resp = await editWorkshopsApi(formParams);
console.log(resp, "fetchAddPoint_resp");
if (isSuccessApi(resp)) {
message(resp.msg || "编辑成功", { type: "success" });
resetFormData();
emit("finishEdit", resp.data);
dialogVisible.value = false;
} else {
@ -98,10 +119,27 @@ async function fetchEditPoint() {
}
}
async function deleteNotInVisableList() {
console.log("isNotInVisableList", previewCurrentRef.value.isNotInVisableList);
const resp = await deleteWorkshopDevicesListApi(
toRaw(previewCurrentRef.value.isNotInVisableList)
);
console.log(resp, "fetchAddPoint_resp");
if (isSuccessApi(resp)) {
fetchEditPoint();
}
}
const submitForm = () => {
formRef.value.validate((valid: boolean) => {
if (valid) {
fetchEditPoint();
const currList = toRaw(previewCurrentRef.value.isNotInVisableList);
if (currList.length) {
//
deleteNotInVisableList();
} else {
fetchEditPoint();
}
} else {
message("验证失败", { type: "error" });
return false;
@ -129,7 +167,7 @@ defineExpose({
>
<template #header="{ titleId, titleClass }">
<div class="flex items-center my-header">
<img :src="historyAlarm" class="w-[26px] h-[26px]" />
<img src="@/assets/editIcon.png" class="w-[26px] h-[26px]" />
<h4 :id="titleId" class="pl-[10px]" :class="titleClass">
编辑布点位置
</h4>
@ -166,17 +204,27 @@ defineExpose({
>
<div>
<div v-if="!imagePreview">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<el-icon class="el-icon--upload text-[40px]">
<img src="@/assets/uploadImageIcon.png" />
</el-icon>
<div class="el-upload__text">
拖拽图片到这里或点此添加 <em>点此添加</em>
拖拽图片到这里<em>点此添加</em>
</div>
</div>
<el-image
<div v-else class="w-full h-[311px]">
<previewCurrent
:picture="imagePreview"
:currDeviceList="props.currDeviceList"
ref="previewCurrentRef"
/>
</div>
<!-- <el-image
v-if="imagePreview"
:src="imagePreview || ''"
:fit="'contain'"
class="w-full"
/>
/> -->
</div>
</el-upload>
</el-form-item>

@ -0,0 +1,202 @@
<!--
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-26 11:32:07
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-28 16:16:06
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\components\previewCurrent.vue
* @Description: 预览组件
-->
<script lang="ts" setup>
import { fabric } from "fabric";
import { useDeviceObject } from "../hooks/useDeviceObject";
import device_video_bg_gray from "@/assets/modelSetting/device_video_bg_gray.png";
import device_video_bg from "@/assets/modelSetting/device_video_bg.png";
const { initDeviceGroupObjects } = useDeviceObject();
const props = defineProps({
picture: {
type: String
},
currDeviceList: {
type: Array as Record<string, any>[]
}
});
const viewData = ref<{
width: number;
height: number;
}>({
width: 551, //
height: 311 //
});
const isNotInVisableList = ref([]);
const viewPicOptions = ref({
scale: 1
});
const canvasRef = ref<any>(null);
const cvs = ref<any>(null);
//
function getBoundaryPoints() {
const canvasObject = cvs.value;
const { backgroundImage } = canvasObject;
const startLeft =
(viewData.value.width - backgroundImage.width * backgroundImage.scaleX) / 2;
const startTop =
(viewData.value.height - backgroundImage.height * backgroundImage.scaleY) /
2;
const endLeft = startLeft + backgroundImage.width * backgroundImage.scaleX;
const endTop = startTop + backgroundImage.height * backgroundImage.scaleY;
return { startLeft, startTop, endLeft, endTop };
}
//
function refreshDevicePosition() {
// const { scale } = toRaw(viewPicOptions.value);
const canvasObject = cvs.value;
const { startLeft, startTop, endLeft, endTop } = getBoundaryPoints();
const notInVisableIds = [];
canvasObject.getObjects().forEach(deviceItem => {
const objLeft = deviceItem.left;
const objTop = deviceItem.top;
const targetBgImage = deviceItem.getObjects()[0];
const targetTextBox = deviceItem.getObjects()[2];
const targetDelIcon = deviceItem.getObjects()[3];
console.log(targetBgImage, "notInVisableIds", deviceItem);
let notInVisable = false; //
if (
objLeft < startLeft ||
objTop < startTop ||
objLeft + deviceItem.width * deviceItem.scaleX > endLeft ||
objTop + deviceItem.heigth * deviceItem.scaleY > endTop
) {
//
notInVisable = true;
notInVisableIds.push(Number(deviceItem?.deviceInfo?.id));
}
targetTextBox.set("fill", notInVisable ? "red" : "#333333"); //
targetBgImage.setSrc(
notInVisable ? device_video_bg_gray : device_video_bg,
() => {
console.log("Image loaded successfully activeObject_iconType");
deviceItem.addWithUpdate(); //
canvasObject.renderAll(); //
cvs.value = canvasObject;
},
{ crossOrigin: "anonymous" }
);
targetDelIcon.set("visible", notInVisable);
canvasObject.renderAll();
cvs.value = canvasObject;
});
isNotInVisableList.value = notInVisableIds;
}
//
function renderDeviceToCanvas() {
const { scale } = toRaw(viewPicOptions.value);
console.log("renderDeviceToCanvas", props.currDeviceList, scale);
const canvasObject = cvs.value;
const startArr = props.currDeviceList;
const finalArr = [];
const { startLeft, startTop } = getBoundaryPoints();
startArr.map(deviceItem => {
const fullDeviceItem = {
// left: 100,
// top: 100,
shadow: "",
fontFamily: "1-1",
...deviceItem,
left: Number(deviceItem.x_ordinate) * scale + startLeft,
top: Number(deviceItem.y_ordinate) * scale + startTop,
name: deviceItem.device_name
};
finalArr.push({
...fullDeviceItem,
...initDeviceGroupObjects(fullDeviceItem, {
selectable: false,
hasControls: false,
scaleX: scale,
scaleY: scale
})
});
});
fabric.util.enlivenObjects([...finalArr], function (enlivenedObjects) {
enlivenedObjects.forEach(groupObject => {
if (groupObject.type === "group") {
// group canvas
canvasObject.add(groupObject);
}
});
canvasObject.renderAll();
});
}
function refreshPic(loadDevice) {
const canvasObject = cvs.value;
//
fabric.Image.fromURL(props.picture, function (img) {
//
const canvasWidth = viewData.value.width;
const canvasHeight = viewData.value.height;
//
const imgWidth = img.width;
const imgHeight = img.height;
// 使
const scaleX = canvasWidth / imgWidth;
const scaleY = canvasHeight / imgHeight;
const scale = Math.min(scaleX, scaleY); //
//
img.scale(scale);
//
img.set({
originX: "center",
originY: "center",
left: canvasWidth / 2,
top: canvasHeight / 2
});
viewPicOptions.value = {
scale
};
//
canvasObject.setBackgroundImage(
img,
canvasObject.renderAll.bind(canvasObject)
);
cvs.value = canvasObject;
if (!loadDevice) {
refreshDevicePosition();
} else {
renderDeviceToCanvas();
}
});
// canvasObject.loadFromJSON(JSON.stringify(currJson), () => {
// canvasObject.renderAll();
// });
console.log(canvasObject);
}
function renderPreview() {
const currWorkSpace = document.getElementById("previewPic");
viewData.value = {
width: currWorkSpace.clientWidth,
height: currWorkSpace.clientHeight
};
const canvasObject = new fabric.Canvas(canvasRef.value);
cvs.value = canvasObject;
nextTick(() => {
refreshPic(true);
});
}
defineExpose({ renderPreview, refreshPic, isNotInVisableList });
</script>
<template>
<div class="w-full h-full" id="previewPic">
<canvas ref="canvasRef" :width="viewData.width" :height="viewData.height" />
</div>
</template>

@ -1,118 +0,0 @@
/*
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-12-13 14:29:17
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-07 11:31:52
* @FilePath: \vue-fabric-editor\src\hooks\useAddModels.ts
* @Description: ,`customMade`, koroFileHeader : https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
// import {watch00} from '@/assets/modelSettingJsons/watch01'
import watchError from "@/assets/modelSetting/watchError.svg";
import watchOnline from "@/assets/modelSetting/watchOnline.svg";
import watchOutline from "@/assets/modelSetting/watchOutline.svg";
import watchWarn from "@/assets/modelSetting/watchWarn.svg";
import watchErrorSelected from "@/assets/modelSetting/watchErrorSelected.svg";
import watchOnlineSelected from "@/assets/modelSetting/watchOnlineSelected.svg";
import watchOutlineSelected from "@/assets/modelSetting/watchOutlineSelected.svg";
import watchWarnSelected from "@/assets/modelSetting/watchWarnSelected.svg";
export interface materialItemI {
value: string;
name: string;
tempUrl: string;
src: string;
color?: string;
}
const customObjectJson = {
type: "group",
objects: [
{
type: "rect",
left: 100,
top: 100,
width: 100,
height: 100,
fill: "red"
},
{
type: "circle",
left: 200,
top: 100,
radius: 50,
fill: "blue"
},
{
type: "text",
left: 150,
top: 200,
text: "Hello",
fontSize: 24,
fill: "white"
}
]
};
export const useWatchModels = () => {
const locaWatchList: materialItemI[] = [
{
value: "watchError",
name: "摄像头1",
tempUrl: "",
groupObject: customObjectJson,
src: watchError,
color: "#E80D0D"
},
{
value: "watchOnline",
name: "摄像头",
tempUrl: "",
src: watchOnline,
color: "#52C41A"
},
{
value: "watchOutline",
name: "摄像头",
tempUrl: "",
src: watchOutline,
color: "#CCCCCC"
},
{
value: "watchWarn",
name: "摄像头",
tempUrl: "",
src: watchWarn,
color: "#FAAD14"
},
{
value: "watchErrorSelected",
name: "摄像头",
tempUrl: "",
src: watchErrorSelected,
color: "#E80D0D"
},
{
value: "watchOnlineSelected",
name: "摄像头",
tempUrl: "",
src: watchOnlineSelected,
color: "#52C41A"
},
{
value: "watchOutlineSelected",
name: "摄像头",
tempUrl: "",
src: watchOutlineSelected,
color: "#CCCCCC"
},
{
value: "watchWarnSelected",
name: "摄像头",
tempUrl: "",
src: watchWarnSelected,
color: "#FAAD14"
}
];
return {
locaWatchList
};
};

@ -6,23 +6,27 @@
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 device_video_bg from "@/assets/modelSetting/device_video_bg.png";
import device_video_bg_gray from "@/assets/modelSetting/device_video_bg_gray.png";
import notInVisableIcon from "@/assets/modelSetting/notInVisableIcon.png";
import { v4 as uuid } from "uuid";
const deviceInfoKey = "deviceInfo";
export const useDeviceObject = () => {
// 移动到画布上的设备对象的相对坐标
function getDragDeviceObjectOrdinate(event, canvasObj, deviceObj) {
const { left, top } = canvasObj
.getSelectionElement()
.getBoundingClientRect();
// 移动到画布上的设备对象的相对坐标,使用相对图片的左边系,而不是画布的坐标系
function getDragDeviceObjectOrdinate(event, viewObj, deviceObj) {
// const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const imgObjects = viewObj.getObjects()[1]; // 获取图片对象
const { left, top } = viewObj.getSelectionElement().getBoundingClientRect();
const point = {
x: event.x - left,
y: event.y - top
x: event.x - left - imgObjects.left,
y: event.y - top - imgObjects.top
};
const pointerVpt = canvasObj.restorePointerVpt(point);
const x_ordinate = pointerVpt.x - deviceObj.width / 2;
const y_ordinate = pointerVpt.y;
const pointerVpt = viewObj.restorePointerVpt(point);
const x_ordinate = pointerVpt.x - (deviceObj.width * deviceObj.scaleX) / 2;
const y_ordinate = pointerVpt.y - (deviceObj.height * deviceObj.scaleY) / 2;
console.log(x_ordinate, y_ordinate, "getDragDeviceObjectOrdinate");
return {
@ -35,72 +39,90 @@ export const useDeviceObject = () => {
const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const imgObjects = viewObj.getObjects()[1]; // 获取图片对象
const startLeft =
(cvsObjects.width - imgObjects.width * imgObjects.scaleX) / 2;
(cvsObjects.width * cvsObjects.scaleX -
imgObjects.width * imgObjects.scaleX) /
2;
const startTop =
(cvsObjects.height - imgObjects.height * imgObjects.scaleY) / 2;
const endLeft = startLeft + imgObjects.width;
const endTop = startTop + imgObjects.height;
(cvsObjects.height * cvsObjects.scaleY -
imgObjects.height * imgObjects.scaleY) /
2;
const endLeft = startLeft + imgObjects.width * imgObjects.scaleX;
const endTop = startTop + imgObjects.height * imgObjects.scaleY;
return {
x_max: imgObjects.width * imgObjects.scaleX,
y_max: imgObjects.height * imgObjects.scaleY,
startLeft,
startTop,
endLeft,
endTop,
moveLeft: endLeft - activeObj.width * activeObj.scaleX,
moveTop: endTop - activeObj.height * activeObj.scaleY
moveLeft: endLeft - activeObj?.width * activeObj?.scaleX,
moveTop: endTop - activeObj?.height * activeObj?.scaleY
};
}
// 判断设备是否在可视区域内
function isInViewBoundaries(deviceObj, viewObj): boolean {
const { startLeft, startTop, moveLeft, moveTop } = fetchViewsBoundaries(
viewObj,
deviceObj
);
const { x_max, y_max } = fetchViewsBoundaries(viewObj, deviceObj);
const { x_ordinate, y_ordinate } = deviceObj;
// 获取对象的当前尺寸和位置
const objLeft = x_ordinate;
const objTop = y_ordinate;
// 限制对象在画布内移动
if (objLeft < startLeft) {
if (objLeft < 0) {
return false;
}
if (objTop < startTop) {
if (objTop < 0) {
return false;
}
if (objLeft > moveLeft) {
if (objLeft > x_max) {
return false;
}
if (objTop > moveTop) {
if (objTop > y_max) {
return false;
}
return true;
}
// 设备对象是否移动
function isMoveDevice(activeObject) {
function isMoveDevice(activeObject, viewObj) {
const { x_ordinate, y_ordinate } = activeObject.get(deviceInfoKey);
const { startLeft, startTop } = fetchViewsBoundaries(viewObj);
// 误差设置为 0.1
const errorValue = [1, 1];
let x_move = true;
let y_move = true;
const x_move_value = Math.abs(
Number(activeObject.left) - Number(x_ordinate) - Number(startLeft)
);
const y_move_value = Math.abs(
Number(activeObject.top) - Number(y_ordinate) - Number(startTop)
);
console.log(
"startLeft" + startLeft,
"startTop" + startTop,
"isMoveDevice",
"x_move_value" + x_move_value,
"y_move_value" + y_move_value,
activeObject.left,
x_ordinate,
activeObject.top,
y_ordinate,
Math.abs(Number(activeObject.top) - Number(y_ordinate)),
Math.abs(Number(activeObject.left) - Number(x_ordinate))
Math.abs(
Number(activeObject.top) - Number(y_ordinate) - Number(startTop)
),
Math.abs(
Number(activeObject.left) - Number(x_ordinate) - Number(startLeft)
)
);
if (
Math.abs(Number(activeObject.left) - Number(x_ordinate)) < errorValue[0]
) {
// TODO 重新绑定车间的设备没有坐标信息,暂时不判断设备是否移动【默认没有移动】
if (Number.isNaN(x_move_value) || Number.isNaN(y_move_value)) {
return false;
}
if (x_move_value < errorValue[0]) {
x_move = false;
}
if (
Math.abs(Number(activeObject.top) - Number(y_ordinate)) < errorValue[1]
) {
if (y_move_value < errorValue[1]) {
y_move = false;
}
return x_move || y_move;
@ -111,7 +133,10 @@ export const useDeviceObject = () => {
// }
// 初始化设备对象
const initDeviceGroupObjects: Record<string, any> = record => {
const initDeviceGroupObjects: Record<string, any> = (
record,
restDeviceItem = {}
) => {
console.log(record, "initDeviceGroupObjects");
// const { value } = record;
let iconObjectSrc = video_type_1;
@ -127,11 +152,20 @@ export const useDeviceObject = () => {
iconObjectSrc = video_type_1;
break;
}
let bgDeviceImage;
const fontStyle = { fill: "#333333" };
// 不在可视区域内的设备
if (record?.notInVisable) {
bgDeviceImage = device_video_bg_gray;
fontStyle.fill = "gray";
} else {
bgDeviceImage = device_video_bg;
}
return {
id: uuid(),
deviceInfo: record, // 设备信息
left: record?.x_ordinate ? Number(record?.x_ordinate) : 0,
top: record?.y_ordinate ? Number(record?.y_ordinate) : 0,
left: record?.left ? Number(record?.left) : 0,
top: record?.top ? Number(record?.top) : 0,
selectable: true,
hasControls: true,
lockUniScaling: true, // 当设置为trueObject将无法被锁定比例进行缩放。默认值为false。
@ -142,8 +176,7 @@ export const useDeviceObject = () => {
version: "5.3.0",
originX: "left",
originY: "top",
width: 113,
width: 132,
height: 66,
fill: "rgb(0,0,0)",
stroke: null,
@ -174,10 +207,10 @@ export const useDeviceObject = () => {
version: "5.3.0",
originX: "left",
originY: "top",
left: -56.5,
left: -66,
top: -33,
width: 113,
height: 66,
width: 264,
height: 132,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
@ -187,8 +220,8 @@ export const useDeviceObject = () => {
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
scaleX: 0.5,
scaleY: 0.5,
angle: 0,
flipX: false,
flipY: false,
@ -205,7 +238,7 @@ export const useDeviceObject = () => {
cropY: 0,
selectable: false,
hasControls: false,
src: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTEzIiBoZWlnaHQ9IjY2IiB2aWV3Qm94PSIwIDAgMTEzIDY2IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8ZyBmaWx0ZXI9InVybCgjZmlsdGVyMF9kXzIyMDNfMTAzMTgpIj4KPG1hc2sgaWQ9InBhdGgtMS1pbnNpZGUtMV8yMjAzXzEwMzE4IiBmaWxsPSJ3aGl0ZSI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAgMkM3Ljc5MDg2IDIgNiAzLjc5MDg2IDYgNlY0NEM2IDQ2LjIwOTEgNy43OTA4NiA0OCAxMCA0OEg0OS44TDU3IDU2TDY0LjIgNDhIMTAzQzEwNS4yMDkgNDggMTA3IDQ2LjIwOTEgMTA3IDQ0VjZDMTA3IDMuNzkwODYgMTA1LjIwOSAyIDEwMyAySDEwWiIvPgo8L21hc2s+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAgMkM3Ljc5MDg2IDIgNiAzLjc5MDg2IDYgNlY0NEM2IDQ2LjIwOTEgNy43OTA4NiA0OCAxMCA0OEg0OS44TDU3IDU2TDY0LjIgNDhIMTAzQzEwNS4yMDkgNDggMTA3IDQ2LjIwOTEgMTA3IDQ0VjZDMTA3IDMuNzkwODYgMTA1LjIwOSAyIDEwMyAySDEwWiIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC44IiBzaGFwZS1yZW5kZXJpbmc9ImNyaXNwRWRnZXMiLz4KPHBhdGggZD0iTTQ5LjggNDhMNTAuNTQzMyA0Ny4zMzFMNTAuMjQ1NCA0N0g0OS44VjQ4Wk01NyA1Nkw1Ni4yNTY3IDU2LjY2OUw1NyA1Ny40OTQ4TDU3Ljc0MzMgNTYuNjY5TDU3IDU2Wk02NC4yIDQ4VjQ3SDYzLjc1NDZMNjMuNDU2NyA0Ny4zMzFMNjQuMiA0OFpNNyA2QzcgNC4zNDMxNSA4LjM0MzE1IDMgMTAgM1YxQzcuMjM4NTggMSA1IDMuMjM4NTcgNSA2SDdaTTcgNDRWNkg1VjQ0SDdaTTEwIDQ3QzguMzQzMTUgNDcgNyA0NS42NTY5IDcgNDRINUM1IDQ2Ljc2MTQgNy4yMzg1NyA0OSAxMCA0OVY0N1pNNDkuOCA0N0gxMFY0OUg0OS44VjQ3Wk00OS4wNTY3IDQ4LjY2OUw1Ni4yNTY3IDU2LjY2OUw1Ny43NDMzIDU1LjMzMUw1MC41NDMzIDQ3LjMzMUw0OS4wNTY3IDQ4LjY2OVpNNTcuNzQzMyA1Ni42NjlMNjQuOTQzMyA0OC42NjlMNjMuNDU2NyA0Ny4zMzFMNTYuMjU2NyA1NS4zMzFMNTcuNzQzMyA1Ni42NjlaTTEwMyA0N0g2NC4yVjQ5SDEwM1Y0N1pNMTA2IDQ0QzEwNiA0NS42NTY5IDEwNC42NTcgNDcgMTAzIDQ3VjQ5QzEwNS43NjEgNDkgMTA4IDQ2Ljc2MTQgMTA4IDQ0SDEwNlpNMTA2IDZWNDRIMTA4VjZIMTA2Wk0xMDMgM0MxMDQuNjU3IDMgMTA2IDQuMzQzMTUgMTA2IDZIMTA4QzEwOCAzLjIzODU4IDEwNS43NjEgMSAxMDMgMVYzWk0xMCAzSDEwM1YxSDEwVjNaIiBmaWxsPSJ3aGl0ZSIgbWFzaz0idXJsKCNwYXRoLTEtaW5zaWRlLTFfMjIwM18xMDMxOCkiLz4KPC9nPgo8ZGVmcz4KPGZpbHRlciBpZD0iZmlsdGVyMF9kXzIyMDNfMTAzMTgiIHg9IjAiIHk9IjAiIHdpZHRoPSIxMTMiIGhlaWdodD0iNjYiIGZpbHRlclVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj4KPGZlRmxvb2QgZmxvb2Qtb3BhY2l0eT0iMCIgcmVzdWx0PSJCYWNrZ3JvdW5kSW1hZ2VGaXgiLz4KPGZlQ29sb3JNYXRyaXggaW49IlNvdXJjZUFscGhhIiB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMTI3IDAiIHJlc3VsdD0iaGFyZEFscGhhIi8+CjxmZU9mZnNldCBkeT0iNCIvPgo8ZmVHYXVzc2lhbkJsdXIgc3RkRGV2aWF0aW9uPSIzIi8+CjxmZUNvbXBvc2l0ZSBpbjI9ImhhcmRBbHBoYSIgb3BlcmF0b3I9Im91dCIvPgo8ZmVDb2xvck1hdHJpeCB0eXBlPSJtYXRyaXgiIHZhbHVlcz0iMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMC4xIDAiLz4KPGZlQmxlbmQgbW9kZT0ibm9ybWFsIiBpbjI9IkJhY2tncm91bmRJbWFnZUZpeCIgcmVzdWx0PSJlZmZlY3QxX2Ryb3BTaGFkb3dfMjIwM18xMDMxOCIvPgo8ZmVCbGVuZCBtb2RlPSJub3JtYWwiIGluPSJTb3VyY2VHcmFwaGljIiBpbjI9ImVmZmVjdDFfZHJvcFNoYWRvd18yMjAzXzEwMzE4IiByZXN1bHQ9InNoYXBlIi8+CjwvZmlsdGVyPgo8L2RlZnM+Cjwvc3ZnPgo=",
src: bgDeviceImage,
crossOrigin: null,
filters: []
},
@ -214,7 +247,7 @@ export const useDeviceObject = () => {
version: "5.3.0",
originX: "left",
originY: "top",
left: -40.6281,
left: -50.6281,
top: -22.9893,
width: 48,
height: 48,
@ -254,11 +287,11 @@ export const useDeviceObject = () => {
version: "5.3.0",
originX: "left",
originY: "top",
left: -7.3377,
left: -14.3377,
top: -15.4904,
width: 320,
height: 90.4,
fill: "#333333",
fill: fontStyle.fill,
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
@ -301,8 +334,49 @@ export const useDeviceObject = () => {
pathAlign: "baseline",
selectable: false,
hasControls: false
},
{
type: "image",
version: "5.3.0",
originX: "left",
originY: "top",
left: -47.6281,
top: -19.9893,
width: 40,
height: 40,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 0.6174,
scaleY: 0.6174,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: false,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
cropX: 0,
cropY: 0,
selectable: false,
hasControls: false,
src: notInVisableIcon,
crossOrigin: null,
filters: []
}
]
],
...restDeviceItem
};
};
return {

@ -1,564 +0,0 @@
/**
* @
* 1. 使
*/
export const useDeviceObject = () => {
const initDeviceGroupObjects: Record<string, any> = (record: {
id: string;
value: string;
}) => {
console.log(record, "initDeviceGroupObjects");
return {
selectable: true,
hasControls: true,
lockUniScaling: true, // 当设置为trueObject将无法被锁定比例进行缩放。默认值为false。
lockScalingX: true, // 当设置为trueObject水平方向将无法被缩放。默认值为false。
lockScalingY: true, // 当设置为trueObject垂直方向将无法被缩放。默认值为false。
lockRotation: true, // 当设置为trueObject的旋转将被锁定。默认值为false。
type: "group",
version: "5.3.0",
originX: "left",
originY: "top",
left: 20.9866,
top: 16.4716,
width: 131,
height: 66,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
objects: [
{
type: "group",
version: "5.3.0",
originX: "left",
originY: "top",
left: -65.5,
top: -33,
width: 131,
height: 66,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: "",
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
objects: [
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -60,
top: -31.5,
width: 119,
height: 54,
fill: "white",
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "evenodd",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 10, 2],
["C", 7.79086, 2, 6, 3.79086, 6, 6],
["L", 6, 44],
["C", 6, 46.2091, 7.79086, 48, 10, 48],
["L", 58.8, 48],
["L", 66, 56],
["L", 73.2, 48],
["L", 121, 48],
["C", 123.209, 48, 125, 46.2091, 125, 44],
["L", 125, 6],
["C", 125, 3.79086, 123.209, 2, 121, 2],
["L", 10, 2],
["Z"]
]
},
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -61,
top: -32.5,
width: 121,
height: 56.4948,
fill: "rgba(21,77,221,0.2)",
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 58.8, 48],
["L", 59.5433, 47.331],
["L", 59.2454, 47],
["L", 58.8, 47],
["L", 58.8, 48],
["Z"],
["M", 66, 56],
["L", 65.2567, 56.669],
["L", 66, 57.4948],
["L", 66.7433, 56.669],
["L", 66, 56],
["Z"],
["M", 73.2, 48],
["L", 73.2, 47],
["L", 72.7546, 47],
["L", 72.4567, 47.331],
["L", 73.2, 48],
["Z"],
["M", 7, 6],
["C", 7, 4.34315, 8.34315, 3, 10, 3],
["L", 10, 1],
["C", 7.23858, 1, 5, 3.23857, 5, 6],
["L", 7, 6],
["Z"],
["M", 7, 44],
["L", 7, 6],
["L", 5, 6],
["L", 5, 44],
["L", 7, 44],
["Z"],
["M", 10, 47],
["C", 8.34315, 47, 7, 45.6569, 7, 44],
["L", 5, 44],
["C", 5, 46.7614, 7.23858, 49, 10, 49],
["L", 10, 47],
["Z"],
["M", 58.8, 47],
["L", 10, 47],
["L", 10, 49],
["L", 58.8, 49],
["L", 58.8, 47],
["Z"],
["M", 58.0567, 48.669],
["L", 65.2567, 56.669],
["L", 66.7433, 55.331],
["L", 59.5433, 47.331],
["L", 58.0567, 48.669],
["Z"],
["M", 66.7433, 56.669],
["L", 73.9433, 48.669],
["L", 72.4567, 47.331],
["L", 65.2567, 55.331],
["L", 66.7433, 56.669],
["Z"],
["M", 121, 47],
["L", 73.2, 47],
["L", 73.2, 49],
["L", 121, 49],
["L", 121, 47],
["Z"],
["M", 124, 44],
["C", 124, 45.6569, 122.657, 47, 121, 47],
["L", 121, 49],
["C", 123.761, 49, 126, 46.7614, 126, 44],
["L", 124, 44],
["Z"],
["M", 124, 6],
["L", 124, 44],
["L", 126, 44],
["L", 126, 6],
["L", 124, 6],
["Z"],
["M", 121, 3],
["C", 122.657, 3, 124, 4.34315, 124, 6],
["L", 126, 6],
["C", 126, 3.23858, 123.761, 1, 121, 1],
["L", 121, 3],
["Z"],
["M", 10, 3],
["L", 121, 3],
["L", 121, 1],
["L", 10, 1],
["L", 10, 3],
["Z"]
]
},
{
type: "rect",
version: "5.3.0",
originX: "left",
originY: "top",
left: -52,
top: -24.5,
width: 32,
height: 32,
fill: "#52C41A",
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
rx: 2,
ry: 2,
selectable: true,
hasControls: true
},
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -45.9945,
top: -17.6,
width: 19.8963,
height: 0,
fill: "",
stroke: "white",
strokeWidth: 1.2,
strokeDashArray: null,
strokeLineCap: "round",
strokeDashOffset: 0,
strokeLineJoin: "round",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 40.0018, 16],
["L", 29.5301, 16],
["L", 20.1055, 16]
]
},
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -36.5727,
top: -17.6,
width: 0,
height: 8.8419,
fill: "",
stroke: "white",
strokeWidth: 1.2,
strokeDashArray: null,
strokeLineCap: "round",
strokeDashOffset: 0,
strokeLineJoin: "round",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 29.5273, 24.8419],
["L", 29.5273, 16]
]
},
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -46.1,
top: -10.5375,
width: 18.5869,
height: 10.9372,
fill: "white",
stroke: "white",
strokeWidth: 1.2,
strokeDashArray: null,
strokeLineCap: "round",
strokeDashOffset: 0,
strokeLineJoin: "round",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 21.8972, 23.0625],
["L", 38.5869, 27.5048],
["L", 37.6746, 28.8773],
["L", 35.579, 32.6272],
["L", 34.6667, 33.9997],
["L", 20, 30.0959],
["L", 21.8972, 23.0625],
["Z"]
]
},
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -30.5219,
top: -4.7211,
width: 4.1186,
height: 4.5576,
fill: "",
stroke: "white",
strokeWidth: 1.2,
strokeDashArray: null,
strokeLineCap: "round",
strokeDashOffset: 0,
strokeLineJoin: "round",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 37.6737, 28.8789],
["L", 39.6967, 29.4174],
["L", 38.6126, 33.4365],
["L", 35.5781, 32.6288]
]
},
{
type: "path",
version: "5.3.0",
originX: "left",
originY: "top",
left: -43.3008,
top: -7.6387,
width: 4.2123,
height: 4.181,
fill: "",
stroke: "#52C41A",
strokeWidth: 0.5,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: null,
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
selectable: true,
hasControls: true,
path: [
["M", 26.6615, 27.7018],
["C", 26.6615, 28.8548, 25.7201, 29.7923, 24.5554, 29.7923],
["C", 23.3906, 29.7923, 22.4492, 28.8548, 22.4492, 27.7018],
["C", 22.4492, 26.5488, 23.3906, 25.6113, 24.5554, 25.6113],
["C", 25.7201, 25.6113, 26.6615, 26.5488, 26.6615, 27.7018],
["Z"]
]
}
]
},
{
type: "textbox",
version: "5.3.0",
originX: "left",
originY: "top",
left: -15.709,
top: -15.0177,
width: 67.6873,
height: 13.56,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 1,
strokeDashArray: null,
strokeLineCap: "butt",
strokeDashOffset: 0,
strokeLineJoin: "miter",
strokeUniform: false,
strokeMiterLimit: 4,
scaleX: 1,
scaleY: 1,
angle: 0,
flipX: false,
flipY: false,
opacity: 1,
shadow: "",
visible: true,
backgroundColor: "",
fillRule: "nonzero",
paintFirst: "fill",
globalCompositeOperation: "source-over",
skewX: 0,
skewY: 0,
fontFamily: "arial",
fontWeight: "normal",
fontSize: 12,
text: record?.name || "设备",
underline: false,
overline: false,
linethrough: false,
textAlign: "left",
fontStyle: "normal",
lineHeight: 1.16,
textBackgroundColor: "",
charSpacing: 0,
styles: [],
direction: "ltr",
path: null,
pathStartOffset: 0,
pathSide: "left",
pathAlign: "baseline",
minWidth: 20,
splitByGrapheme: true,
selectable: true,
hasControls: true
}
]
};
};
return {
initDeviceGroupObjects
};
};

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-02 10:52:32
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-22 17:43:49
* @LastEditTime: 2024-08-28 17:36:58
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\index.vue
* @Description: 设备点位管理设置
@ 交互说明
@ -91,7 +91,7 @@ const deviceList = ref([]); // 所有设备列表
const currDeviceList = ref([]); //
const isDeleteVisible = ref<boolean>(false);
const deleteMessage = computed(() => {
return `确定删除“${activePoint.value.name}吗?删除后设备所处区域的实拍图或平面图及设备点位将一 并被删除,请谨慎操作。`;
return `'确定删除<span class="font-bold">${activePoint.value.name}</span>吗?删除后设备所处区域的实拍图或平面图及设备点位将一并被删除,请谨慎操作。`;
});
//
@ -255,6 +255,7 @@ function afterFinishEdit(record) {
}
return item;
});
fetchDeviceList();
console.log("afterFinishEdit", record);
nextTick(() => {
refreshCanvas(); //
@ -318,17 +319,19 @@ async function fetchDeviceByPoint() {
//
function afterAddDevice(record) {
currDeviceList.value = [...toRaw(currDeviceList.value), record];
deviceList.value = toRaw(deviceList.value).filter(item => {
if (item.id === record?.device_id) {
Object.assign(item, {
wd_id: record?.id,
workshop_name: record?.workshop_name,
is_binding: true
});
}
return item;
});
fetchDeviceByPoint();
fetchDeviceList();
// currDeviceList.value = [...toRaw(currDeviceList.value), record];
// deviceList.value = toRaw(deviceList.value).filter(item => {
// if (item.id === record?.device_id) {
// Object.assign(item, {
// wd_id: record?.id,
// workshop_name: record?.workshop_name,
// is_binding: true
// });
// }
// return item;
// });
console.log("新增完成", deviceList.value, record);
}
@ -371,18 +374,24 @@ async function editDevice({ editParams, callback }) {
//
function afterDeleteDevice(record) {
const deleteDeviceIds = JSON.parse(record);
currDeviceList.value = toRaw(currDeviceList.value).filter(
item => item.id !== record.id
item => !deleteDeviceIds.includes(item?.id)
);
deviceList.value = toRaw(deviceList.value).filter(item => {
if (item.id === record?.device_id) {
if (deleteDeviceIds.includes(item?.wd_id)) {
item.wd_id = undefined;
item.workshop_name = undefined;
item.is_binding = false;
}
return item;
});
console.log("删除完成", deviceList.value, record);
console.log(
currDeviceList.value,
"删除完成",
deviceList.value,
deleteDeviceIds
);
}
onMounted(() => {
@ -439,7 +448,7 @@ provide("canvasEditor", canvasEditor);
<!-- 左侧画布区域 -->
<div id="workspace" class="h-full deviceOfPoint_wrap">
<!-- <div class="inside-shadow"></div> -->
<canvas id="canvas" width="0" height="0" />
<canvas id="canvas" />
<!-- <dragMode v-if="state.showFabric"></dragMode>
<zoom></zoom> -->
<!-- <mouseMenu></mouseMenu> -->
@ -486,6 +495,7 @@ provide("canvasEditor", canvasEditor);
<DeviceSettingEdit
ref="deviceSettingEditRef"
@finishEdit="afterFinishEdit"
:currDeviceList="currDeviceList"
/>
</div>
</template>

Loading…
Cancel
Save