DrawDesigns.vue 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. <template>
  2. <div>
  3. <div class="bigBox">
  4. <div ref="container" class="container" v-loading="loading"></div>
  5. </div>
  6. <!-- 功能模态框 -->
  7. <AbilityModal v-if="abModal" :fun="fun" :funOne="funOne" :listMap="listMap" :abModal="abModal"
  8. :modelId="modelId" :iedType="iedType" :nodeid="nodeid" @abilityBack="abilityBack">
  9. </AbilityModal>
  10. <LineDouble v-if="ldModal" :ldModal="ldModal" :modelId="modelId" :startTarget="startTarget"
  11. :endTarget="endTarget" :numCase="numCase" :startText="startText" :endText="endText" :lineType="lineType"
  12. @lineBack="lineBack">
  13. </LineDouble>
  14. <GroupModelAdd v-if="groupType" :groupType="groupType" :groupNodeId="groupNodeId" :modelId="modelId"
  15. @groupBack="groupBack"></GroupModelAdd>
  16. </div>
  17. </template>
  18. <script>
  19. import { ref, onMounted, watch, onBeforeUnmount } from 'vue';
  20. import LogicFlow from "@logicflow/core";
  21. import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core";
  22. import cid from '@/api/cid/cid'
  23. import { ElMessage } from 'element-plus';
  24. import { useRouter, useRoute } from 'vue-router';
  25. import AbilityModal from "../drawModal/AbilityModal.vue"
  26. import LineDouble from '../drawModal/LineDouble.vue';
  27. import GroupModelAdd from '../drawModal/GroupModelAdd.vue';
  28. import {
  29. DndPanel,
  30. SelectionSelect,
  31. Group,
  32. Menu,
  33. MiniMap,
  34. regeister,
  35. Snapshot,
  36. lfJson2Xml,
  37. lfXml2Json,
  38. RectResize,
  39. NodeResize,
  40. GroupNode,
  41. groupModel,
  42. } from "@logicflow/extension";
  43. import "@logicflow/core/dist/style/index.css";
  44. import "@logicflow/extension/lib/style/index.css";
  45. export default {
  46. props: {
  47. lineMenuColor: {
  48. type: String,
  49. required: true
  50. },
  51. fatX: {
  52. type: Number,
  53. required: true
  54. },
  55. fatY: {
  56. type: Number,
  57. required: true
  58. },
  59. nowLook: {
  60. type: null || Number,
  61. required: true
  62. },
  63. needObj: {
  64. type: Object,
  65. required: true
  66. },
  67. needId: {
  68. type: Number || String,
  69. required: true
  70. },
  71. needName: {
  72. type: String,
  73. required: true
  74. },
  75. coolObj: {
  76. type: Object,
  77. required: true
  78. },
  79. // 用于判断是sv还是goose
  80. svOrGoose: {
  81. type: Number,
  82. required: true,
  83. },
  84. searchModule: {
  85. type: Function,
  86. required: true
  87. },//父组件insideModule的方法
  88. cleanAll: {
  89. type: Function,
  90. required: true
  91. },//父组件insideModule的方法
  92. },
  93. setup(props, { emit }) {
  94. let router = useRouter()
  95. let route = useRoute()
  96. const container = ref();
  97. const lf = ref();
  98. let lineColor = ref('#255CE7')
  99. let copyColor = ref('')
  100. let delId = ref('')
  101. let nodeId = ref('')
  102. let copyId = ref('')
  103. let setX = ref(0)
  104. let setY = ref(0)
  105. let needMap = ref([])
  106. let coolId = ref('')
  107. let coolName = ref('')
  108. let copyObj = ref({})//整个模型属性
  109. let modelId = ref("")//模型id
  110. let abModal = ref(false)//功能模态框
  111. let iedType = ref("")//iedtype
  112. let ldModal = ref(false)//linemodel.vue开关
  113. let startTarget = ref({})//开始节点
  114. let endTarget = ref({})//结束节点
  115. let numCase = ref(1)//判断sv还是goose
  116. let startText = ref("")//开始节点名称
  117. let endText = ref("")//结束节点名称
  118. let lineType = ref("")//连接线
  119. let loading = ref(false)
  120. let nodeid = ref("")//节点的id
  121. let fun = ref()//储存父节点传来的函数
  122. let funOne = ref()//储存父节点传来的函数
  123. let groupType = ref(false)//GroupModelAdd.vue组件显示与否
  124. let groupNodeId = ref('') //当前设置ied_type的分组节点ID
  125. let modelIedTypes=ref([]) //当前模型已配置的装置类型
  126. watch(() => props.lineMenuColor, (newVal) => {
  127. copyColor.value = newVal
  128. })
  129. watch(() => props.fatX, (newVal) => {
  130. if (newVal == 0 || newVal == '') {
  131. setX.value = 0
  132. } else {
  133. setX.value = newVal
  134. }
  135. })
  136. watch(() => props.fatY, (newVal) => {
  137. if (newVal == 0 || newVal == '') {
  138. setY.value = 0
  139. } else {
  140. setY.value = newVal
  141. }
  142. })
  143. // watch(() => props.needObj, (newVal) => {
  144. // coolObj.value = newVal
  145. // })
  146. watch(() => props.needId, (newVal) => {
  147. coolId.value = newVal
  148. })
  149. watch(() => props.needName, (newVal) => {
  150. coolName.value = newVal
  151. })
  152. watch(() => props.coolObj, (newVal) => {
  153. if (route.query.modelid != '' && route.query.modelid != null && route.query.modelid != undefined) {
  154. return
  155. } else {
  156. loading.value = true//打开加载动画
  157. copyObj.value = newVal
  158. modelId.value = copyObj.value.id//模型id
  159. setTimeout(() => {
  160. cid.getModelInfo({ id: copyObj.value.id, pageno: 1, pagesize: 20 }).then(res => {
  161. modelIedTypes.value = res.data[0].ied_types!=null ? res.data[0].ied_types.split(","):[]
  162. if (res.data[0].relation_json == null || res.data[0].relation_json == '') return;
  163. const origiondata = JSON.parse(res.data[0].relation_json)
  164. lf.value.render(origiondata);//渲染模型图
  165. loading.value = false//关闭加载动画
  166. for (let index = 0; index < origiondata.edges.length; index++) {
  167. const element = origiondata.edges[index];
  168. if (element.properties != null && element.properties["issv"] === 'SV') {
  169. let lineStyle = lf.value.getEdgeModelById(element.id)//.getEdgeStyle();
  170. // console.log(lineStyle)
  171. lineStyle.setProperties({ svEdge: { stroke: 'orange' } })
  172. }
  173. }
  174. })
  175. }, 2000);
  176. }
  177. }, {
  178. deep: true
  179. })
  180. watch(() => props.svOrGoose, (newVal) => {
  181. numCase.value = newVal
  182. })
  183. function blue() {
  184. lf.value.setTheme({
  185. baseEdge: {
  186. stroke: '#255CE7',
  187. strokeWidth: 2,
  188. },
  189. });//设置连接线为蓝色
  190. }
  191. function orange() {
  192. lf.value.setTheme({
  193. svEdge: {
  194. stroke: 'orange',
  195. strokeWidth: 2,
  196. },
  197. });//设置连接线为橙色
  198. }
  199. function delLine() {
  200. if (delId.value!="") {
  201. lf.value.deleteEdge(delId.value)//删除选择的连接线
  202. delId.value = ""
  203. }
  204. if (nodeId.value!="") {
  205. lf.value.deleteNode(nodeId.value)//删除节点
  206. nodeId.value = ""
  207. }
  208. }
  209. function saveLine() {
  210. // lf.value.getSnapshot()//保存为图片
  211. //console.log(JSON.stringify(lf.value.getGraphData()))
  212. const xml = lfJson2Xml(lf.value.getGraphData());
  213. const data = JSON.stringify(lf.value.getGraphData())
  214. if (modelId.value != undefined && modelId.value != null && modelId.value != '') {
  215. cid.saveMap(
  216. {
  217. id: modelId.value - 0,
  218. relation_json: data,
  219. }
  220. ).then(res => {
  221. if (res.code == 0) {
  222. ElMessage({
  223. type: "success",
  224. message: "保存成功!",
  225. duration: 2000,
  226. })
  227. if(res.data!=null && res.data!=""){
  228. modelIedTypes.value = res.data.IedTypes!=null ?res.data.IedTypes.split(","):[]
  229. }
  230. } else {
  231. ElMessage({
  232. message: res.msg,
  233. type: "error"
  234. })
  235. }
  236. }).catch(res => {
  237. ElMessage({
  238. message: "操作失败:服务器发生异常",
  239. type: "error"
  240. })
  241. })
  242. } else {
  243. cid.saveMap(
  244. {
  245. id: copyObj.value.id - 0,
  246. relation_json: data,
  247. }
  248. ).then(res => {
  249. if (res.code == 0) {
  250. ElMessage({
  251. type: "success",
  252. message: "保存成功!",
  253. duration: 2000,
  254. })
  255. } else {
  256. ElMessage({
  257. message: res.msg,
  258. type: "error"
  259. })
  260. }
  261. })
  262. }
  263. }
  264. function cleanMap() {
  265. lf.value.clearData()
  266. }
  267. function textColor() {
  268. if (lineColor.value == "#255CE7") {
  269. lf.value.setTheme({
  270. svEdge: {
  271. stroke: "orange",
  272. strokeWidth: 2,
  273. },
  274. });
  275. lineColor.value = 'orange'
  276. } else {
  277. lf.value.setTheme({
  278. baseEdge: {
  279. stroke: "#255CE7",
  280. strokeWidth: 2,
  281. },
  282. });
  283. lineColor.value = '#255CE7'
  284. }
  285. }
  286. function momal() {
  287. lf.value.graphModel.moveNode2Coordinate(copyId.value, setX.value - 0, setY.value - 0, true);
  288. }
  289. function lastRender() {
  290. loading.value = true
  291. modelId.value = route.query.modelid
  292. cid.getModelInfo({ id: modelId.value - 0,is_sys:0, pageno: 1, pagesize: 20 }).then(res => {
  293. modelIedTypes.value = res.data[0].ied_types!=null ? res.data[0].ied_types.split(","):[]
  294. if (res.data[0].relation_json == null || res.data[0].relation_json == '') return;
  295. const origiondata = JSON.parse(res.data[0].relation_json)
  296. lf.value.render(origiondata);
  297. loading.value = false
  298. for (let index = 0; index < origiondata.edges.length; index++) {
  299. const element = origiondata.edges[index];
  300. if (element.properties != null && element.properties["issv"] === 'SV') {
  301. let lineStyle = lf.value.getEdgeModelById(element.id)
  302. lineStyle.setProperties({ svEdge: { stroke: 'orange' } })
  303. }
  304. }
  305. }, { immediate: true })
  306. }
  307. function listMap() {
  308. fun.value = props.searchModule
  309. //funOne.value = props.cleanAll //触发关闭按钮事件
  310. coolId.value = props.needId
  311. coolName.value = props.needName//模型名称
  312. copyObj.value = props.coolObj//需要的模型信息对象
  313. numCase.value = props.svOrGoose//判断sv或者goose类型
  314. copyColor.value = props.lineMenuColor//颜色
  315. setTimeout(() => {
  316. cid.getModelInfo({ id: copyObj.value.id ? copyObj.value.id : route.query.modelid - 0,is_sys:copyObj.value.id?1:2, pageno: 1, pagesize: 20 }).then(res => {
  317. emit("drawCor", res.data)
  318. const filteredArray = res.data[0].ied_type.filter(param => param !== null)
  319. let groups = {
  320. type: "my-group",
  321. label: "分组",
  322. id: "952",
  323. resizable: true,//手动调整大小
  324. foldable: true,//展开收起
  325. children: [],
  326. width: 5,
  327. height: 5,
  328. x: 0,
  329. y: 0,
  330. isShowAnchor: true,//锚点
  331. }
  332. needMap.value = filteredArray.map(item => {
  333. return {
  334. type: 'rect',
  335. text: item.name,
  336. label: item.name,
  337. icon: '',
  338. id: item.id,
  339. properties: {
  340. ied_type: item.code,
  341. id: item.id
  342. },
  343. }
  344. })
  345. needMap.value.push(groups)
  346. // lf.value.register(logicFlows)
  347. lf.value.extension.dndPanel.setPatternItems(needMap.value);
  348. console.log('执行了渲染.....', route.query);
  349. if (route.query.modelid != '' && route.query.modelid != null && route.query.modelid != undefined) {
  350. lastRender()
  351. }
  352. setTimeout(() => {
  353. loading.value = false
  354. }, 1000)
  355. })
  356. }, 1000);
  357. }
  358. onMounted(() => {
  359. lf.value = new LogicFlow({
  360. // 通过选项指定了渲染的容器和需要显示网格
  361. container: container.value,//需要显示画布的容器ref
  362. isSilentMode:false, //仅浏览不可编辑模式,默认不开启
  363. grid: {
  364. size: 1,//同时影响位置精确度。当前设置为1像素级
  365. visible: false,
  366. type: "mesh",
  367. config: {
  368. color: "#ededed",
  369. thickness: 1,
  370. },
  371. },//网格,
  372. //grid: true,
  373. plugins: [DndPanel, SelectionSelect, Group, GroupNode, Menu, MiniMap, Snapshot, RectResize, NodeResize],//全局加载的组件
  374. keyboard: {
  375. enabled: true
  376. },
  377. snapline: true,//辅助线
  378. //edgeTextDraggable: true,//连接线文本可以拖拽
  379. nodeTextEdit:false,
  380. edgeTextEdit:false,
  381. multipleSelectKey:"ctrl",//多选按键:meta(cmd)、shift、alt
  382. })
  383. class SvEdge extends PolylineEdge { }
  384. // 节点Model
  385. class SvEdgeModel extends PolylineEdgeModel {
  386. getEdgeStyle() {
  387. const stl = super.getEdgeStyle()
  388. stl.stroke = 'orange'
  389. return stl
  390. }
  391. }
  392. class GooseEdge extends PolylineEdge { }
  393. // 节点Model
  394. class GooseEdgeModel extends PolylineEdgeModel {
  395. getEdgeStyle() {
  396. const stl = super.getEdgeStyle()
  397. stl.stroke = '#255CE7'
  398. /*
  399. console.log("this.isSelected:",this.isSelected)
  400. if (this.isSelected) {
  401. stl.strokeWidth = 3;
  402. }
  403. */
  404. return stl
  405. }
  406. }
  407. class MyGroup extends GroupNode.view {
  408. }
  409. class MyGroupModel extends GroupNode.model {
  410. initNodeData(data) {
  411. data.text = ""//{"value":"未命名组","x":10,"y":5,"editable":true}
  412. //data.id=(new Date().getTime())+"";
  413. super.initNodeData(data);
  414. this.width = 200;
  415. this.height = 150;
  416. this.foldedWidth = 100;
  417. this.foldedHeight = 100;
  418. }
  419. setAttributes() {
  420. this.resizable = true;
  421. this.foldable = false; //不允许收起来
  422. this.isShowAnchor = false;
  423. }
  424. getNodeStyle() {
  425. const stl = super.getNodeStyle()
  426. stl.strokeDasharray = '4 4'
  427. //stl.stroke="rgb(255,255,255)"
  428. return stl
  429. }
  430. getAnchorStyle(anchorInfo) {
  431. const style = super.getAnchorStyle(anchorInfo);
  432. style.stroke = "rgb(24, 125, 255)";
  433. style.r = 5;
  434. style.hover.r = 8;
  435. style.hover.fill = "rgb(24, 125, 255)";
  436. style.hover.stroke = "rgb(24, 125, 255)";
  437. return style;
  438. }
  439. getTextStyle() {
  440. const style = super.getTextStyle();
  441. style.fontSize = 12;
  442. style.color = "#666"
  443. style.textAlign = "left"
  444. return style;
  445. }
  446. }
  447. lf.value.register({
  448. type: "svEdge",
  449. view: SvEdge,
  450. model: SvEdgeModel,
  451. })
  452. lf.value.register({
  453. type: "baseEdge",
  454. view: GooseEdge,
  455. model: GooseEdgeModel,
  456. })
  457. lf.value.register({
  458. type: "my-group",
  459. model: MyGroupModel,
  460. view: MyGroup,
  461. });
  462. lf.value.setTheme({//设置画布
  463. rect: {
  464. fill: "#FFFFFF",
  465. stroke: "#255CE7",
  466. strokeWidth: 2,
  467. },//放置的元素
  468. snapline: {
  469. stroke: 'black', // 对齐线颜色
  470. strokeWidth: 1, // 对齐线宽度
  471. },
  472. edgeText: {
  473. textWidth: 100,
  474. overflowMode: "default",
  475. fontSize: 18,
  476. background: {
  477. fill: "#FFFFFF",
  478. },
  479. },//连接线w文字样式
  480. outline: {
  481. fill: "transparent",
  482. stroke: "none",//"#949494",
  483. //strokeDasharray: "3,3",
  484. hover: {
  485. stroke: "#949494",
  486. },
  487. },
  488. anchor: {
  489. stroke: "#000000",
  490. fill: "#FFFFFF",
  491. r: 4,
  492. hover: {
  493. fill: "#949494",
  494. fillOpacity: 0.5,
  495. stroke: "#949494",
  496. r: 10,
  497. },
  498. },//锚点样式
  499. baseEdge: {
  500. stroke: "#255CE7",
  501. strokeWidth: 1,
  502. },//连接线颜色
  503. svEdge: {
  504. stroke: "orange",
  505. strokeWidth: 1,
  506. },//连接线颜色
  507. nodeText: {
  508. color: "#255CE7",
  509. overflowMode: "autoWrap",
  510. lineHeight: 1.2,
  511. fontSize: 12,
  512. },//节点内文字样式
  513. });
  514. lf.value.on("edge:add", function (data, e, position) {
  515. if (copyColor.value == '#255CE7') {
  516. blue()
  517. lf.value.changeEdgeType(data.data.id, "baseEdge")
  518. lf.value.setProperties(data.data.id, { 'issv': 'GOOSE' })
  519. }
  520. if (copyColor.value == 'orange') {
  521. orange()
  522. lf.value.changeEdgeType(data.data.id, "svEdge")
  523. lf.value.setProperties(data.data.id, { 'issv': 'SV' })
  524. }
  525. })
  526. lf.value.on('node:click', function (data, e, position) {//传送坐标轴参数到父组件
  527. copyId.value = data.data.id
  528. nodeId.value = data.data.id
  529. if(delId.value!=""){
  530. //恢复原线宽度
  531. lf.value.getEdgeModelById(delId.value).setStyle("strokeWidth",1)
  532. }
  533. delId.value = "" //清除选择的连线ID
  534. setX.value = data.data.x
  535. setY.value = data.data.y
  536. emit("backxy", setX.value, setY.value)
  537. })
  538. // lf.value.on('anchor:drop', function (data, e, position) {//添加线上文字
  539. // if (numCase.value == 0) {
  540. // lf.value.graphModel.updateText(data.edgeModel.id, "SV");
  541. // } else if (numCase.value == 1) {
  542. // lf.value.graphModel.updateText(data.edgeModel.id, "GOOSE");
  543. // }
  544. // })
  545. lf.value.on('node:dbclick', function (data, e, position) {//双击打开弹窗
  546. if(!modelIedTypes.value.includes(data.data.properties.ied_type)){
  547. ElMessage({
  548. type: "info",
  549. message: "当前节点为新节点或装置编码发生更改,请先保存当前模型关系配置"
  550. })
  551. return
  552. }
  553. iedType.value = data.data.properties.ied_type
  554. nodeid.value = data.data.properties.id
  555. delId.value=""
  556. abModal.value = true
  557. })
  558. lf.value.on('edge:dbclick', function (data, e, position) {//双击连接线
  559. nodeId.value = "" //清除选择的节点Id
  560. let start = lf.value.getNodeModelById(data.data.sourceNodeId)//获取连线开始节点
  561. let end = lf.value.getNodeModelById(data.data.targetNodeId)//获取连线结尾节点
  562. if(!modelIedTypes.value.includes(start.properties.ied_type) ||!modelIedTypes.value.includes(end.properties.ied_type)){
  563. ElMessage({
  564. type: "info",
  565. message: "当前关系中存在新节点或装置编码发生更改,请先保存当前模型关系配置"
  566. })
  567. return
  568. }
  569. lineType.value = data.data.properties.issv
  570. startText.value = start.text.value//开始文本
  571. endText.value = end.text.value//结束文本
  572. startTarget.value = start.properties
  573. endTarget.value = end.properties
  574. ldModal.value = true
  575. })
  576. lf.value.on('node:mousemove', function (data, e) {//传递坐标轴参数到父组件
  577. setX.value = data.data.x
  578. setY.value = data.data.y
  579. emit("backxy", setX.value, setY.value)
  580. })
  581. lf.value.on('edge:click', function (data, e, position) {//解决点击连接线问题
  582. if(delId.value!=""){
  583. //恢复原线宽度
  584. const oldline=lf.value.getEdgeModelById(delId.value)
  585. if(oldline!=null) oldline.setStyle("strokeWidth",1)
  586. }
  587. delId.value = data.data.id
  588. //当前点击线设置为粗线
  589. lf.value.getEdgeModelById(data.data.id).setStyle("strokeWidth",3)
  590. nodeId.value = "" //清除选择的节点Id
  591. })
  592. //当将节点托入画布后触发事件
  593. lf.value.on('node:dnd-add', function (nodedata) {
  594. if (nodedata.data.type == 'my-group') {
  595. // 添加的是分组节点,需要打开一个窗口让用户设置该节点的ied_type并保存到properties中
  596. let ied_type = "TMP"
  597. const g = lf.value.getNodeModelById(nodedata.data.id);
  598. g.setProperties({
  599. ied_type: ied_type,
  600. id: '-99' //分组的装置类型id固定为-99
  601. });
  602. groupNodeId.value = nodedata.data.id
  603. groupType.value = true
  604. }
  605. })
  606. lf.value.on("node:resize", function (data) {
  607. //if(data.oldNodeSize.type!="my-group") return;
  608. })
  609. //画布点击事件
  610. lf.value.on("blank:click", function (data) {
  611. if(delId.value!=""){
  612. //恢复原线宽度
  613. lf.value.getEdgeModelById(delId.value).setStyle("strokeWidth",1)
  614. }
  615. })
  616. lf.value.render();
  617. listMap()
  618. })
  619. function abilityBack(data) {
  620. abModal.value = data
  621. }
  622. function lineBack(data) {
  623. ldModal.value = data
  624. }
  625. // GroupModelAdd.vue返回状态
  626. function groupBack(data) {
  627. groupType.value = data.show
  628. //设置窗口关闭时
  629. if (!data.show && data.ied_type != '') {
  630. //更新分组的装置类型编码属性ied_type
  631. const g = lf.value.getNodeModelById(data.groupNodeId);
  632. g.setProperties({
  633. ied_type: data.ied_type,
  634. });
  635. } else {
  636. //未设置装置编码,自动删除
  637. lf.value.deleteNode(data.groupNodeId)
  638. }
  639. }
  640. //切换选区模式
  641. function selectMode(state){
  642. if(state){
  643. //开启
  644. lf.value.extension.selectionSelect.openSelectionSelect();
  645. }else{
  646. //关闭
  647. lf.value.extension.selectionSelect.closeSelectionSelect();
  648. lf.value.clearSelectElements();//清除已框选的节点及边
  649. }
  650. }
  651. //设置选择节点的对齐方式
  652. //还有BUG...
  653. function onAlignChange(v){
  654. const elements = lf.value.getSelectElements(false);
  655. if(elements.nodes.length<2){
  656. ElMessage({
  657. type: "info",
  658. message: "至少需要选中2个节点"
  659. })
  660. return
  661. }
  662. let calMax=function(){
  663. let resultMax={"left":0,"right":0,"top":0,"bottom":0,"width":0,"height":0}
  664. elements.nodes.forEach(ele => {
  665. let size=ele.properties.nodeSize
  666. if(size==null) size={"width":100,"height":80} //默认高宽
  667. if(resultMax.left==0 || ele.x<resultMax.left){
  668. //获取最小的left
  669. resultMax.left = ele.x
  670. }
  671. if(resultMax.right==0 || (ele.x+size.width)>resultMax.right){
  672. //获取最大的right
  673. resultMax.right = ele.x+size.width
  674. }
  675. if(resultMax.top==0 || ele.y<resultMax.top){
  676. //获取最小的topt
  677. resultMax.top = ele.y
  678. }
  679. if(resultMax.top==0 || (ele.y+size.height)>resultMax.top){
  680. //获取最大的topt
  681. resultMax.bottom = ele.y+size.height
  682. }
  683. if(resultMax.width==0 || size.width>resultMax.width){
  684. resultMax.width = size.width
  685. }
  686. if(resultMax.height==0 || size.height>resultMax.height){
  687. resultMax.height = size.height
  688. }
  689. });
  690. return resultMax
  691. }
  692. const xyz=calMax()
  693. switch(v){
  694. case "align_left":
  695. //位置调整
  696. elements.nodes.forEach(ele => {
  697. const size=ele.properties.nodeSize
  698. //lf.value.getNodeModelById(ele.id).moveTo(xyz.left,ele.y)
  699. lf.value.graphModel.moveNode2Coordinate(ele.id,xyz.left,ele.y,false)
  700. })
  701. break;
  702. case "align_right":
  703. elements.nodes.forEach(ele => {
  704. const size=ele.properties.nodeSize
  705. //lf.value.getNodeModelById(ele.id).moveTo(xyz.right-size.width,ele.y)
  706. lf.value.graphModel.moveNode2Coordinate(ele.id,xyz.right-size.width,ele.y,false)
  707. })
  708. break;
  709. case "align_center":
  710. break;
  711. case "align_top":
  712. elements.nodes.forEach(ele => {
  713. //const size=ele.properties.nodeSize
  714. lf.value.graphModel.moveNode2Coordinate(ele.id,ele.x,xyz.top,false)
  715. })
  716. break;
  717. case "align_bottom":
  718. elements.nodes.forEach(ele => {
  719. const size=ele.properties.nodeSize
  720. lf.value.graphModel.moveNode2Coordinate(ele.id,ele.x,xyz.bottom-size.height,false)
  721. })
  722. break;
  723. case "size_samewidth":
  724. elements.nodes.forEach(ele => {
  725. lf.value.getNodeModelById(ele.id).width=xyz.width;
  726. })
  727. break;
  728. case "size_sameheight":
  729. elements.nodes.forEach(ele => {
  730. lf.value.getNodeModelById(ele.id).height=xyz.height;
  731. })
  732. break;
  733. default:
  734. break;
  735. }
  736. }
  737. onBeforeUnmount(() => {
  738. // lf.value.remove()
  739. // coolObj.value = {}
  740. router.push("/home/setting")
  741. })
  742. return {
  743. container,
  744. lf,
  745. textColor,
  746. lineColor,
  747. blue,
  748. orange,
  749. delLine,
  750. saveLine,
  751. cleanMap,
  752. selectMode,
  753. onAlignChange,
  754. nodeId,
  755. copyColor,
  756. copyId,
  757. setX,
  758. setY,
  759. momal,
  760. needMap,
  761. coolId,
  762. coolName,
  763. copyObj,//模型整个数据
  764. modelId,//模型id
  765. abModal,//功能模态框
  766. iedType,//模型属性
  767. abilityBack,//abilitymodal.vue返回模态框开关状态
  768. ldModal,//lineDouble.vue模态框开关
  769. startTarget,//开始节点
  770. endTarget,//结束节点
  771. lineBack,//LineDouble.vue返回模态框开关状态
  772. numCase,//判断是sv还是goose,0为sv,1为goose
  773. startText,//开始节点名称
  774. endText,//结束节点名称
  775. lineType,//连接线
  776. lastRender,//路由跳转的渲染
  777. loading,
  778. nodeid,//节点的id
  779. fun,//储存父节点传来的函数
  780. listMap,//组件初始化
  781. funOne,//储存父节点传来的函数
  782. groupType,//GroupModelAdd.vue组件显示与否
  783. groupNodeId,
  784. groupBack,// GroupModelAdd.vue返回状态
  785. }
  786. },
  787. components: {
  788. AbilityModal,//功能模态框
  789. LineDouble,//连接线模态框
  790. GroupModelAdd,//分组专属模态框
  791. }
  792. }
  793. </script>
  794. <style scoped>
  795. .container {
  796. width: 100%;
  797. height: calc(100vh - 18rem);
  798. /* overflow: auto; */
  799. }
  800. :deep(.lf-element-text) {
  801. color: black;
  802. }
  803. /* :deep(.lf-dndpanel){
  804. w
  805. } */
  806. /* :deep(.lf-basic-shape) {
  807. width: 150px;
  808. height: 150px;
  809. } */
  810. </style>