feat: 解决布点位置重复问题并优化

develop
donghao 10 months ago
parent 97b22aa010
commit d22275bffb

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-20 15:31:30
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-20 16:00:47
* @LastEditTime: 2024-08-22 17:42:58
* @FilePath: \General-AI-Platform-Web-Client\src\components\TableActionCard\isAction.tsx
* @Description:
*/
@ -23,14 +23,14 @@ export default defineComponent({
default: "确定要操作吗?"
},
visible: {
type: Boolean as PropType<boolean>,
required: true
type: Boolean as PropType<boolean>
// required: true
}
},
emits: ["update:visible", "confirm"],
setup(props, { emit }) {
// const visible = ref(props.visible);
const { visible } = toRefs(props);
const localVisible = ref<boolean>(visible.value);
const handleConfirm = () => {
emit("confirm");
// visible.value = false;
@ -38,27 +38,24 @@ export default defineComponent({
};
const handleCancel = () => {
// visible.value = false;
// localVisible.value = false;
emit("update:visible", false);
};
const handleClose = () => {
// visible.value = false;
// localVisible.value = false;
emit("update:visible", false);
// done();
};
watch(
() => props.visible,
val => {
visible.value = val;
}
);
watch(visible, newVal => {
localVisible.value = newVal;
});
return () => (
<ElDialog
className="action_model_wrap el-dialog"
visible={props.visible}
visible={localVisible.value}
width="560px"
before-close={handleClose}
show-close={false}

@ -2,11 +2,11 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-02-22 13:38:04
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-20 15:28:31
* @LastEditTime: 2024-08-22 17:46:27
* @FilePath: \General-AI-Platform-Web-Client\src\components\TableActionCard\isDelete.tsx
* @Description:
*/
import { defineComponent, ref, PropType } from "vue";
import { defineComponent, PropType } from "vue";
import { ElDialog, ElButton } from "element-plus";
// TODO 完善删除交互
export default defineComponent({
@ -40,7 +40,7 @@ export default defineComponent({
emit("update:visible", false);
};
const handleClose = (done: () => void) => {
const handleClose = () => {
// visible.value = false;
emit("update:visible", false);
// done();

@ -2,7 +2,7 @@
* @Author: zhoux zhouxia@supervision.ltd
* @Date: 2023-11-29 09:31:35
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-06 17:12:48
* @LastEditTime: 2024-08-22 09:46:30
* @FilePath: \vue-fabric-editor\src\core\ServersPlugin.ts
* @Description:
*/
@ -71,7 +71,7 @@ class ServersPlugin {
});
}
insertSvgFile(jsonFile) {
insertSvgFile(jsonFile, callback) {
console.log(jsonFile, "insertSvgFile");
// 加载前钩子
this.editor.hooksEntity.hookImportBefore.callAsync(jsonFile, () => {
@ -80,6 +80,8 @@ class ServersPlugin {
// 加载后钩子
this.editor.hooksEntity.hookImportAfter.callAsync(jsonFile, () => {
this.canvas.renderAll();
callback && callback();
console.log(this.canvas, "afterInsertSvgFile");
});
});
});

@ -2,7 +2,7 @@
* @Author:
* @Date: 2023-06-27 12:26:41
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-06 17:30:13
* @LastEditTime: 2024-08-21 15:59:11
* @Description:
*/
@ -201,12 +201,12 @@ class WorkspacePlugin {
// 自动缩放
auto() {
const scale = this._getScale();
this.setZoomAuto(scale - 0.08);
this.setZoomAuto(scale);
}
// 1:1 放大
one() {
this.setZoomAuto(0.8 - 0.08);
this.setZoomAuto(0.8);
this.canvas.requestRenderAll();
}

@ -12,3 +12,11 @@
text-transform: none;
}
}
.point_dialog_wrap {
.el-dialog__header {
padding: 16px 24px 0;
}
.el-dialog__body {
padding: 24px;
}
}

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-07 14:47:44
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-16 14:09:05
* @LastEditTime: 2024-08-21 13:44:44
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\components\add.vue
* @Description: 新建位置
-->
@ -105,11 +105,12 @@ defineExpose({
<template>
<div>
<el-dialog
class="point_dialog_wrap"
top="5vh"
v-model="dialogVisible"
title="新建布点位置"
append-to-body
width="44.445vw"
width="640px"
:style="{
borderRadius: '6px'
}"

@ -2,15 +2,15 @@
import useSelect from "@/hooks/select";
import { fetchArrayByAttrObject, setAttrObjectByArray } from "@/utils/utils";
//
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
deleteWorkshopDevicesApi
// editWorkshopDevicesApi
} from "@/api/workshops";
import { isSuccessApi } from "@/utils/forApi";
import { useDeviceObject } from "../hooks/useDeviceObject";
const props = defineProps({
pointInfo: {
@ -22,6 +22,7 @@ const emit = defineEmits(["afterDelete", "editDevice"]);
const event = inject("event");
const update = getCurrentInstance();
const { mixinState, canvasEditor } = useSelect();
const { fetchViewsBoundaries, isMoveDevice } = useDeviceObject();
/**业务属性 */
const formData = ref({
icon: 1
@ -52,23 +53,6 @@ const iconOptions = ref([
}
]);
const formRef = ref(null);
const submitForm = () => {
formRef.value?.validate((valid: boolean) => {
if (valid) {
//
// axios
// .post("/api/submit-icon", form.value)
// .then(() => {
// ElMessage.success("");
// })
// .catch(() => {
// ElMessage.error("");
// });
} else {
// ElMessage.error("");
}
});
};
/**拓展属性 */
//
@ -117,37 +101,24 @@ const fontAttr = reactive({
overline: false
});
//
const getCanvasBoundaries = () => {
const canvasObj = canvasEditor.canvas.getObjects()[1];
return {
width: canvasObj.width,
height: canvasObj.height
};
};
const constrainObjectWithinCanvas = obj => {
const { width, height } = getCanvasBoundaries();
//
const objLeft = obj.left;
const objTop = obj.top;
const objWidth = obj.width * obj.scaleX;
const objHeight = obj.height * obj.scaleY;
const { startLeft, startTop, moveLeft, moveTop } = fetchViewsBoundaries(
canvasEditor.canvas,
obj
);
//
if (objLeft < 0) {
obj.left = 0;
if (obj.left < startLeft) {
obj.left = startLeft;
}
if (objTop < 0) {
obj.top = 0;
if (obj.top < startTop) {
obj.top = startTop;
}
if (objLeft + objWidth > width) {
obj.left = width - objWidth;
if (obj.left > moveLeft) {
obj.left = moveLeft;
}
if (objTop + objHeight > height) {
obj.top = height - objHeight;
if (obj.top > moveTop) {
obj.top = moveTop;
}
//
obj.setCoords();
};
@ -212,29 +183,20 @@ async function deleteDeviceObject(deleteObject) {
}
}
//
// 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 && callback(resp);
// }
// }
function startEditDevice(callback) {
emit("editDevice", { formData: toRaw(formData.value), callback });
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"),
icon: formData.value?.icon
};
emit("editDevice", { editParams, callback });
}
const selectCancel = e => {
const selectCancel = () => {
baseAttr.fill = "";
update?.proxy?.$forceUpdate();
};
@ -246,7 +208,11 @@ const init = () => {
canvasEditor.canvas.on("object:deleteObject", deleteDeviceObject);
canvasEditor.canvas.on("mouse:up", () => {
const activeObject = canvasEditor.canvas.getActiveObject();
activeObject && activeObject.get("deviceInfo") && startEditDevice();
//
activeObject &&
activeObject.get("deviceInfo") &&
isMoveDevice(activeObject) &&
startEditDevice();
});
canvasEditor.canvas.on("object:modified", getObjectAttr);
// object:moving
@ -297,13 +263,11 @@ const changeCommon = (key, value) => {
if (key === "icon") {
// group fabric.Image
const imageObject = activeObject._objects[1];
if (imageObject) {
const targetIcon = toRaw(iconOptions.value).find(
item => item.value === value
);
console.log(targetIcon, "activeObject_iconType", activeObject);
if (targetIcon) {
//
startEditDevice(() => {
@ -318,31 +282,6 @@ const changeCommon = (key, value) => {
{ crossOrigin: "anonymous" }
);
});
//
// fabric.Image.fromURL(
// targetIcon.url,
// img => {
// // 使 oldImage.get()
// // img.set(imageObject.get());
// // group
// console.log(img, "old_img", imageObject);
// const index = activeObject._objects.indexOf(imageObject);
// if (index !== -1) {
// activeObject._objects[index] = {
// ...imageObject.get(),
// src: img.src
// }; //
// activeObject.addWithUpdate(); // group
// canvasEditor.canvas.renderAll(); //
// } else {
// console.error("Image object not found in the group.");
// }
// },
// {
// crossOrigin: "anonymous" //
// }
// );
}
return;
}
@ -368,24 +307,6 @@ onBeforeUnmount(() => {
</script>
<template>
<div class="deviceAtrr_toolbar" v-if="mixinState.mSelectMode === 'one'">
<!-- 字体属性 -->
<div v-show="textTypeConf.includes(mixinState.mSelectOneType)">
<!-- 字体属性 -->
</div>
<!-- ID属性 -->
<!-- <div>
<div class="flex-view">
<div class="flex-item">
<span class="label">{{ $t("attributes.id") }}</span>
<div class="content slider-box">
<input
v-model="baseAttr.id"
@change="changeCommon('id', baseAttr.id)"
/>
</div>
</div>
</div>
</div> -->
<el-form
ref="formRef"
:rules="rules"
@ -413,44 +334,5 @@ onBeforeUnmount(() => {
</el-radio-group>
</el-form-item>
</el-form>
<!-- 动态属性 -->
<!-- <div>
<ul>
<li class="flex-view" v-for="(v, k) in baseAttr.userProperty" :key="k">
<div class="flex-item">
<span class="content slider-box">
<input
v-model="baseAttr.userProperty[k].key"
@change="
changeCommon('userProperty_key', baseAttr.userProperty)
"
/>
</span>
<div class="content slider-box">
<input
v-model="baseAttr.userProperty[k].value"
@change="
changeCommon('userProperty_value', baseAttr.userProperty)
"
/>
</div>
</div>
</li>
<li
class="flex-view"
style="justify-content: center; color: dodgerblue; text-align: center"
@click="
() => {
baseAttr.userProperty.push({
key: 'key' + baseAttr.userProperty.length,
value: 'value'
});
}
"
>
<span>新增一项</span>
</li>
</ul>
</div> -->
</div>
</template>

@ -2,29 +2,31 @@
* @Description: 设备选择
-->
<script setup name="CanvasSize" lang="ts">
// import { Modal } from "view-ui-plus";
import useSelect from "@/hooks/select";
// import { cloneDeep } from "lodash-es";
// import { useI18n } from "vue-i18n";
import { useDeviceObject } from "../hooks/useDeviceObject";
// import watchOnlineSelected from "../../../assets/modelSetting/watchOnlineSelected.svg";
// const testSrc =
// "https://img.cgmodel.com/image/2020/1010/big/1537169-1390622992.jpg";
import { IsAction } from "@/components/Action";
const props = defineProps({
deviceList: {
type: Array as Record<string, any>[]
},
currDeviceList: {
type: Array as Record<string, any>[]
},
pointInfo: {
type: Object as Record<string, any>
}
});
const emit = defineEmits(["addDevice"]);
const emit = defineEmits(["addDevice", "editDevice"]);
const { fabric, mixinState, canvasEditor } = useSelect();
const { initDeviceGroupObjects } = useDeviceObject();
const {
initDeviceGroupObjects,
isInViewBoundaries,
getDragDeviceObjectOrdinate
} = useDeviceObject();
// const { t } = useI18n();
const defaultPosition = {
left: 100,
@ -46,11 +48,7 @@ interface materialItemI {
src: string;
}
// const allType: materialTypeI = {
// value: "",
// label: ""
// };
const allDeviceList = ref([]);
const state = reactive({
search: "",
// placeholder: <undefined | string>"",
@ -59,58 +57,86 @@ const state = reactive({
materialTypelist: [], //
materialist: [] //
});
const detailInfo = ref({});
const currDetailInfo = ref({
name: "设备",
workshop_name: "点位"
});
const isUpdateVisible = ref<boolean>(false);
const isAllowUpdate = ref<boolean>(false);
const currDetailInfo = ref({});
const isUpdateBindVisible = ref<boolean>(false);
const bindDeviceData = ref<Record<string, any>>({});
const updateMessage = computed(() => {
return `${currDetailInfo.value.name}”已绑定至“${currDetailInfo.value.workshop_name}”,确定解除绑定并重新配置吗?`;
});
//
canvasEditor.getMaterialType("svg").then((list: materialTypeI[]) => {
state.materialTypelist = [...list];
state.materialist = list;
return `${currDetailInfo.value?.name}”已绑定至“${currDetailInfo.value?.workshop_name}”,确定解除绑定并重新配置吗?`;
});
//
// const handleChange = (e, item) => {
// //
//
canvasEditor.getMaterialType("svg").then((list: materialTypeI[]) => {
state.materialTypelist = [...list];
state.materialist = list;
});
function fetchDetail(record, callback) {
detailInfo.value = record;
console.log(detailInfo.value, "fetchDetail");
emit("addDevice", { record, callback });
}
/**
* 校验是否允许添加设备
* @param record 选中的素材
* 处理添加设备&重复添加设备同点位不同点位
*/
function isValidAdd(event, record) {
console.log(props.currDeviceList, "isValidAdd_record", event, record);
//
if (record.is_binding) {
return false;
function deviceSelected(callback, options) {
const { targetDeviceItem } = options;
console.log(targetDeviceItem, "deviceSelected", props.currDeviceList);
currDetailInfo.value = targetDeviceItem;
if (targetDeviceItem.is_binding) {
let isSeemPoint = false;
toRaw(props.currDeviceList).forEach(item => {
if (item.device_id === targetDeviceItem.id) {
isSeemPoint = true;
}
});
if (!isSeemPoint) {
//
isUpdateBindVisible.value = true;
bindDeviceData.value = options;
} else {
//
emit("editDevice", {
editParams: {
// id: currDeviceInfo.id,
// device_id: currDeviceInfo.device_id,
id: targetDeviceItem.wd_id,
device_id: targetDeviceItem.id,
workshop_id: props.pointInfo?.id,
x_ordinate: targetDeviceItem.x_ordinate,
y_ordinate: targetDeviceItem.y_ordinate
},
callback: () => {
//
console.log(
canvasEditor.canvas.getObjects(),
"canvasEditor_callback"
);
canvasEditor.canvas.getObjects().forEach(v => {
if (v?.deviceInfo?.device_id === targetDeviceItem.id) {
v.set({
left: targetDeviceItem.x_ordinate,
top: targetDeviceItem.y_ordinate
});
canvasEditor.canvas.renderAll();
}
});
}
});
}
return;
}
return true;
//
emit("addDevice", { record: targetDeviceItem, callback });
}
//
function updateConfirmBind() {
const { event, item, targetDeviceItem } = toRaw(bindDeviceData.value);
console.log(event, item, targetDeviceItem, "updateConfirmBind");
emit("addDevice", {
record: targetDeviceItem,
callback: () => {
canvasEditor.dragAddItem(event, item); //
bindDeviceData.value = {}; //
isUpdateBindVisible.value = false;
}
});
}
const dragItem = (event, deviceItem) => {
console.log(event, deviceItem, "dragItem");
if (!isValidAdd(event, deviceItem)) {
return;
}
fabric.util.enlivenObjects(
[
{
@ -121,32 +147,47 @@ const dragItem = (event, deviceItem) => {
...initDeviceGroupObjects(deviceItem)
}
],
function (objects) {
// objects JSONGroup
// TODO
const item = objects[0];
console.log(event, item, "dragItem");
const { x_ordinate, y_ordinate } = getDragDeviceObjectOrdinate(
event,
canvasEditor.canvas,
item
);
//
if (
!isInViewBoundaries(
{ ...item, x_ordinate, y_ordinate },
canvasEditor.canvas
)
) {
return;
}
const targetDeviceItem = {
...deviceItem,
x_ordinate,
y_ordinate
};
fetchDetail(
{
...deviceItem,
x_ordinate: item.left,
y_ordinate: item.top
},
() => {
// canvasEditor.dragAddItem(event, item);
deviceSelected(
resData => {
//
item.set({
deviceInfo: resData
}); //
canvasEditor.dragAddItem(event, item);
},
{
targetDeviceItem,
event,
item
}
);
}
);
};
function updateConfirm() {
isAllowUpdate.value = true;
}
//
// const addItem = deviceItem => {
// if (isValidAdd(deviceItem)) {
@ -163,10 +204,11 @@ function updateConfirm() {
// ],
// function (objects) {
// const item = objects[0];
// canvasEditor.canvas.add(item);
// canvasEditor.canvas.setActiveObject(item);
// canvasEditor.canvas.requestRenderAll();
// fetchDetail(deviceItem);
// deviceSelected(() => {
// canvasEditor.canvas.add(item);
// canvasEditor.canvas.setActiveObject(item);
// canvasEditor.canvas.requestRenderAll();
// });
// }
// );
// };
@ -174,7 +216,6 @@ function updateConfirm() {
//
function renderDeviceToCanvas(record) {
const startArr = record;
const finalArr = [];
startArr.map(deviceItem => {
const fullDeviceItem = {
@ -196,97 +237,26 @@ function renderDeviceToCanvas(record) {
canvasEditor.canvas.add(groupObject);
}
});
// objects JSONGroup
// const item = enlivenedObjects[0];
// canvasEditor.canvas.setActiveObject(item);
canvasEditor.canvas.requestRenderAll();
});
}
// const DefaultSize = {
// width: 1200,
// height: 900
// };
// const modalData = reactive({
// width: DefaultSize.width,
// height: DefaultSize.height
// });
// let width = ref(DefaultSize.width);
// let height = ref(DefaultSize.height);
// let presetSize = reactive([
// {
// label: t("red_book_vertical"),
// width: 900,
// height: 1200
// },
// {
// label: t("red_book_horizontal"),
// width: 1200,
// height: 900
// },
// {
// label: t("phone_wallpaper"),
// width: 1080,
// height: 1920
// },
// {
// label: "kindle",
// width: 1200,
// height: 860
// },
// {
// label: "kindle-resize",
// width: 860,
// height: 1200
// }
// ]);
// const DefaultSize = {
// width: 977,
// height: 670
// };
onMounted(() => {
// 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,
// height: height.value,
// });
});
// const setSizeBy = (w, h) => {
// modalData.width = w;
// modalData.height = h;
// };
// const setSize = () => {
// canvasEditor.setSize(width.value, height.value);
// // canvas.editor.editorWorkspace.setSize(width.value, height.value);
// };
// const handleClose = () => {
// showModal.value = false;
// };
// const handleConfirm = () => {
// width.value = modalData.width;
// height.value = modalData.height;
// setSize();
// handleClose();
// };
// watch(
// () => props.deviceList,
// () => {
// console.log(props.deviceList, "watch_deviceList");
// },
// {
// immediate: true,
// deep: true
// }
// );
watch(
() => props.deviceList,
() => {
allDeviceList.value = toRaw(props.deviceList).filter(item => {
// item.workshop_id = item?.wd_id;
return item;
});
console.log(allDeviceList.value, "allDeviceList", props.deviceList);
},
// {
// immediate: true
// },
{
deep: true
}
);
defineExpose({ renderDeviceToCanvas });
</script>
<template>
@ -300,8 +270,8 @@ defineExpose({ renderDeviceToCanvas });
<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"
:class="currDetailInfo?.id === info.id ? 'active' : ''"
v-for="(info, i) in allDeviceList"
:key="`${i}-logo1-button`"
:draggable="true"
@dragend="event => dragItem(event, info)"
@ -315,11 +285,11 @@ defineExpose({ renderDeviceToCanvas });
</div>
</div>
<IsAction
v-model="isUpdateVisible"
@update:visible="val => (isUpdateVisible = val)"
v-model="isUpdateBindVisible"
@update:visible="val => (isUpdateBindVisible = val)"
title="确定重新绑定吗?"
:message="updateMessage"
@confirm="updateConfirm"
@confirm="updateConfirmBind"
/>
</template>
@ -339,9 +309,6 @@ defineExpose({ renderDeviceToCanvas });
background: #f5f5f5;
padding: 6px;
cursor: pointer;
// width: 135px;
// cursor: pointer;
// margin-right: 5px;
}
.form-wrap {

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-16 14:28:49
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-16 14:48:42
* @LastEditTime: 2024-08-21 13:50:47
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\components\edit.vue
* @Description: 新建位置
-->
@ -28,6 +28,7 @@ const formRef = ref(null);
const uploadRef = ref(null);
const imagePreview = ref<string | null>(null); // URL
const dialogVisible = ref<boolean>(false);
const isChangePic = ref<boolean>(false);
const fileList = ref([]);
const rules = {
name: [{ required: true, message: "请输入位置名称", trigger: "blur" }],
@ -55,6 +56,7 @@ const handleFileChange = (file: any) => {
...formData.value,
picture: file.raw
};
isChangePic.value = true;
};
//
const removeFile = () => {
@ -82,7 +84,9 @@ async function fetchEditPoint() {
const formParams = new FormData();
formParams.append("id", formData.value.id);
formParams.append("name", formData.value.name);
formParams.append("picture", formData.value.picture);
if (isChangePic.value) {
formParams.append("picture", formData.value.picture);
}
const resp = await editWorkshopsApi(formParams);
console.log(resp, "fetchAddPoint_resp");
if (isSuccessApi(resp)) {
@ -113,11 +117,12 @@ defineExpose({
<template>
<div>
<el-dialog
class="point_dialog_wrap"
top="5vh"
v-model="dialogVisible"
title="编辑布点位置"
append-to-body
width="44.445vw"
width="640px"
:style="{
borderRadius: '6px'
}"

@ -8,7 +8,109 @@ 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";
const deviceInfoKey = "deviceInfo";
export const useDeviceObject = () => {
// 移动到画布上的设备对象的相对坐标
function getDragDeviceObjectOrdinate(event, canvasObj, deviceObj) {
const { left, top } = canvasObj
.getSelectionElement()
.getBoundingClientRect();
const point = {
x: event.x - left,
y: event.y - top
};
const pointerVpt = canvasObj.restorePointerVpt(point);
const x_ordinate = pointerVpt.x - deviceObj.width / 2;
const y_ordinate = pointerVpt.y;
console.log(x_ordinate, y_ordinate, "getDragDeviceObjectOrdinate");
return {
x_ordinate: x_ordinate,
y_ordinate: y_ordinate
};
}
// 可操作区域的相对坐标
function fetchViewsBoundaries(viewObj, activeObj) {
const cvsObjects = viewObj.getObjects()[0]; // 获取画布对象
const imgObjects = viewObj.getObjects()[1]; // 获取图片对象
const startLeft =
(cvsObjects.width - imgObjects.width * imgObjects.scaleX) / 2;
const startTop =
(cvsObjects.height - imgObjects.height * imgObjects.scaleY) / 2;
const endLeft = startLeft + imgObjects.width;
const endTop = startTop + imgObjects.height;
return {
startLeft,
startTop,
endLeft,
endTop,
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_ordinate, y_ordinate } = deviceObj;
// 获取对象的当前尺寸和位置
const objLeft = x_ordinate;
const objTop = y_ordinate;
// 限制对象在画布内移动
if (objLeft < startLeft) {
return false;
}
if (objTop < startTop) {
return false;
}
if (objLeft > moveLeft) {
return false;
}
if (objTop > moveTop) {
return false;
}
return true;
}
// 设备对象是否移动
function isMoveDevice(activeObject) {
const { x_ordinate, y_ordinate } = activeObject.get(deviceInfoKey);
// 误差设置为 0.1
const errorValue = [1, 1];
let x_move = true;
let y_move = true;
console.log(
"isMoveDevice",
activeObject.left,
x_ordinate,
activeObject.top,
y_ordinate,
Math.abs(Number(activeObject.top) - Number(y_ordinate)),
Math.abs(Number(activeObject.left) - Number(x_ordinate))
);
if (
Math.abs(Number(activeObject.left) - Number(x_ordinate)) < errorValue[0]
) {
x_move = false;
}
if (
Math.abs(Number(activeObject.top) - Number(y_ordinate)) < errorValue[1]
) {
y_move = false;
}
return x_move || y_move;
}
// function fetchDeviceObjectBySeemKey(targetDeviceItem, viewObj) {
// console.log(targetDeviceItem, viewObj, "fetchDeviceObjectBySeemKey");
// }
// 初始化设备对象
const initDeviceGroupObjects: Record<string, any> = record => {
console.log(record, "initDeviceGroupObjects");
// const { value } = record;
@ -204,6 +306,11 @@ export const useDeviceObject = () => {
};
};
return {
initDeviceGroupObjects
initDeviceGroupObjects,
isInViewBoundaries,
getDragDeviceObjectOrdinate,
isMoveDevice,
fetchViewsBoundaries
// fetchDeviceObjectBySeemKey
};
};

@ -8,23 +8,6 @@ export const useDeviceObject = () => {
value: string;
}) => {
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;
// }
return {
selectable: true,
hasControls: true,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-14 11:26:47
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-15 13:25:48
* @LastEditTime: 2024-08-22 11:25:32
* @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
*/
@ -23,7 +23,7 @@ export const usePointObject = () => {
top: 0,
width: width,
height: height,
fill: "rgba(21, 77, 221, 0.1)",
fill: "", // rgba(21, 77, 221, 0.1)
stroke: null,
strokeWidth: 0,
strokeDashArray: null,
@ -56,12 +56,10 @@ export const usePointObject = () => {
{
type: "image",
version: "5.3.0",
originX: "left",
originY: "top",
left: 0,
top: 0,
width: width,
height: height,
// originX: "left",
// originY: "top",
// left: 0,
// top: 0,
fill: "rgb(0,0,0)",
stroke: null,
strokeWidth: 0,

@ -2,7 +2,7 @@
* @Author: donghao donghao@supervision.ltd
* @Date: 2024-08-02 10:52:32
* @LastEditors: donghao donghao@supervision.ltd
* @LastEditTime: 2024-08-20 16:44:13
* @LastEditTime: 2024-08-22 17:43:49
* @FilePath: \General-AI-Platform-Web-Client\src\views\deviceSetting\index.vue
* @Description: 设备点位管理设置
@ 交互说明
@ -32,7 +32,7 @@ import {
import { getLinkDevicesApi } from "@/api/device";
import { isSuccessApi } from "@/utils/forApi";
// TODO
// TODO
//
import { CanvasEventEmitter } from "@/utils/event/notifier";
// import { downFile } from '@/utils/utils';
@ -90,7 +90,6 @@ const activePoint = ref({
const deviceList = ref([]); //
const currDeviceList = ref([]); //
const isDeleteVisible = ref<boolean>(false);
const deleteMessage = computed(() => {
return `确定删除“${activePoint.value.name}”吗?删除后设备所处区域的实拍图或平面图及设备点位将一 并被删除,请谨慎操作。`;
});
@ -98,14 +97,37 @@ const deleteMessage = computed(() => {
//
const refreshCanvas = (isLoadDevice = true) => {
const currWorkSpace = document.getElementById("workspace");
console.log(
currWorkSpace.clientWidth,
currWorkSpace.clientHeight,
"currWorkSpace",
canvasEditor.canvas.viewportTransform
);
canvasEditor.insertSvgFile(
getPointObject(toRaw(activePoint.value), {
width: currWorkSpace.clientWidth,
height: currWorkSpace.clientHeight
})
}),
() => {
//
const img = canvasEditor.canvas.getObjects()[1] as fabric.Rect;
const cvs = canvasEditor.canvas.getObjects()[0] as fabric.Image;
// Get canvas dimensions
const canvasWidth = cvs.width;
const canvasHeight = cvs.height;
// Calculate the center position for the image
const left = (canvasWidth - img.width * img.scaleX) / 2;
const top = (canvasHeight - img.height * img.scaleY) / 2;
img.set({
left,
top
});
// Re-render the canvas to apply changes
canvasEditor.canvas.renderAll();
console.log("插入文件完成", canvasEditor.canvas.getObjects());
isLoadDevice && fetchDeviceByPoint();
}
);
isLoadDevice && fetchDeviceByPoint();
console.log("插入文件");
};
// fabric&
const initFabric = () => {
@ -117,6 +139,8 @@ const initFabric = () => {
hasControls: false,
selection: false
});
canvas.setZoom(1);
//
canvasEditor.init(canvas);
canvasEditor.use(DringPlugin);
@ -223,9 +247,18 @@ function editPoint() {
//
function afterFinishEdit(record) {
console.log("afterFinishEdit", record);
//
pointList.value = toRaw(pointList.value).filter(item => {
if (item.id === record.id) {
Object.assign(item, record);
activePoint.value = item;
}
return item;
});
console.log("afterFinishEdit", record);
nextTick(() => {
refreshCanvas(); //
});
}
//
@ -283,6 +316,22 @@ async function fetchDeviceByPoint() {
deviceSelectRef.value?.renderDeviceToCanvas(resp.data.results);
}
//
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;
});
console.log("新增完成", deviceList.value, record);
}
//
async function addDevice({ record, callback }) {
const resp = await addWorkshopDevicesApi({
@ -295,44 +344,25 @@ async function addDevice({ record, callback }) {
});
if (isSuccessApi(resp)) {
callback && callback(resp.data);
const finalData = {
...resp.data,
wd_id: resp.data?.id
};
currDeviceList.value = [...currDeviceList.value, finalData];
deviceList.value = toRaw(deviceList.value).filter(item => {
if (item.id === finalData?.id) {
item.wd_id = finalData?.wd_id;
item.is_binding = true;
}
return item;
});
afterAddDevice(resp.data);
}
}
//
function afterEditDevice(record) {
console.log("编辑完成", record);
currDeviceList.value = toRaw(currDeviceList.value).filter(item => {
if (item.device_id === record.device_id) {
Object.assign(item, record);
}
return item;
});
console.log("编辑完成", currDeviceList.value, record);
}
//
async function editDevice({ formData, callback }) {
const activeObject = canvasEditor.canvas.getActiveObject();
const currDeviceInfo = activeObject.get("deviceInfo");
const currParams = {
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.icon
};
console.log(
activeObject,
"editDeviceObject_activeObject",
currDeviceInfo,
currParams
);
const resp = await editWorkshopDevicesApi(currParams);
async function editDevice({ editParams, callback }) {
console.log("editDevice", editParams);
const resp = await editWorkshopDevicesApi(editParams);
if (isSuccessApi(resp)) {
afterEditDevice(resp.data);
callback && callback(resp.data);
@ -341,8 +371,18 @@ async function editDevice({ formData, callback }) {
//
function afterDeleteDevice(record) {
const startArr = toRaw(currDeviceList.value);
currDeviceList.value = startArr.filter(item => item.id !== record.id);
currDeviceList.value = toRaw(currDeviceList.value).filter(
item => item.id !== record.id
);
deviceList.value = toRaw(deviceList.value).filter(item => {
if (item.id === record?.device_id) {
item.wd_id = undefined;
item.workshop_name = undefined;
item.is_binding = false;
}
return item;
});
console.log("删除完成", deviceList.value, record);
}
onMounted(() => {
@ -399,7 +439,7 @@ provide("canvasEditor", canvasEditor);
<!-- 左侧画布区域 -->
<div id="workspace" class="h-full deviceOfPoint_wrap">
<!-- <div class="inside-shadow"></div> -->
<canvas id="canvas" />
<canvas id="canvas" width="0" height="0" />
<!-- <dragMode v-if="state.showFabric"></dragMode>
<zoom></zoom> -->
<!-- <mouseMenu></mouseMenu> -->
@ -411,11 +451,13 @@ provide("canvasEditor", canvasEditor);
:deviceList="deviceList"
:currDeviceList="currDeviceList"
@addDevice="addDevice"
@editDevice="editDevice"
:pointInfo="activePoint"
/>
<DeviceAttr
@afterDelete="afterDeleteDevice"
@editDevice="editDevice"
:pointInfo="activePoint"
/>
</div>
</div>

Loading…
Cancel
Save