UNPKG

kre-form

Version:

本项目由 Angular8+ 编写的表单设计器和表单应用,所有的配置都是 JSON 结构体组成,PC 端是基于 ANT 组件库封装

604 lines (598 loc) 21.2 kB
import { Graph, Shape, Addon } from '@antv/x6'; import { NzMessageService } from 'ng-zorro-antd/message'; import { Component, Input, Output, EventEmitter, NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class DataFlowComponent { /** * @param {?} message */ constructor(message) { this.message = message; this.drawerEvent = new EventEmitter(); this.modalEvent = new EventEmitter(); this.data = { // 节点 nodes: [ { id: "node1", // String,可选,节点的唯一标识 x: 40, // Number,必选,节点位置的 x 值 y: 40, // Number,必选,节点位置的 y 值 width: 80, // Number,可选,节点大小的 width 值 height: 40, // Number,可选,节点大小的 height 值 label: "hello", }, { id: "node2", // String,节点的唯一标识 x: 160, // Number,必选,节点位置的 x 值 y: 180, // Number,必选,节点位置的 y 值 width: 80, // Number,可选,节点大小的 width 值 height: 40, // Number,可选,节点大小的 height 值 label: "world", }, ], // 边 edges: [ { source: "node1", // String,必须,起始节点 id target: "node2", }, ], }; this.title = "my-app"; } /** * @return {?} */ ngOnInit() { this.graphShape(); this.grahpInit(); this.getHistoryGrahp(); this.graphEvent(); // console.log("节点", this.graph.getNodes()); // console.log("cell-----"); // console.log("节点和边", this.graph.getCells()); // console.log("根节点,即没有输入边的节点", this.graph.getRootNodes()); // console.log("叶子节点,即没有输出边的节点", this.graph.getLeafNodes()); // console.log("数量", this.graph.getCellCount()); // console.log(this.graph); // console.log(this.stencil.graphs.group1.getNodes()); /** @type {?} */ let nodes = this.graph.getLeafNodes(); for (let i = 0; i < nodes.length; i++) { /** @type {?} */ let node = nodes[i]; if (node["label"] !== "输出") { this.message.error("界面必须包含输出"); break; } } } /** * @return {?} */ grahpInit() { /** @type {?} */ const that = this; // #region 初始化画布 this.graph = new Graph({ container: (/** @type {?} */ (document.getElementById("graph-container"))), grid: true, history: true, minimap: { enabled: true, container: (/** @type {?} */ (document.getElementById("minimap"))), width: 198, height: 198, padding: 10, }, mousewheel: { enabled: true, zoomAtMousePosition: true, modifiers: "ctrl", minScale: 0.5, maxScale: 3, }, connecting: { router: "manhattan", connector: { name: "rounded", args: { radius: 8, }, }, anchor: "center", connectionPoint: "anchor", allowBlank: false, snap: { radius: 20, }, /** * @return {?} */ createEdge() { return new Shape.Edge({ attrs: { line: { stroke: "#A2B1C3", strokeWidth: 2, targetMarker: { name: "block", width: 12, height: 8, }, }, }, zIndex: 0, }); }, // 在移动边的时候判断连接是否有效 /** * @param {?} __0 * @return {?} */ validateConnection({ sourceView, targetView, sourceMagnet, targetMagnet, sourceCell, targetCell, }) { if (targetMagnet && targetCell) { /** @type {?} */ const incomingEdges = (/** @type {?} */ (that.graph)).getIncomingEdges(targetCell) || []; if (incomingEdges.length >= (/** @type {?} */ (targetView)).cell.getData().out) { that.message.error("超出out数量"); return false; } } // 不允许连接到自己 if (sourceView === targetView) { // that.message.error("不允许连接到自己"); return false; } // 只能从输出链接桩创建连接 if (!sourceMagnet || sourceMagnet.getAttribute("port-group") === "left") { // that.message.error("只能从输出链接桩创建连接"); return false; } // 只能连接到输入链接桩 if (!targetMagnet || targetMagnet.getAttribute("port-group") === "right") { // that.message.error("只能连接到输入链接桩"); return false; } return !!targetMagnet; }, }, highlighting: { magnetAdsorbed: { name: "stroke", args: { attrs: { fill: "#5F95FF", stroke: "#5F95FF", }, }, }, }, resizing: true, rotating: true, selecting: { enabled: true, rubberband: true, showNodeSelectionBox: true, }, snapline: true, keyboard: true, clipboard: true, }); this.stencil = new Addon.Stencil({ target: this.graph, stencilGraphWidth: 200, stencilGraphHeight: 180, collapsable: true, groups: [ { title: "数据处理", name: "group1", }, { title: "输入输出", name: "group2", }, ], layoutOptions: { columns: 2, columnWidth: 80, rowHeight: 55, }, /** * @param {?} currentnode * @return {?} */ validateNode(currentnode) { /** @type {?} */ const nodes = that.graph.getNodes(); if (nodes.length > 0) { for (let i = 0; i < nodes.length; i++) { /** @type {?} */ let node = nodes[i]; if (currentnode["label"] === "输出" && node["label"] === "输出") { return false; } } } return true; }, /** * @param {?} node * @return {?} */ getDropNode(node) { /** @type {?} */ const size = node.size(); if (node["label"] === "输入") { that.getModal(node["label"]); } if (node["label"] === "输出") { r2.attr("body/fill", "#ccc"); } return node.clone().size(size.width * 1.1, size.height * 1.1); }, }); (/** @type {?} */ (document.getElementById("stencil"))).appendChild(this.stencil.container); // #region 初始化图形 // 常规左右两个桩 /** @type {?} */ const ports = { groups: { right: { position: "right", attrs: { circle: { r: 4, magnet: true, stroke: "#5F95FF", strokeWidth: 1, fill: "#fff", style: { visibility: "hidden", }, }, }, }, left: { position: "left", attrs: { circle: { r: 4, magnet: true, stroke: "#5F95FF", strokeWidth: 1, fill: "#fff", style: { visibility: "hidden", }, }, }, }, }, items: [ { id: "port1", group: "left", }, { id: "port2", group: "right", }, ], }; // 输入只有左侧一个桩 /** @type {?} */ const ports2 = { groups: { left: { position: "left", attrs: { circle: { r: 4, magnet: true, stroke: "#5F95FF", strokeWidth: 1, fill: "#fff", style: { visibility: "hidden", }, }, }, }, }, items: [ { id: "port1", group: "left", }, ], }; // 输出只有右侧一个桩 /** @type {?} */ const ports3 = { groups: { right: { position: "right", attrs: { circle: { r: 4, magnet: true, stroke: "#5F95FF", strokeWidth: 1, fill: "#fff", style: { visibility: "hidden", }, }, }, }, }, items: [ { id: "port2", group: "right", }, ], }; /** @type {?} */ const r1 = this.graph.createNode({ shape: "custom-rect", id: "in", label: "输入", ports: Object.assign({}, ports3), data: { in: 0, out: 3, }, }); /** @type {?} */ const r2 = this.graph.createNode({ shape: "custom-rect", id: "out", label: "输出", ports: Object.assign({}, ports2), data: { in: 2, out: 2, }, }); /** @type {?} */ const nodeArr = []; this.menuList.forEach((/** * @param {?} element * @param {?} i * @return {?} */ (element, i) => { nodeArr.push(this.graph.createNode({ shape: "custom-rect", label: element.title, ports: Object.assign({}, ports), data: element.data, })); })); this.stencil.load([r1, r2], "group1"); this.stencil.load([...nodeArr], "group2"); } /** * @return {?} */ graphEvent() { // delete this.graph.bindKey("backspace", (/** * @return {?} */ () => { /** @type {?} */ const cells = this.graph.getSelectedCells(); if (cells.length) { this.graph.removeCells(cells); } })); // 控制连接桩显示/隐藏 /** @type {?} */ const showPorts = (/** * @param {?} ports * @param {?} show * @return {?} */ (ports, show) => { for (let i = 0, len = ports.length; i < len; i = i + 1) { ports[i].style.visibility = show ? "visible" : "hidden"; } }); this.graph.on("node:mouseenter", (/** * @return {?} */ () => { /** @type {?} */ const container = (/** @type {?} */ (document.getElementById("graph-container"))); /** @type {?} */ const ports = (/** @type {?} */ (container.querySelectorAll(".x6-port-body"))); showPorts(ports, true); })); this.graph.on("node:mouseleave", (/** * @return {?} */ () => { /** @type {?} */ const container = (/** @type {?} */ (document.getElementById("graph-container"))); /** @type {?} */ const ports = (/** @type {?} */ (container.querySelectorAll(".x6-port-body"))); showPorts(ports, false); })); // this.graph.on( // "edge:connected", // ({ isNew, currentMagnet, currentCell }) => {} // ); // this.graph.on("edge:added", ({ cell, index, options }) => {}); // this.graph.on( // "edge:change:*", // (args: { // key: string; // 通过 key 来确定改变项 // current: any; // 当前值,类型根据 key 指代的类型确定 // previous: any; // 改变之前的值,类型根据 key 指代的类型确定 // options: any; // 透传的 options // }) => { // console.log("key:", args.key); // } // ); // this.graph.on("edge:changed", ({ edge, options }) => {}); this.graph.on("node:click", (/** * @param {?} __0 * @return {?} */ ({ cell, view }) => { /** @type {?} */ let node = view.cell; console.log(node.label); if (node.label === "输入") { this.getModal(node.label); } else { this.getDrawer(node.label); } })); } /** * @return {?} */ getHistoryGrahp() { /** @type {?} */ let json = localStorage.getItem("graphJSON"); if (json) { this.graph.fromJSON(JSON.parse(json)); } } /** * @param {?} label * @return {?} */ getModal(label) { this.modalEvent.emit(label); } /** * @param {?} label * @return {?} */ getDrawer(label) { this.drawerEvent.emit(label); } /** * @return {?} */ graphShape() { Graph.registerNode("custom-rect", { inherit: "rect", width: 66, height: 30, attrs: { body: { strokeWidth: 1, stroke: "#eee", fill: "#fff", }, text: { fontSize: 12, color: "#262626", }, }, }, true); } /** * @return {?} */ handleZoomIn() { this.graph.zoom(0.1); console.log(this.graph.zoom()); } /** * @return {?} */ handleZoomOut() { this.graph.zoom(-0.1); } /** * @return {?} */ handleUndo() { this.graph.history.undo(); } /** * @return {?} */ handleRedo() { this.graph.history.redo(); } /** * @return {?} */ handleReal() { this.graph.scale(1); this.graph.centerContent(); } /** * @return {?} */ handleFit() { this.graph.zoomToFit({ padding: 12 }); } } DataFlowComponent.decorators = [ { type: Component, args: [{ selector: "data-flow", template: "<div class=\"wrap\">\n <div class=\"main\">\n <div class=\"edit-container\">\n <div id=\"container\">\n <div id=\"stencil\"></div>\n <div class=\"graph-wrap\">\n <div class=\"toolbar-wrap\">\n <span (click)=\"handleZoomIn()\" class=\"toolbar-btn\">+</span>\n <span class=\"number\">{{ graph.zoom() | percent }}</span>\n <span (click)=\"handleZoomOut()\" class=\"toolbar-btn\">-</span>\n <span class=\"line\">|</span>\n <span\n (click)=\"handleUndo()\"\n [ngClass]=\"{ on: graph.history.canUndo() }\"\n class=\"toolbar-btn-off\"\n >&lt;</span\n >\n <span\n (click)=\"handleRedo()\"\n [ngClass]=\"{ on: graph.history.canRedo() }\"\n class=\"toolbar-btn-off\"\n >&gt;</span\n >\n\n <span (click)=\"handleReal()\">\u5B9E\u9645\u5C3A\u5BF8</span>\n <span (click)=\"handleFit()\">\u9002\u5E94\u753B\u5E03</span>\n </div>\n <div id=\"graph-container\"></div>\n <div id=\"minimap\"></div>\n </div>\n </div>\n </div>\n <div class=\"board\"></div>\n </div>\n</div>\n", styles: [":host #stencil{width:180px;height:100%;position:relative}:host .graph-wrap{width:calc(100% - 180px)}:host .graph-wrap .toolbar-wrap{height:42px;line-height:42px}:host .graph-wrap .toolbar-wrap span{color:#111;margin:0 10px}:host .graph-wrap .toolbar-wrap .number{display:inline-block;width:42px}:host .graph-wrap .toolbar-wrap .line{color:#eee}:host .graph-wrap .toolbar-wrap .toolbar-btn{cursor:pointer;font-weight:700;padding:0 10px}:host .graph-wrap .toolbar-wrap .toolbar-btn-off{font-weight:700;padding:0 10px;cursor:default;color:#eee}:host .graph-wrap .toolbar-wrap .on{cursor:pointer;color:#111}:host .graph-wrap #graph-container{width:100%;height:100%}:host .graph-wrap #minimap{position:absolute;right:1rem;top:1rem;background-color:#bc8f8f}:host #container{display:flex;height:500px}:host ::ng-deep .x6-widget-stencil-title{display:none}:host ::ng-deep .x6-widget-stencil.collapsable>.x6-widget-stencil-content{top:0}"] }] } ]; /** @nocollapse */ DataFlowComponent.ctorParameters = () => [ { type: NzMessageService } ]; DataFlowComponent.propDecorators = { menuList: [{ type: Input }], drawerEvent: [{ type: Output }], modalEvent: [{ type: Output }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class DataFlowModule { } DataFlowModule.decorators = [ { type: NgModule, args: [{ declarations: [DataFlowComponent], imports: [CommonModule], exports: [DataFlowComponent], entryComponents: [DataFlowComponent], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { DataFlowComponent, DataFlowModule }; //# sourceMappingURL=kre-form-abc-src-lib-data-flow.js.map