SBaseEditScene.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. /*
  2. * *********************************************************************************************************************
  3. *
  4. * !!
  5. * .F88X
  6. * X8888Y
  7. * .}888888N;
  8. * i888888N; .:! .I$WI:
  9. * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
  10. * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
  11. * +888888N; .8888888Y "&&8Y.}8,
  12. * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
  13. * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
  14. * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
  15. * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
  16. * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
  17. * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
  18. * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
  19. * .:R888888I
  20. * .&888888I Copyright (c) 2016-2020. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import { SGraphDeleteListCommand, SGraphEditScene, SGraphEdit } from "./../edit/"
  27. import { SMouseEvent } from "@persagy-web/base/lib";
  28. import { SArrowStyleType, SPoint, SRect } from '@persagy-web/draw';
  29. import { SItemStatus, SRectSelectItem } from '@persagy-web/big/lib';
  30. import { SGraphItem, SGraphSelectContainer, SOrderSetType } from "@persagy-web/graph/lib/";
  31. import { uuid } from "./until";
  32. import { SBaseArrow, SBaseEquipment, SBaseExpainEdit, SBasePipeUninTool, SBasePipe } from "./"
  33. import { PTopoParser } from "./../persagy-edit/"
  34. import { SBaseArrowPolyEdit } from './items/SBaseArrowPolyEdit';
  35. /**
  36. * big-edit 场景
  37. *
  38. * @author 韩耀龙 <han_yao_long@163.com>
  39. */
  40. export class SBaseEditScene extends SGraphEditScene {
  41. /** 图例节点 */
  42. Nodes: any = []; // 图例节点,所有与工程信息化相关的图例(图标类型与区域)
  43. /** 图例节点 */ // 与工程信息无关的标识对象(增加文本注释,图上的图片说明)
  44. Markers: any = [];
  45. /** 管线对象 */
  46. Relations: any = [];
  47. /** 复制的对象 */
  48. copyString: any[] = [];
  49. /** 选中的对象 */
  50. grabItem: null | SGraphEdit | SGraphItem = null;
  51. /**
  52. * 构造函数
  53. *
  54. */
  55. constructor() {
  56. super()
  57. } // Constructor
  58. /**
  59. * 新增基础类注释
  60. *
  61. * @param event 鼠标事件参数
  62. */
  63. addExplainItem(event: SMouseEvent): void {
  64. const data = {
  65. /** 名称 */
  66. name: '基础注释文本',
  67. /** 图标 */
  68. type: "Text",
  69. /** 位置 */
  70. pos: { x: event.x, y: event.y },
  71. /** 由应用自己定义 */
  72. properties: {
  73. type: "BaseExplain",
  74. },
  75. style: {
  76. default: {
  77. text: '请在右侧属性栏输入文字!',
  78. color: "#646c73",
  79. font: 14,
  80. backgroundcolor: "#f7f9facc",
  81. }
  82. }
  83. };
  84. const item = new SBaseExpainEdit(null, data);
  85. item.moveTo(event.x, event.y);
  86. item.selectable = true;
  87. item.moveable = true;
  88. this.addItem(item);
  89. this.grabItem = null;
  90. item.connect("onContextMenu", this, this.getItem);
  91. this.finishCreated(item);
  92. } // Function addExplainItem()
  93. /**
  94. * 新增基础箭头(折线)
  95. *
  96. * @param event 鼠标事件
  97. */
  98. addPolyLineArrow(event: SMouseEvent): void {
  99. const data = {
  100. name: '基础箭头',
  101. type: "Arrow",
  102. pos: { x: 0, y: 0 },
  103. properties: {
  104. type: "BaseArrow",
  105. },
  106. style: {
  107. outLine: [{ x: event.x, y: event.y }],
  108. begin: SArrowStyleType.None, //开端箭头样式
  109. end: SArrowStyleType.None, //结尾箭头样式
  110. isMove: true, //是否可以移动
  111. default: {}
  112. }
  113. };
  114. const item = new SBaseArrow(null, data);
  115. item.status = SItemStatus.Create;
  116. item.selectable = true;
  117. this.addItem(item);
  118. this.grabItem = item;
  119. item.connect("finishCreated", this, this.finishCreated);
  120. item.connect("onContextMenu", this, this.getItem);
  121. if (this.view) {
  122. this.view.update();
  123. }
  124. } // Function addPolyLineArrow()
  125. /**
  126. * 新增基础箭头(多边形)
  127. *
  128. * @param event 鼠标事件
  129. */
  130. addPolygonArrow(event: SMouseEvent): void {
  131. const data = {
  132. /** 名称 */
  133. name: '多边形箭头',
  134. /** 图标(Image),线类型(Line) */
  135. type: "ArrowPolygon",
  136. /** 缩放比例(Image),线类型(Line) */
  137. scale: { x: 1, y: 1, z: 1 },
  138. /** 缩放比例(Image),线类型(Line) */
  139. rolate: { x: 0, y: 0, z: 0 },
  140. /** 位置 */
  141. pos: { x: 0, y: 0 },
  142. /** 由应用自己定义 */
  143. properties: {
  144. type: "BaseArrowPolygon" // 自定义类型用于区分mark与node
  145. },
  146. style: {
  147. line: [{ x: event.x, y: event.y }],
  148. default: {
  149. }
  150. }
  151. };
  152. const item = new SBaseArrowPolyEdit(null, data);
  153. item.status = SItemStatus.Create;
  154. item.selectable = true;
  155. this.addItem(item);
  156. this.grabItem = item;
  157. item.connect("finishCreated", this, this.finishCreated);
  158. item.connect("onContextMenu", this, this.getItem);
  159. if (this.view) {
  160. this.view.update();
  161. }
  162. } // Function addPolygonArrow()
  163. /**
  164. * 添加基本设备 item
  165. *
  166. * @param event 鼠标事件
  167. * @param legendObj 图例样式
  168. */
  169. addEuqipment(event: SMouseEvent, legendObj: any): void {
  170. const data = {
  171. /** 名称 */
  172. name: '基础设备',
  173. num: 1,
  174. size: { width: 50, height: 50 },
  175. /** 图标 (Image),线类型 (Line) */
  176. type: "Image",
  177. /** 位置 */
  178. pos: { x: event.x, y: event.y },
  179. /** 由应用自己定义 */
  180. properties: {
  181. type: "BaseEquipment",
  182. },
  183. style: {
  184. default: {
  185. strokecolor: "#c0ccda",
  186. url: require('./../../../assets/images/equip/' + legendObj.url),
  187. }
  188. }
  189. }
  190. const item = new SBaseEquipment(null, data);
  191. item.status = SItemStatus.Create;
  192. this.addItem(item);
  193. item.selectable = true;
  194. item.moveable = true;
  195. this.grabItem = item;
  196. this.finishCreated(item)
  197. item.connect("onContextMenu", this, this.getItem);
  198. if (this.view) {
  199. this.view.update();
  200. }
  201. } // Function addEuqipment()
  202. /**
  203. * 新增管道
  204. *
  205. * @param event 鼠标事件
  206. */
  207. addBasePipe(event: SMouseEvent) {
  208. const anc = this.clickIsAnchor(event);
  209. if (anc) {
  210. const p = anc.mapToScene(0, 0)
  211. anc.isConnected = true;
  212. event.x = p.x;
  213. event.y = p.y;;
  214. };
  215. const data = {
  216. name: '管道',
  217. lineType: '',
  218. pointList: [{ x: event.x, y: event.y }],
  219. properties: {
  220. type: "BasePipe",
  221. },
  222. style: {
  223. default: {
  224. }
  225. }
  226. };
  227. const item = new SBasePipe(null, data);
  228. item.status = SItemStatus.Create;
  229. item.selectable = true;
  230. this.addItem(item);
  231. this.grabItem = item;
  232. // 起始锚点
  233. item.startAnchor = anc;
  234. if (anc) {
  235. anc.parent?.connect('changePos', item, item.changePos)
  236. item.anchor1ID = anc.id;
  237. item.node1Id = anc.parent.id;
  238. }
  239. item.connect("finishCreated", this, this.finishCreated);
  240. item.connect("onContextMenu", this, this.getItem);
  241. if (this.view) {
  242. this.view.update();
  243. }
  244. } // Function addBasePipe()
  245. /**
  246. * 添加基本管道联通器
  247. *
  248. * @param event 鼠标事件
  249. * @param cmd 命令
  250. */
  251. addPipeUninTool(event: SMouseEvent, cmd: string): void {
  252. const cmdList = {
  253. 'wantou': 2,
  254. 'santong': 3,
  255. 'sitong': 4,
  256. }
  257. const data = {
  258. /** 名称 */
  259. name: '基础管道接头',
  260. /** 图标 (Image),线类型 (Line) */
  261. type: "Image",
  262. /** 位置 */
  263. pos: { x: event.x, y: event.y },
  264. /** 由应用自己定义 */
  265. properties: {
  266. type: "BasePipeUninTool",
  267. },
  268. style: {
  269. uninToolType: cmdList[cmd] ? cmdList[cmd] : 2, //2,3,4 分别分二头连接器、三头连接器、四头连接器
  270. default: {
  271. strokecolor: "#c0ccda",
  272. }
  273. }
  274. };
  275. const item = new SBasePipeUninTool(null, data);
  276. item.status = SItemStatus.Create;
  277. item.selectable = true;
  278. item.moveable = true;
  279. this.addItem(item);
  280. this.grabItem = item;
  281. this.finishCreated(item)
  282. item.connect("onContextMenu", this, this.getItem);
  283. if (this.view) {
  284. this.view.update();
  285. }
  286. } // Function addPipeUninTool()
  287. /**
  288. * 重做
  289. */
  290. redo(): void {
  291. if (this.grabItem && this.grabItem instanceof SGraphEdit) {
  292. this.grabItem.redo()
  293. } else {
  294. this.undoStack.redo();
  295. }
  296. } // Function redo()
  297. /**
  298. * 撤销
  299. */
  300. undo(): void {
  301. if (this.grabItem && this.grabItem instanceof SGraphEdit) {
  302. this.grabItem.undo()
  303. } else {
  304. this.undoStack.undo();
  305. }
  306. } // Function undo()
  307. /**
  308. * 删除
  309. *
  310. * @return 删除的图例
  311. */
  312. deleteItem(): any {
  313. if (this.selectContainer.count == 0) {
  314. return []
  315. }
  316. let itemList = this.selectContainer.itemList;
  317. // 推入 undo/redo 栈
  318. this.undoStack.push(new SGraphDeleteListCommand(this, [...itemList]))
  319. itemList.forEach((element: any) => {
  320. this.removeItem(element)
  321. });
  322. if (this.view) {
  323. this.view.update()
  324. }
  325. return itemList
  326. } // Function deleteItem()
  327. /**
  328. * 框选
  329. */
  330. addRectSelect(event: SMouseEvent): void {
  331. let point = new SPoint(event.x, event.y);
  332. let rect = new SRectSelectItem(null, point);
  333. this.addItem(rect);
  334. this.grabItem = rect;
  335. } // Function addRectSelect()
  336. /**
  337. * 计算框选交集
  338. *
  339. * @param ctrl 是否点击ctrl
  340. */
  341. groupSelect(ctrl: boolean) {
  342. // if (!ctrl) {
  343. // this.selectContainer.clear()
  344. // }
  345. if (this.grabItem instanceof SRectSelectItem) {
  346. const rect = this.grabItem.boundingRect();
  347. this.arrToSelect(this.root.children, rect)
  348. }
  349. } // Function groupSelect()
  350. /**
  351. * 选中item:框选
  352. *
  353. * @param arr 实例数组
  354. * @param rect 框选矩形区域
  355. */
  356. private arrToSelect(arr: SGraphItem[], rect: SRect) {
  357. if (Array.isArray(arr) && arr.length) {
  358. arr.forEach(t => {
  359. if (!(t instanceof SGraphSelectContainer) && t.parent) {
  360. let temp = t.boundingRect();
  361. let lefttop = t.mapToScene(temp.left, temp.top)
  362. let rightbottom = t.mapToScene(temp.right, temp.bottom)
  363. let r = new SRect(lefttop, rightbottom)
  364. if (rect.isIn(r)) {
  365. this.selectContainer.toggleItem(t)
  366. }
  367. }
  368. })
  369. }
  370. } // Function arrToSelect()
  371. /////////////////////////////////////////////////////////////////////
  372. // 鼠标事件
  373. /**
  374. * 鼠标左键按下
  375. *
  376. * @param event 鼠标事件参数
  377. */
  378. onMouseDown(event: SMouseEvent): any {
  379. if (!super.onMouseDown(event) && 1 == event.buttons) {
  380. this.addRectSelect(event);
  381. }
  382. } // Function onMouseDown()
  383. /**
  384. * 鼠标抬起
  385. *
  386. * @param event 鼠标事件参数
  387. */
  388. onMouseUp(event: SMouseEvent): boolean {
  389. console.log('-----baseEditScene');
  390. if (this.grabItem) {
  391. // 鼠标抬起时,如果grabItem为框选则删除框选item
  392. if (this.grabItem instanceof SRectSelectItem) {
  393. this.removeItem(this.grabItem);
  394. this.groupSelect(false);
  395. this.grabItem = null;
  396. if (this.view) {
  397. this.view.update()
  398. }
  399. console.log(1);
  400. return true;
  401. }
  402. console.log(2);
  403. return this.grabItem.onMouseUp(event);
  404. }
  405. console.log(3);
  406. return super.onMouseUp(event)
  407. } // Function onMouseUp()
  408. /**
  409. * 复制
  410. */
  411. copy(): void {
  412. const itemList = this.save(false);
  413. if (itemList) {
  414. // 生成复制字符串
  415. // 删除对应得id
  416. itemList.markers.map((item: any) => {
  417. delete item.id;
  418. delete item.graphId;
  419. delete item.markerId;
  420. return item
  421. });
  422. itemList.nodes.map((item: any) => {
  423. delete item.id;
  424. delete item.graphId;
  425. delete item.markerId;
  426. return item
  427. });
  428. itemList.relations.map((item: any) => {
  429. delete item.id;
  430. delete item.graphId;
  431. delete item.markerId;
  432. return item
  433. });
  434. this.copyString = itemList
  435. // 获取input dom
  436. const input = document.createElement('input');
  437. input.setAttribute('id', 'COPYINPUT')
  438. input.value = JSON.stringify(this.copyString)
  439. sessionStorage.setItem("copyString", input.value);
  440. document.body.appendChild(input);
  441. input.select()
  442. document.execCommand('copy');
  443. input.style.display = 'none';
  444. console.log(input.value, Date.now());
  445. document.body.removeChild(input)
  446. }
  447. } // Function copy()
  448. /**
  449. * 粘贴
  450. */
  451. paste(): void {
  452. const copyList = JSON.parse(JSON.stringify(this.copyString));
  453. console.log('copyList', copyList)
  454. const parserData = new PTopoParser();
  455. parserData.parseData(copyList);
  456. parserData.markers.forEach((item: SGraphEdit) => {
  457. item.selectable = true;
  458. item.moveable = true;
  459. if (this.view) {
  460. item.pos.x += 10 / this.view.scale
  461. item.pos.y += 10 / this.view.scale
  462. }
  463. this.addItem(item);
  464. });
  465. this.view ? this.view.update() : '';
  466. } // Function paste()
  467. /**
  468. * 图例置顶、置底
  469. *
  470. * @parm type 设置类型
  471. */
  472. setOrder(type: string) {
  473. this.selectContainer.setOrder(SOrderSetType.[type])
  474. }
  475. /**
  476. * 获取item (常用与场景外的调用F)
  477. *
  478. * @params isAll 是否为全部item数据
  479. * @return obj 返回保存的数据接口
  480. */
  481. save(isAll: boolean = true): any {
  482. } // Function save()
  483. } // Class SBaseEditScene