DrawFlow.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. <!--
  2. * @author 肖阳
  3. * @time 2020-9-10
  4. * @dec 生成流程绘制 基本节点(审批 抄送)组装逻辑
  5. * 组装
  6. -->
  7. <script>
  8. import AddNodeBtn from "@/components/DrawFlow/src/components/AddNodeBtn";
  9. import RowFactory from "@/components/DrawFlow/src/components/DrawRow/FactoryRow";
  10. // import EventBus from "@/components/ApprovalProcess/ProcessDesign/components/EventBus/EventBus";
  11. import {
  12. RowNode,
  13. ConditionNode,
  14. CopyNode
  15. } from "./components/NodeConfigFactory/NodeFactory";
  16. import { deepClone } from "@/common/utils";
  17. import FlowFactory from "./components/factory";
  18. import { HashCode, transToTreeDat } from "./utils";
  19. import FlowNode from "@/components/DrawFlow/src/components/DrawRow/FlowNode";
  20. export default {
  21. name: "FactoryDrawFlow",
  22. components: {
  23. AddNodeBtn,
  24. FlowNode
  25. },
  26. created() {
  27. this.init();
  28. // this.creatBusNodeChange(); // 可用事件派发
  29. },
  30. props: {
  31. FlowConfig: {
  32. type: Array,
  33. default() {
  34. return [];
  35. }
  36. }
  37. },
  38. data() {
  39. return {
  40. rectTypeDic: {
  41. 1: "审批节点",
  42. 2: "规则节点",
  43. 3: "抄送人",
  44. 4: "开始节点"
  45. },
  46. isColList: ["3", "5"],
  47. selfConfig: null,
  48. currentNode: null,
  49. //缓存数据
  50. cacheData: null
  51. };
  52. },
  53. methods: {
  54. // 节点数据变化事件
  55. nodeChange(node) {
  56. this.currentNode.title = node.title;
  57. this.selfConfig.forEach(i => {
  58. if (i.id === this.currentNode.id) {
  59. i.data = node.data;
  60. i.title = node.title;
  61. }
  62. });
  63. this.$forceUpdate();
  64. },
  65. /**
  66. * 添加条件框
  67. */
  68. addBranch(node) {
  69. let newNode = new CopyNode(node[0]);
  70. this.selfConfig = this.selfConfig.concat([newNode]);
  71. },
  72. creatBusNodeChange() {
  73. // EventBus.$on("nodeChange", this.nodeChange);
  74. },
  75. /**
  76. * 获取传参数据结构
  77. */
  78. getResData() {
  79. let list = JSON.parse(JSON.stringify(this.selfConfig));
  80. this.transformTree(list);
  81. console.log(list, "list");
  82. return list;
  83. },
  84. /**
  85. * 初始化 数据私有化
  86. */
  87. init() {
  88. this.selfConfig = deepClone(this.FlowConfig);
  89. },
  90. /**
  91. * @param data 源数组一维数组
  92. * @requires tree 二维数组
  93. */
  94. transformTree(data) {
  95. return transToTreeDat(data);
  96. },
  97. clickSelectBox(nextNode) {
  98. let { node, selfConfig } = this.getNodeFactory(nextNode);
  99. this.selfConfig = selfConfig.concat(node);
  100. },
  101. /**
  102. * 根据isRow去判断row或者rol
  103. */
  104. getNodeFactory(nextNode) {
  105. if (!nextNode.isRow) {
  106. let { node, selfConfig } = this.getColNode(nextNode);
  107. return { node, selfConfig };
  108. } else {
  109. let { node, selfConfig } = this.getRowNode(nextNode);
  110. return { node, selfConfig };
  111. }
  112. },
  113. /**
  114. * 获取row节点
  115. */
  116. getRowNode(nextNode) {
  117. let node = [new RowNode(nextNode)];
  118. let selfConfig = this.repickArr(node[0]);
  119. // this.clickNode(node[0]);
  120. return { node, selfConfig };
  121. },
  122. /**
  123. * 获取col节点
  124. */
  125. getColNode(nextNode) {
  126. let groupId = HashCode();
  127. let node = [
  128. new ConditionNode({ groupId, ...nextNode }),
  129. new ConditionNode({ groupId, ...nextNode })
  130. ];
  131. let repickConfig = {
  132. groupId: node[0].groupPid,
  133. id: node[0].id
  134. };
  135. let selfConfig = this.repickArr(repickConfig);
  136. this.locationScroll();
  137. return { node, selfConfig };
  138. },
  139. /**
  140. * 定位滚动条
  141. */
  142. locationScroll() {
  143. // window.location.hash = ".bottom-right-cover-line";
  144. let el = document.getElementsByClassName("dingflow-design")[0];
  145. setTimeout(() => {
  146. el.scrollLeft = el.scrollWidth - el.clientWidth + 340;
  147. }, 0);
  148. },
  149. /**
  150. * 重定位数组
  151. */
  152. repickArr(repickConfig) {
  153. let selfConfig = JSON.parse(JSON.stringify(this.selfConfig));
  154. selfConfig.forEach(i => {
  155. if (i.isRow) {
  156. if (i.groupId === repickConfig.groupId) {
  157. i.groupId = repickConfig.id;
  158. }
  159. } else {
  160. if (i.groupPid === repickConfig.groupId) {
  161. i.groupPid = repickConfig.id;
  162. }
  163. }
  164. });
  165. return selfConfig;
  166. },
  167. // 点击节点
  168. clickNode(nodeConfig) {
  169. this.currentNode = nodeConfig;
  170. this.$emit("clickNode", nodeConfig);
  171. },
  172. //点击关闭节点
  173. closeNode(node) {
  174. let repickConfig = {};
  175. if (node.isRow) {
  176. repickConfig.groupId = node.groupId;
  177. repickConfig.id = node.id;
  178. let selfConfig = JSON.parse(JSON.stringify(this.selfConfig));
  179. console.log("selfConfigselfConfigselfConfig", selfConfig);
  180. this.selfConfig = this.deleteNode(selfConfig, node);
  181. this.repickDeleteArr(repickConfig);
  182. } else {
  183. this.deleteColNode(node);
  184. }
  185. },
  186. // 删除节点
  187. deleteNode(selfConfig, node) {
  188. selfConfig = selfConfig.map(i => i.id !== node.id && i).filter(Boolean);
  189. return selfConfig;
  190. },
  191. //单独删除col下node
  192. deleteColNode(node) {
  193. let selfConfig = JSON.parse(JSON.stringify(this.selfConfig));
  194. let nodeArr = selfConfig.filter(
  195. i => i.groupId === node.groupId && !i.isRow
  196. );
  197. let deleteArr = [];
  198. let repickConfig;
  199. if (nodeArr.length > 2) {
  200. //递归删除所有关联子节点
  201. deleteArr = [node];
  202. this.deleteLoop(selfConfig, node, deleteArr);
  203. repickConfig = {
  204. id: node.id,
  205. groupId: node.groupId
  206. };
  207. } else {
  208. //删除整个group
  209. let allCol = selfConfig
  210. .map(i => i.groupId === node.groupId && !i.isRow && i)
  211. .filter(Boolean);
  212. deleteArr = allCol;
  213. allCol.forEach(i => {
  214. this.deleteLoop(selfConfig, i, deleteArr);
  215. });
  216. repickConfig = {
  217. id: node.groupId,
  218. groupId: node.groupPid
  219. };
  220. }
  221. deleteArr.forEach(i => {
  222. selfConfig = this.deleteNode(selfConfig, i);
  223. });
  224. this.selfConfig = selfConfig;
  225. this.repickDeleteArr(repickConfig);
  226. return selfConfig;
  227. },
  228. // 循环遍历删除组下关联节点
  229. deleteLoop(selfConfig, node, deleteArr) {
  230. console.log(selfConfig, node, "selfConfig");
  231. let currentDeleteArr = selfConfig.filter(i => {
  232. if (i.isRow) {
  233. return i.groupId === node.id;
  234. } else {
  235. return i.groupPid === node.id;
  236. }
  237. });
  238. if (currentDeleteArr.length) {
  239. currentDeleteArr.forEach(i => {
  240. deleteArr.push(i);
  241. this.deleteLoop(selfConfig, i, deleteArr);
  242. });
  243. } else {
  244. return;
  245. }
  246. },
  247. //判断是否是row
  248. judgeNodeIsRow(node) {
  249. return node.isRow;
  250. },
  251. //删除后重组数组
  252. repickDeleteArr(repickConfig) {
  253. let selfConfig = JSON.parse(JSON.stringify(this.selfConfig));
  254. selfConfig.forEach(i => {
  255. if (i.isRow && i.groupId === repickConfig.id) {
  256. i.groupId = repickConfig.groupId;
  257. } else if (!i.isRow && i.groupPid === repickConfig.id) {
  258. i.groupPid = repickConfig.groupId;
  259. }
  260. });
  261. this.selfConfig = selfConfig;
  262. console.log(selfConfig, repickConfig, "groupPid");
  263. },
  264. //绘制body
  265. drawBody(h, node) {
  266. if (node.childNode) {
  267. return FlowFactory.getFactory.bind(this, h, node.childNode)();
  268. } else {
  269. return <div></div>;
  270. }
  271. }
  272. },
  273. destroyed() {
  274. // EventBus.$off("nodeChange");
  275. },
  276. render(h) {
  277. // this.init();
  278. let FlowConfig = JSON.parse(JSON.stringify(this.selfConfig));
  279. FlowConfig = this.transformTree(FlowConfig);
  280. this.cacheData = FlowConfig;
  281. const root = JSON.parse(JSON.stringify(this.selfConfig[0]));
  282. return (
  283. <div class="design-engine">
  284. <div class="dingflow-design">
  285. <div class="ie-polyfill-container">
  286. <div class="box-scale" id="box-scale">
  287. {RowFactory.nodeWrapRender.bind(this, h, root)()}
  288. {this.drawBody(h, FlowConfig[0])}
  289. <div class="end-node">
  290. <div class="end-node-circle"></div>
  291. <div class="end-node-text">流程结束</div>
  292. </div>
  293. </div>
  294. </div>
  295. </div>
  296. </div>
  297. );
  298. }
  299. };
  300. </script>
  301. <style scoped lang="less">
  302. .design-engine {
  303. position: relative;
  304. height: 100%;
  305. .dingflow-design {
  306. width: 100%;
  307. // background-color: #f5f5f7;
  308. overflow: auto;
  309. height: 100%;
  310. position: relative;
  311. bottom: 0;
  312. left: 0;
  313. right: 0;
  314. top: 0;
  315. /deep/ .ant-popover-arrow {
  316. display: none !important;
  317. }
  318. .ie-polyfill-container {
  319. display: -ms-grid;
  320. -ms-grid-columns: min-content;
  321. .box-scale {
  322. transform: scale(1);
  323. display: inline-block;
  324. position: relative;
  325. width: 100%;
  326. padding: 54.5px 0;
  327. -webkit-box-align: start;
  328. -ms-flex-align: start;
  329. align-items: flex-start;
  330. -webkit-box-pack: center;
  331. -ms-flex-pack: center;
  332. justify-content: center;
  333. -ms-flex-wrap: wrap;
  334. flex-wrap: wrap;
  335. min-width: -webkit-min-content;
  336. min-width: -moz-min-content;
  337. min-width: min-content;
  338. // background-color: #f5f5f7;
  339. -webkit-transform-origin: 0 0 0;
  340. transform-origin: 50% 0px 0px;
  341. .end-node {
  342. border-radius: 50%;
  343. font-size: 14px;
  344. color: rgba(25, 31, 37, 0.4);
  345. text-align: left;
  346. .end-node-circle {
  347. width: 10px;
  348. height: 10px;
  349. margin: auto;
  350. border-radius: 50%;
  351. background: #dbdcdc;
  352. }
  353. .end-node-text {
  354. margin-top: 5px;
  355. text-align: center;
  356. }
  357. }
  358. }
  359. }
  360. }
  361. }
  362. </style>