inoutDialog.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <template>
  2. <div id="treedomDialog">
  3. <el-dialog
  4. @close="cancelClick2"
  5. v-model="open"
  6. append-to-body
  7. draggable
  8. width="70%"
  9. style="height: 550px; overflow-y: auto"
  10. >
  11. <template #header>
  12. <div class="my-header">
  13. <div class="title">
  14. {{ `虚端子 — 详细信息` }}
  15. </div>
  16. </div>
  17. </template>
  18. <div class="dialog-circle">
  19. <div class="dialog-left">
  20. <div class="nav" v-if="listData">
  21. <div>{{ listData.ied_name }}</div>
  22. <div class="desc">{{ listData.desc }}</div>
  23. </div>
  24. <p class="title" v-if="dilogData&&dilogData.length>0 && titleUnusual == 'inout'">
  25. {{ `${dilogData[0].attr_ld_inst} ${dilogData[0].attr_ld_desc}` }}
  26. </p>
  27. <p class="title" v-if="dilogData&&dilogData.length>0 && titleUnusual != 'inout'">
  28. {{ `${dilogData[0].to_ld_inst} ${dilogData[0].to_ld_desc}` }}
  29. </p>
  30. <!-- 白色区域的内容 -->
  31. <div class="main">
  32. <div class="main-title" v-if="titleUnusual == 'input'"></div>
  33. <div class="main-title" v-else>
  34. {{ `${dilogLeftTitle.attr_name}${dilogLeftTitle.datset_desc}` }}
  35. </div>
  36. <div
  37. class="ied-desc-child"
  38. v-for="(item, index) in dilogData"
  39. :key="index"
  40. :ref="(el) => setDialogLeftChild2(el, item)"
  41. >
  42. <template v-if="titleUnusual == 'input'">
  43. <div>{{ item.to_doi_desc }}</div>
  44. <div>{{ item.attr_int_addr }}</div>
  45. </template>
  46. <template v-else>
  47. <div>{{ item.from_doi_desc }}</div>
  48. <div>
  49. {{
  50. `${item.attr_ld_inst}/${item.attr_prefix}${item.attr_ln_class}${item.attr_ln_inst}.${item.attr_do_name}.${item.attr_da_name}`
  51. }}
  52. </div>
  53. </template>
  54. </div>
  55. </div>
  56. </div>
  57. <div class="dialog-right">
  58. <div class="nav" v-if="titleUnusual == 'input'">
  59. <div>{{ dilogTitie.target_ied_name }}</div>
  60. <div class="desc">
  61. {{ dilogRightData[dilogTitie.target_ied_name].desc }}
  62. </div>
  63. </div>
  64. <div class="nav" v-else>
  65. <div>{{ dilogTitie.ref_ied_name }}</div>
  66. <div class="desc">
  67. {{ dilogRightData[dilogTitie.ref_ied_name].desc }}
  68. </div>
  69. </div>
  70. <p class="title" v-if="dilogData&&dilogData.length>0 && titleUnusual == 'inout'">
  71. {{ `${dilogData[0].to_ld_inst} ${dilogData[0].to_ld_desc}` }}
  72. </p>
  73. <p class="title" v-if="dilogData&&dilogData.length>0 && titleUnusual != 'inout'">
  74. {{ `${dilogData[0].attr_ld_inst} ${dilogData[0].attr_ld_desc}` }}
  75. </p>
  76. <!-- 白色区域的内容 -->
  77. <div class="main">
  78. <div class="main-title" v-if="titleUnusual == 'input'">
  79. {{ dilogTitie.ctrl_name + dilogTitie.datset_desc }}
  80. </div>
  81. <div class="main-title" v-else></div>
  82. <div
  83. class="ied-desc-child"
  84. v-for="(item, index) in dilogData"
  85. :key="index"
  86. :ref="(el) => setDialogRightChild2(el, item)"
  87. >
  88. <template v-if="titleUnusual == 'input'">
  89. <div>{{ item.from_doi_desc }}</div>
  90. <div>
  91. {{
  92. `${item.attr_ld_inst}/${item.attr_prefix}${item.attr_ln_class}${item.attr_ln_inst}.${item.attr_do_name}.${item.attr_da_name}`
  93. }}
  94. </div>
  95. </template>
  96. <template v-else>
  97. <div>{{ item.to_doi_desc }}</div>
  98. <div>{{ item.attr_int_addr }}</div>
  99. </template>
  100. </div>
  101. </div>
  102. </div>
  103. </div>
  104. <div id="dilogwrapperInout"></div>
  105. </el-dialog>
  106. </div>
  107. </template>
  108. <script setup>
  109. import { ref, reactive, watch, nextTick, defineEmits, onMounted } from "vue";
  110. import LeaderLine from "../../../../public/leader-line.min.js";
  111. import AnimEvent from "../../../../public/anim-event.min.js";
  112. const props = defineProps({
  113. checkData: {
  114. type: Object,
  115. default: () => {},
  116. },
  117. circleOpen: {
  118. type: Boolean,
  119. default: false,
  120. },
  121. dilogData: {
  122. type: Array,
  123. default: () => [],
  124. },
  125. dilogTitie: {
  126. type: Object,
  127. default: () => {},
  128. },
  129. dilogRightData: {
  130. type: Object,
  131. default: () => {},
  132. },
  133. titleUnusual: {
  134. type: String,
  135. default: "",
  136. },
  137. dilogLeftTitle: {
  138. type: Object,
  139. default: () => {},
  140. },
  141. listData2:{
  142. type: Object,
  143. default: () => {},
  144. }
  145. });
  146. const open = ref(false);
  147. const listData = ref(props.listData2); //线条左右两侧的数据
  148. watch(()=>props.listData2,(newValue)=>{
  149. listData.value = newValue
  150. })
  151. const dialogListRightChild = ref(new Map()); //获取弹窗右侧所有子的ref
  152. const dialogListLeftChild = ref(new Map()); //获取弹窗左侧所有子的ref
  153. const setDialogLeftChild2 = (el, item) => {
  154. if (el) {
  155. dialogListLeftChild.value.set(item, el);
  156. }
  157. };
  158. const setDialogRightChild2 = (el, item) => {
  159. if (el) {
  160. dialogListRightChild.value.set(item, el);
  161. }
  162. };
  163. const emit = defineEmits(["done"]);
  164. const dialogLines = ref([]);
  165. const cancelClick2 = () => {
  166. open.value = false;
  167. emit("done", false);
  168. };
  169. //弹框画线
  170. const setDialogLine = () => {
  171. console.log('======dir:',props.titleUnusual)
  172. dialogLines.value = [];
  173. for (const [key, value] of dialogListRightChild.value) {
  174. let line;
  175. for (const [key2, value2] of dialogListLeftChild.value) {
  176. if (key.attr_int_addr == key2.attr_int_addr) {
  177. LeaderLine.positionByWindowResize = false;
  178. if (props.titleUnusual == "input") {
  179. line = new LeaderLine(value2, value, {
  180. color: "#255CE7",
  181. size: 2,
  182. path: "straight",
  183. startSocket: "right",
  184. endSocket: "left",
  185. startPlug: "arrow1",
  186. endPlug: "behind",
  187. });
  188. } else {
  189. line = new LeaderLine(value2, value, {
  190. color: "#255CE7",
  191. size: 2,
  192. path: "straight",
  193. startSocket: "right",
  194. endSocket: "left",
  195. startPlug: "behind",
  196. endPlug: "arrow1",
  197. });
  198. }
  199. dialogLines.value.push(line);
  200. }
  201. }
  202. }
  203. };
  204. watch(
  205. () => props.circleOpen,
  206. (newValue) => {
  207. open.value = newValue;
  208. if (newValue==true) {
  209. nextTick(() => {
  210. setDialogLine();
  211. hiddenLineDialog();
  212. newPositionLine3(dialogLines.value);
  213. });
  214. } else {
  215. dialogListLeftChild.value.clear();
  216. dialogListRightChild.value.clear();
  217. dialogLines.value = [];
  218. const elmWrapper = document.getElementById("dilogwrapperInout");
  219. if (elmWrapper) {
  220. document.body
  221. .querySelectorAll("#dilogwrapperInout .leader-line")
  222. .forEach((node) => {
  223. node.remove();
  224. // elmWrapper.removeChild(node);
  225. });
  226. }
  227. }
  228. }
  229. );
  230. //滚动时重定位线条
  231. const newPositionLine3 = (diffline) => {
  232. document.getElementById("treedomDialog").addEventListener(
  233. "scroll",
  234. AnimEvent.add(() => {
  235. diffline.forEach((line) => {
  236. if (line) {
  237. hiddenLineDialog();
  238. line.position();
  239. line.positionByWindowResize = false;
  240. }
  241. });
  242. //中间展示图片的
  243. }),
  244. false
  245. );
  246. document.getElementById("treedomDialog").addEventListener(
  247. "resize",
  248. AnimEvent.add(function () {
  249. diffline.forEach((line) => {
  250. hiddenLineDialog();
  251. line.position();
  252. line.positionByWindowResize = false;
  253. });
  254. }),
  255. false
  256. );
  257. };
  258. //弹窗打开后使得线条在指定区域中
  259. const hiddenLineDialog = () => {
  260. const elmWrapper = document.getElementById("dilogwrapperInout");
  261. if(!elmWrapper) return;
  262. if (elmWrapper) {
  263. document.body.querySelectorAll("body>.leader-line").forEach((node) => {
  264. elmWrapper.appendChild(node);
  265. });
  266. elmWrapper.style.transform = "none";
  267. var rectWrapper = elmWrapper.getBoundingClientRect();
  268. elmWrapper.style.transform = `translate(${
  269. (rectWrapper.left + window.scrollY) * -1
  270. }px, ${(rectWrapper.top + window.scrollX) * -1}px)`;
  271. }
  272. };
  273. onMounted(() => {});
  274. </script>
  275. <style lang="scss" scoped>
  276. @mixin left-and-right {
  277. display: flex;
  278. flex-direction: column;
  279. }
  280. .my-header {
  281. border-bottom: 1px solid #a3ade0;
  282. font-size: 16px;
  283. color: #1a2447;
  284. .title {
  285. padding-bottom: 15px;
  286. }
  287. }
  288. .dialog-circle {
  289. display: flex;
  290. flex-wrap: nowrap;
  291. justify-content: space-around;
  292. //点击数字弹窗的样式
  293. .dialog-left,
  294. .dialog-right {
  295. flex-basis: 40%;
  296. border: 2px dashed #98a8ff;
  297. background: #f7f8fb;
  298. border-radius: 4px;
  299. .nav {
  300. text-align: center;
  301. border-bottom: 1px solid #c8d4e2;
  302. .desc {
  303. color: #255ce7;
  304. padding-bottom: 4px;
  305. }
  306. }
  307. .title {
  308. margin: 7px 20px;
  309. }
  310. .main {
  311. margin: 0 20px;
  312. border: 1px solid #c8d4e2;
  313. .main-title {
  314. height: 40px;
  315. text-align: center;
  316. line-height: 40px;
  317. background: #fff;
  318. }
  319. }
  320. }
  321. .dialog-left {
  322. }
  323. .dialog-right {
  324. }
  325. }
  326. #dilogwrapperInout,
  327. #treedomDialog {
  328. width: 0;
  329. height: 0;
  330. position: relative; /* Origin of coordinates for lines, and scrolled content (i.e. not `absolute`) */
  331. }
  332. .ied-desc-child {
  333. @include left-and-right;
  334. align-items: center;
  335. border: 1px solid #7484ab;
  336. border-radius: 2px;
  337. margin: 12px 14px;
  338. padding: 5px;
  339. color: #1a2447;
  340. position: relative;
  341. }
  342. .leader-line {
  343. z-index: 99999;
  344. }
  345. </style>