123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- <!-- 装置关联关系 -->
- <template>
- <div
- v-loading="loading"
- element-loading-text="加载数据中"
- >
- <div class="main-cont" ref="myElement" id="treedom" style="overflow: hidden">
- <div class="main-left" ref="leftElement">
- <div
- v-for="(item, index) in leftList"
- :key="index"
- class="cont"
- @click="clickImg(item)"
- >
- <img
- :src="devicePng"
- alt=""
- class="img-item"
- :ref="(el) => setdom(el, item)"
- />
- <div>{{ item.ref_ied_name }}</div>
- <div class="ied-desc">{{ item.ref_ied_desc }}</div>
- </div>
- </div>
- <div class="main-middle">
- <div class="middle-item" ref="middleElement">
- <img :src="devicePng" alt="" id="end" />
- <div v-if="listData">{{ listData.ied_name }}</div>
- <div v-if="listData">{{ listData.desc }}</div>
- </div>
- </div>
- <div class="main-right" ref="rightElement">
- <div
- v-for="(item, index) in rightList"
- :key="index"
- class="cont"
- @click="clickImg(item)"
- >
- <img
- :src="devicePng"
- alt=""
- class="img-item"
- :ref="(el) => setdomRight(el, item)"
- />
- <div>{{ item.ref_ied_name }}</div>
- <div class="ied-desc">{{ item.ref_ied_desc }}</div>
- </div>
- </div>
- </div>
- <div id="wrapper"></div>
- </div>
- </template>
- <script setup>
- import { onMounted, watch, ref, nextTick, defineEmits, inject } from "vue";
- import devicePng from "@/assets/image/instruct/device.png";
- import LeaderLine from "../../../../public/leader-line.min.js";
- import AnimEvent from "../../../../public/anim-event.min.js";
- import { useRoute } from "vue-router";
- import { clickImgEvent } from "@/utils/common.js";
- const route = useRoute();
- const loading = ref(true);
- const props = defineProps({
- checkData: {
- type: Object,
- default: () => {},
- },
- isOpen: {
- type: Boolean,
- default: false,
- },
- iedRelation: {
- type: Object,
- default: () => {},
- },
- isScdView: {
- type: Boolean,
- default: false,
- },
- });
- const middleElement = ref(null);
- const rightElement = ref(null);
- const leftElement = ref(null);
- const myElement = ref(null);
- let leaderLines = ref([]); //控制线条显示
- const leftList = ref([]);
- const rightList = ref([]);
- const domList = ref(new Map()); //获取 所有的ref
- const domListRight = ref(new Map()); //获取 所有的ref
- const listData = ref(props.checkData); //线条左右两侧的数据
- const emit = defineEmits(["result"]); //如果不加这个再次点击左侧会没有反应
- const setdom = (el, item) => {
- //左侧dom
- if (el) {
- domList.value.set(item, el);
- }
- };
- const setdomRight = (el, item) => {
- //右侧dom
- if (el) {
- domListRight.value.set(item, el);
- }
- };
- const processArray = (arr) => {
- // ref_ied_id作为键,obj作为值
- const uniqueObjects = new Map();
- if (!arr) return;
- // 遍历数组
- for (const obj of arr) {
- const { ref_ied_id } = obj;
- // 如果当前对象的 ref_ied_id 属性已经存在于 uniqueObjects 中
- if (uniqueObjects.has(ref_ied_id)) {
- // 将对应对象的 ref_type 属性设为 2,箭头双向
- uniqueObjects.get(ref_ied_id).ref_type = 2;
- } else {
- // 否则,将当前对象添加到 uniqueObjects 中
- uniqueObjects.set(ref_ied_id, obj);
- }
- }
- // 将 uniqueObjects 中的值转为数组并返回
- return Array.from(uniqueObjects.values());
- };
- //点击图片的时候筛选出数据
- const clickImg = async (dataItem) => {
- loading.value = true;
- listData.value = await clickImgEvent(props, dataItem, scdIdValue);
- if (!listData.value || !listData.value.length) return (loading.value = false);
- };
- watch(
- () => props.checkData,
- (newValue, oldV) => {
- loading.value = true;
- listData.value = newValue;
- if (newValue && leaderLines.value.length > 0) {
- // leaderLines.value.forEach((line) => line.remove()); //清除连线
- leaderLines.value = [];
- }
- },
- { deep: true }
- );
- watch(
- () => listData.value,
- (newValue) => {
- emit("result", newValue);
- clickResetLine();
- }
- );
- watch(
- () => props.isOpen,
- (newValue) => {
- if (newValue) {
- domList.value.clear();
- domListRight.value.clear();
- leaderLines.value = [];
- nextTick(() => {
- // middleLinePosition();
- removeLine();
- });
- }
- }
- );
- //点击后重置数据和线条
- const clickResetLine = () => {
- domList.value.clear();
- domListRight.value.clear();
- leaderLines.value = [];
- removeLine();
- middleLinePosition();
- setLine();
- };
- // 将设备列表分成两份
- const bothSide = (data) => {
- const formatArr = processArray(data);
- if (!formatArr && formatArr.length) return;
- const arrlenght = formatArr.length;
- const long1 = Math.ceil(arrlenght / 2);
- leftList.value = formatArr.splice(0, long1);
- rightList.value = formatArr.splice(0);
- };
- const setLeaderline = () => {
- //线条样式
- const lineStyle1 = {
- color: "#51637F",
- size: 2,
- path: "straight",
- endPlug: "arrow1",
- startSocket: "right",
- endSocket: "left",
- };
- const lineStyle0 = {
- ...lineStyle1,
- startPlug: "arrow1",
- endPlug: "behind",
- };
- const lineStyle2 = {
- color: "#134BEA",
- size: 2,
- path: "straight",
- startPlug: "arrow1",
- endPlug: "arrow1",
- startSocket: "right",
- endSocket: "left",
- };
- const lineStyleRight1 = {
- ...lineStyle1,
- startSocket: "left",
- endSocket: "right",
- };
- const lineStyleRight0 = {
- ...lineStyleRight1,
- startPlug: "arrow1",
- endPlug: "behind",
- };
- const lineStyleRight2 = {
- ...lineStyle2,
- startSocket: "left",
- endSocket: "right",
- };
- const startDom = document.getElementById("end");
- let count = 56;
- //循环画线
- for (const [key, value] of domList.value) {
- const endDom = value;
- let line;
- count += 5;
- LeaderLine.positionByWindowResize = false;
- if (key.ref_type == 0) {
- line = new LeaderLine(
- endDom,
- LeaderLine.pointAnchor(startDom, { x: 0, y: count }),
- lineStyle0
- );
- } else if (key.ref_type == 1) {
- line = new LeaderLine(
- endDom,
- LeaderLine.pointAnchor(startDom, { x: 0, y: count }),
- lineStyle1
- );
- } else if (key.ref_type == 2) {
- line = new LeaderLine(
- endDom,
- LeaderLine.pointAnchor(startDom, { x: 0, y: count }),
- lineStyle2
- );
- }
- // 保存进数组,方便进行遍历删除
- leaderLines.value.push(line);
- }
- let count2 = 56;
- //循环画线右侧
- for (const [key, value] of domListRight.value) {
- const endDom = value;
- let line2;
- count2 += 5;
- LeaderLine.positionByWindowResize = false;
- if (key.ref_type == 0) {
- line2 = new LeaderLine(
- endDom,
- LeaderLine.pointAnchor(startDom, { x: "100%", y: count2 }),
- lineStyleRight0
- );
- } else if (key.ref_type == 1) {
- line2 = new LeaderLine(
- endDom,
- LeaderLine.pointAnchor(startDom, { x: "100%", y: count2 }),
- lineStyleRight1
- );
- } else if (key.ref_type == 2) {
- line2 = new LeaderLine(
- endDom,
- LeaderLine.pointAnchor(startDom, { x: "100%", y: count2 }),
- lineStyleRight2
- );
- }
- // 保存进数组,方便进行遍历删除
- leaderLines.value.push(line2);
- }
- loading.value = false;
- hiddenLine();
- };
- //设置中间盒子的所在位置
- const middleLinePosition = () => {
- setTimeout(() => {
- const heights = myElement.value.scrollHeight;
- let leftListLength = leftList.value.length;
- let rightListLength = rightList.value.length;
- console.log("leftListLength", leftListLength, rightListLength);
- const setElementMarginTop = (element, value) => {
- element.value.style.marginTop = `${value}px`;
- };
- switch (`${rightListLength}${leftListLength}`) {
- case "11":
- setElementMarginTop(rightElement, 165);
- setElementMarginTop(leftElement, 165);
- setElementMarginTop(middleElement, 150);
- break;
- case "22":
- setElementMarginTop(rightElement, 92);
- setElementMarginTop(leftElement, 92);
- setElementMarginTop(middleElement, 150);
- break;
-
- default:
- if (!middleElement.value) return;
- if (rightListLength <= 4 && leftListLength <= 4) {
- setElementMarginTop(middleElement, 150);
- }
- if (leftListLength > 4 || rightListLength > 4) {
- setElementMarginTop(rightElement, 0);
- setElementMarginTop(leftElement, 0);
- middleElement.value.style.marginTop = `${(heights - 60) / 2}px`; // 设置元素的垂直位置
- }
- break;
- }
- const marginTopValues = { 1: 165, 2: 92, 3: 50 };
- setElementMarginTop(rightElement, marginTopValues[rightListLength] || 0);
- setElementMarginTop(leftElement, marginTopValues[leftListLength] || 0);
- }, 0);
- };
- let scdIdValue = "";
- onMounted(() => {
- if (props.delScdId) {
- scdIdValue = props.delScdId;
- } else {
- scdIdValue = route.query.id;
- }
- nextTick(() => {
- setLine();
- middleLinePosition();
- nextTick(() => {
- newPositionLine();
- });
- });
- });
- //滚动时重定位线条
- const newPositionLine = () => {
- if (!document.getElementById("treedom")) return;
- document.getElementById("treedom").addEventListener(
- "scroll",
- AnimEvent.add(() => {
- if (!leaderLines.value) return;
- leaderLines.value.forEach((line) => {
- hiddenLine();
- line.position();
- line.positionByWindowResize = false;
- });
- }),
- false
- );
- document.getElementById("treedom").addEventListener(
- "resize",
- AnimEvent.add(function () {
- if (!leaderLines.value) return;
- leaderLines.value.forEach((line) => {
- hiddenLine();
- line.position();
- line.positionByWindowResize = true;
- });
- }),
- false
- );
- };
- //弹窗打开后使得线条在指定区域中
- const hiddenLine = () => {
- const elmWrapper = document.getElementById("wrapper");
- if (!elmWrapper) return;
- // 移动 line
- document.body.querySelectorAll("body .leader-line").forEach((node) => {
- elmWrapper.appendChild(node);
- });
- elmWrapper.style.transform = "none";
- var rectWrapper = elmWrapper.getBoundingClientRect();
- // Move to the origin of coordinates as the document
- elmWrapper.style.transform = `translate(${
- (rectWrapper.left + window.scrollY) * -1
- }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
- };
- const setLine = () => {
- if (listData.value) {
- bothSide(listData.value.list);
- }
- setTimeout(() => {
- setLeaderline();
- }, 300);
- };
- const removeLine = () => {
- const elmWrapper = document.getElementById("wrapper");
- if (elmWrapper) {
- document.body.querySelectorAll("#wrapper .leader-line").forEach((node) => {
- elmWrapper.removeChild(node);
- });
- }
- };
- </script>
- <style lang="scss">
- @mixin img-size {
- width: 150px;
- height: 90px;
- margin-bottom: 10px;
- }
- @mixin left-and-right {
- display: flex;
- flex-direction: column;
- }
- .main-cont {
- margin-top: 60px;
- display: flex;
- justify-content: space-evenly;
- }
- .leader-line {
- z-index: 3000;
- }
- .main-left {
- display: flex;
- @include left-and-right;
- .img-item {
- @include img-size;
- }
- }
- .main-middle {
- box-sizing: border-box;
- img {
- margin-bottom: 10px;
- }
- .middle-item {
- @include left-and-right;
- align-items: center;
- color: #ffcb11;
- }
- }
- .main-right {
- display: flex;
- @include left-and-right;
- .img-item {
- @include img-size;
- }
- }
- .cont {
- @include left-and-right;
- align-items: center;
- margin-bottom: 10px;
- .ied-desc {
- color: #255ce7;
- }
- }
- #wrapper {
- width: 0;
- height: 0;
- position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
- }
- </style>
|