feat: 后端全量更新 - 含所有本次需求

- Contract.php: 返回合约账户余额(balance_contract)
- My.php: 地址管理增加BTC/ETH
- AppContract.php: 一键平仓(closeall)
- AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2)
- site.php: 手续费减半(0.018→0.009)
- agent_permission_setup.sql: 代理权限SQL
- crypto_news_crawler.py: 新闻自动采集脚本
This commit is contained in:
li
2026-03-30 20:16:32 +08:00
commit 1b24994e74
6721 changed files with 1308571 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
/* for BPMN.html */
/* Diagram and palette area */
#myDiagramDiv {
float: left;
border: solid 1px gray;
border-left: none;
width: 84%;
height: 700px;
background-color: white;
}
#description {
float: left;
margin-left: 4px;
}
#PaletteAndDiagram {
position: relative;
overflow: hidden;
width: 100%;
}
#sideBar {
float: left;
width: 15%;
min-height: 500px;
text-align: center;
border: 1px solid gray;
}
.myPaletteDiv {
width: 100%;
min-height: 625px;
}
#accordion {
margin: 0px;
width: 97%;
min-height: 625px;
}
#myOverviewDiv {
width: 100%;
height: 225px;
}
/* top bar area */
.ui-accordion .ui-accordion-content {
padding: 1px;
}
.ui-menu {
width: 120px;
}
#menuui {
height: 30px;
width: 100%;
}
#menuui > li {
float: left;
}
input {
text-align: center;
font-size: large;
float: left;
}
#myOverviewDiv {
background-color: lightgray;
}
#currentFile {
background: #1874CD;
width: 100%;
text-align: center;
font-family: Arial;
font-weight: bold;
font-size: 14px;
padding: 3px 0px;
color: white;
}
.draggable {
display: inline-block;
vertical-align: top;
border: 1px solid gray;
background-color: #e2e2e2;
position: absolute;
top: 40%;
left: 50%;
width: 300px;
height: 200px;
z-index: 500;
}
.handle {
background-color: #9CCB19;
text-align: center;
font: bold 12px sans-serif;
}
.elementText {
font-family: Arial;
font-size: medium;
margin-left: 10px;
margin-top: 20px;
margin-bottom: 10px;
}
.mySavedFiles {
font-family: Arial;
font-size: medium;
width: 250px;
margin-left: 25px;
}
.elementBtn {
margin-top: 20px;
font-family: Arial;
font-size: medium;
margin-left: 20px;
}
/* sample thumbnails bottom area */
figure {
display: inline-block;
margin: 10px;
}
+188
View File
@@ -0,0 +1,188 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>BPMN Editor</title>
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<link rel="stylesheet" href="../../assets/css/jquery-ui.min.css" />
<script src="../../assets/js/jquery.min.js"></script>
<script src="../../assets/js/jquery-ui.min.js"></script>
<link href="BPMN.css" rel="stylesheet" type="text/css" />
<script src="../../samples/assets/require.js"></script>
<script>
function init() {
require(["BPMNScript"], function (app) {
app.init();
document.getElementById("newDocument").onclick = app.newDocument;
document.getElementById("openDocuments").onclick = app.openDocument;
document.getElementById("saveDocument").onclick = app.saveDocument;
document.getElementById("saveDocumentAs").onclick = app.saveDocumentAs;
document.getElementById("removeDocuments").onclick = app.removeDocument;
document.getElementById("undo").onclick = app.undo;
document.getElementById("redo").onclick = app.redo;
document.getElementById("cutSelection").onclick = app.cutSelection;
document.getElementById("copySelection").onclick = app.copySelection;
document.getElementById("pasteSelection").onclick = app.pasteSelection;
document.getElementById("deleteSelection").onclick = app.deleteSelection;
document.getElementById("selectAll").onclick = app.selectAll;
document.getElementById("alignLeft").onclick = app.alignLeft;
document.getElementById("alignRight").onclick = app.alignRight;
document.getElementById("alignTop").onclick = app.alignTop;
document.getElementById("alignBottom").onclick = app.alignBottom;
document.getElementById("alignCenterX").onclick = app.alignCenterX;
document.getElementById("alignCenterY").onclick = app.alignCenterY;
document.getElementById("alignRows").onclick = app.alignRows;
document.getElementById("alignColumns").onclick = app.alignColumns;
document.getElementById("grid").onclick = app.updateGridOption;
document.getElementById("snap").onclick = app.updateSnapOption;
document.getElementById("basicOrderProcess").onclick = app.basicOrderProcess;
document.getElementById("5.1").onclick = app.BPMNdata51;
document.getElementById("5.2").onclick = app.BPMNdata52;
document.getElementById("5.3").onclick = app.BPMNdata53;
document.getElementById("openBtn").onclick = app.loadFile;
document.getElementById("cancelBtn").onclick = app.cancel1;
document.getElementById("removeBtn").onclick = app.removeFile;
document.getElementById("cancelBtn2").onclick = app.cancel2;
});
}
</script>
</head>
<body onload="init()">
<div>
<div id="currentFile">(Unsaved File)</div>
<ul id="menuui">
<li><a href="#">File</a>
<ul>
<li><a href="#" id="newDocument">New</a></li>
<li><a href="#" id="openDocuments">Open...</a></li>
<li><a href="#" id="saveDocument">Save</a></li>
<li><a href="#" id="saveDocumentAs">Save As...</a></li>
<li><a href="#" id="removeDocuments">Delete...</a></li>
</ul>
</li>
<li><a href="#">Edit</a>
<ul>
<li><a href="#" id="undo">Undo</a></li>
<li><a href="#" id="redo">Redo</a></li>
<li><a href="#" id="cutSelection">Cut</a></li>
<li><a href="#" id="copySelection">Copy</a></li>
<li><a href="#" id="pasteSelection">Paste</a></li>
<li><a href="#" id="deleteSelection">Delete</a></li>
<li><a href="#" id="selectAll">Select All</a></li>
</ul>
</li>
<li><a href="#">Align</a>
<ul>
<li><a href="#" id="alignLeft">Left Sides</a></li>
<li><a href="#" id="alignRight">Right Sides</a></li>
<li><a href="#" id="alignTop">Tops</a></li>
<li><a href="#" id="alignBottom">Bottoms</a></li>
<li><a href="#" id="alignCenterX">Center X</a></li>
<li><a href="#" id="alignCenterY">Center Y</a></li>
</ul>
</li>
<li><a href="#">Space</a>
<ul>
<li><a href="#" id="alignRows">In Row...</a></li>
<li><a href="#" id="alignColumns">In Column...</a></li>
</ul>
</li>
<li><a href="#">Options</a>
<ul>
<li><a href="#">
<input id="grid" type="checkbox" name="options" value="grid">Grid</a></li>
<li><a href="#">
<input id="snap" type="checkbox" name="options" value="0">Snapping</a></li>
</ul>
</li>
</ul>
</div>
<!--END menu bar -->
<!-- Styling for this portion is in BPMN.css -->
<div id="PaletteAndDiagram">
<div id="sideBar">
<span style="display: inline-block; vertical-align: top; padding: 5px; width:100%">
<div id="accordion">
<h4>Level 1 items</h4>
<div>
<div id="myPaletteLevel1" class="myPaletteDiv" ></div>
</div>
<h4>Level 2 items</h4>
<div>
<div id="myPaletteLevel2" class="myPaletteDiv"></div>
</div>
<h4>Other items</h4>
<div>
<div id="myPaletteLevel3" class="myPaletteDiv"></div>
</div>
</div>
</span>
<div class="handle">Overview:</div>
<div id="myOverviewDiv"></div>
</div>
<div id="myDiagramDiv"></div>
<div id="description">
<p>
This sample describes templates and relationships typically used in <a href="https://en.wikipedia.org/wiki/Business_Process_Model_and_Notation">Business Process Model and Notation (BPMN)</a>,
to be used as a starting point for developing BPMN or flow-like web applications.
</p>
<p>In addition to this HTML file, this sample uses the files:</p>
<ul>
<li><a href="BPMN.css">BPMN.css</a> for styling
<li><a href="BPMNScript.ts">BPMN.ts</a> for the Diagram logic
<li><a href="BPMNClasses.ts">BPMNClasses.ts</a> - Custom PoolLink and BPMNLinkingTool classes
<li><a href="../../extensionsTS/DrawCommandHandler.ts">DrawCommandHandler.ts</a> - Custom CommandHandler class
</ul>
<span>
<div>
<p>Additional sample data files:</p>
<figure>
<img src="BPMNdata/BasicOrderProcess.png" id='basicOrderProcess' title="Basic Order Process"></img>
<figcaption>Basic Order Process</figcaption>
</figure>
<figure>
<img src="BPMNdata/OMG BPMN by Example Figure 5.1.png" id='5.1' title="OMG BPMN by Example Figure 5.1"></img>
<figcaption>OMG BPMN by Example Figure 5.1</figcaption>
</figure>
<figure>
<img src="BPMNdata/OMG BPMN by Example Figure 5.2.png" id='5.2' title="OMG BPMN by Example Figure 5.2"></img>
<figcaption>OMG BPMN by Example Figure 5.2</figcaption>
</figure>
<figure>
<img src="BPMNdata/OMG BPMN by Example Figure 5.3.png" id='5.3' title="OMG BPMN by Example Figure 5.3"></img>
<figcaption>OMG BPMN by Example Figure 5.3</figcaption>
</figure>
</div>
</span>
</div>
</div>
<div id="openDocument" class="draggable">
<div id="openDraggableHandle" class="handle">Open File</div>
<div id="openText" class="elementText">Choose file to open...</div>
<select id="mySavedFiles" class="mySavedFiles"></select>
<br />
<button id="openBtn" class="elementBtn" type="button"style="margin-left: 70px">Open</button>
<button id="cancelBtn" class="elementBtn" type="button">Cancel</button>
</div>
<div id="removeDocument" class="draggable">
<div id="removeDraggableHandle" class="handle">Delete File</div>
<div id="removeText" class="elementText">Choose file to remove...</div>
<select id="mySavedFiles2" class="mySavedFiles"></select>
<br />
<button id="removeBtn" class="elementBtn" type="button" style="margin-left: 70px">Remove</button>
<button id="cancelBtn2" class="elementBtn" type="button">Cancel</button>
</div>
</div>
</body>
</html>
+254
View File
@@ -0,0 +1,254 @@
/*
* Copyright (C) 1998-2020 by Northwoods Software Corporation. All Rights Reserved.
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "../../release/go.js"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BPMNRelinkingTool = exports.BPMNLinkingTool = exports.PoolLink = void 0;
var go = require("../../release/go.js");
// Contains PoolLink and BPMNLinkingTool classes for the BPMN sample
/**
* PoolLink, a special Link class for message flows from edges of pools
*
* Used in the <a href="../../projects/bpmn/BPMN.html">BPMN extension</a>.
*/
var PoolLink = /** @class */ (function (_super) {
__extends(PoolLink, _super);
function PoolLink() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* @hidden @internal
*/
PoolLink.prototype.getLinkPoint = function (node, port, spot, from, ortho, othernode, otherport) {
var r = new go.Rect(port.getDocumentPoint(go.Spot.TopLeft), port.getDocumentPoint(go.Spot.BottomRight));
var op = _super.prototype.getLinkPoint.call(this, othernode, otherport, spot, from, ortho, node, port);
var below = op.y > r.centerY;
var y = below ? r.bottom : r.top;
if (node.category === 'privateProcess') {
if (op.x < r.left)
return new go.Point(r.left, y);
if (op.x > r.right)
return new go.Point(r.right, y);
return new go.Point(op.x, y);
}
else { // otherwise get the standard link point by calling the base class method
return _super.prototype.getLinkPoint.call(this, node, port, spot, from, ortho, othernode, otherport);
}
};
/**
* @hidden @internal
* If there are two links from & to same node... and pool is offset in X from node... the link toPoints collide on pool
*/
PoolLink.prototype.computeOtherPoint = function (othernode, otherport) {
var op = _super.prototype.computeOtherPoint.call(this, othernode, otherport);
var node = this.toNode;
if (node === othernode)
node = this.fromNode;
if (node !== null) {
if (othernode.category === 'privateProcess') {
op.x = node.getDocumentPoint(go.Spot.MiddleBottom).x;
}
else {
if ((node === this.fromNode) !== (node.actualBounds.centerY < othernode.actualBounds.centerY)) {
op.x -= 1;
}
else {
op.x += 1;
}
}
}
return op;
};
/**
* @hidden @internal
*/
PoolLink.prototype.getLinkDirection = function (node, port, linkpoint, spot, from, ortho, othernode, otherport) {
if (node.category === 'privateProcess') {
var p = port.getDocumentPoint(go.Spot.Center);
var op = otherport.getDocumentPoint(go.Spot.Center);
var below = op.y > p.y;
return below ? 90 : 270;
}
else {
return _super.prototype.getLinkDirection.call(this, node, port, linkpoint, spot, from, ortho, othernode, otherport);
}
};
return PoolLink;
}(go.Link));
exports.PoolLink = PoolLink;
/**
* BPMNLinkingTool, a custom linking tool to switch the class of the link created.
*
* Used in the <a href="../../projects/bpmn/BPMN.html">BPMN extension</a>.
* @category Extension
*/
var BPMNLinkingTool = /** @class */ (function (_super) {
__extends(BPMNLinkingTool, _super);
function BPMNLinkingTool() {
var _this = _super.call(this) || this;
// don't allow user to create link starting on the To node
_this.direction = go.LinkingTool.ForwardsOnly;
// orthogonal routing during linking
_this.temporaryLink.routing = go.Link.Orthogonal;
// link validation using the validate methods defined below
_this.linkValidation = function (fromnode, fromport, tonode, toport) {
return BPMNLinkingTool.validateSequenceLinkConnection(fromnode, fromport, tonode, toport) ||
BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport);
};
return _this;
}
/**
* Override {@link LinkingTool#insertLink} to do some extra BPMN-specific processing.
*/
BPMNLinkingTool.prototype.insertLink = function (fromnode, fromport, tonode, toport) {
var lsave = null;
// maybe temporarily change the link data that is copied to create the new link
if (BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport)) {
lsave = this.archetypeLinkData;
this.archetypeLinkData = { category: 'msg' };
}
// create the link in the standard manner by calling the base method
var newlink = _super.prototype.insertLink.call(this, fromnode, fromport, tonode, toport);
// maybe make the label visible
if (newlink !== null && fromnode.category === 'gateway') {
var label = newlink.findObject('Label');
if (label !== null)
label.visible = true;
}
// maybe restore the original archetype link data
if (lsave !== null)
this.archetypeLinkData = lsave;
return newlink;
};
// static utility validation routines for linking & relinking as well as insert link logic
/**
* Validate that sequence links don't cross subprocess or pool boundaries.
*/
BPMNLinkingTool.validateSequenceLinkConnection = function (fromnode, fromport, tonode, toport) {
if (fromnode.category === null || tonode.category === null)
return true;
// if either node is in a subprocess, both nodes must be in same subprocess (even for Message Flows)
if ((fromnode.containingGroup !== null && fromnode.containingGroup.category === 'subprocess') ||
(tonode.containingGroup !== null && tonode.containingGroup.category === 'subprocess')) {
if (fromnode.containingGroup !== tonode.containingGroup)
return false;
}
if (fromnode.containingGroup === tonode.containingGroup)
return true; // a valid Sequence Flow
// also check for children in common pool
var common = fromnode.findCommonContainingGroup(tonode);
return common != null;
};
/**
* Validate that message links cross pool boundaries.
*/
BPMNLinkingTool.validateMessageLinkConnection = function (fromnode, fromport, tonode, toport) {
if (fromnode.category === null || tonode.category === null)
return true;
if (fromnode.category === 'privateProcess' || tonode.category === 'privateProcess')
return true;
// if either node is in a subprocess, both nodes must be in same subprocess (even for Message Flows)
if ((fromnode.containingGroup !== null && fromnode.containingGroup.category === 'subprocess') ||
(tonode.containingGroup !== null && tonode.containingGroup.category === 'subprocess')) {
if (fromnode.containingGroup !== tonode.containingGroup)
return false;
}
if (fromnode.containingGroup === tonode.containingGroup)
return false; // an invalid Message Flow
// also check if fromnode and tonode are in same pool
var common = fromnode.findCommonContainingGroup(tonode);
return common === null;
};
return BPMNLinkingTool;
}(go.LinkingTool));
exports.BPMNLinkingTool = BPMNLinkingTool;
/**
* BPMNRelinkingTool, a custom relinking tool to switch the class of the link reconnected.
*
* Used in the <a href="../../projects/bpmn/BPMN.html">BPMN extension</a>.
*/
var BPMNRelinkingTool = /** @class */ (function (_super) {
__extends(BPMNRelinkingTool, _super);
function BPMNRelinkingTool() {
var _this = _super.call(this) || this;
// orthogonal routing during linking
_this.temporaryLink.routing = go.Link.Orthogonal;
// link validation using the validate methods defined below
_this.linkValidation = function (fromnode, fromport, tonode, toport) {
return BPMNLinkingTool.validateSequenceLinkConnection(fromnode, fromport, tonode, toport) ||
BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport);
};
return _this;
}
/**
* Override {@link RelinkingTool#reconnectLink} to do some extra BPMN-specific processing.
*/
BPMNRelinkingTool.prototype.reconnectLink = function (existinglink, newnode, newport, toend) {
var diagram = existinglink.diagram;
if (diagram === null)
return false;
var model = diagram.model;
if (model === null)
return false;
function recreateLinkData(data, cat) {
// Copy existing data, then set from, to, and category
var copy = model.copyLinkData(data);
copy.from = data.from;
copy.to = data.to;
copy.category = cat;
copy.points = undefined; // don't keep points from existing link
model.removeLinkData(data);
model.addLinkData(copy);
}
if (_super.prototype.reconnectLink.call(this, existinglink, newnode, newport, toend)) {
var data = existinglink.data;
var fromnode = existinglink.fromNode;
var fromport = existinglink.fromPort;
var tonode = existinglink.toNode;
var toport = existinglink.toPort;
if (fromnode !== null && fromport !== null && tonode !== null && toport !== null) {
diagram.startTransaction('Relink updates');
if (BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport)) {
// Recreate the link if the category changed, since it is a different class
if (existinglink.category !== 'msg') {
recreateLinkData(data, 'msg');
}
}
// maybe make the label visible
if (fromnode.category === 'gateway') {
var label = existinglink.findObject('Label');
if (label !== null)
label.visible = true;
}
diagram.commitTransaction('Relink updates');
}
return true;
}
return false;
};
return BPMNRelinkingTool;
}(go.RelinkingTool));
exports.BPMNRelinkingTool = BPMNRelinkingTool;
});
+222
View File
@@ -0,0 +1,222 @@
/*
* Copyright (C) 1998-2020 by Northwoods Software Corporation. All Rights Reserved.
*/
import * as go from '../../release/go.js';
// Contains PoolLink and BPMNLinkingTool classes for the BPMN sample
/**
* PoolLink, a special Link class for message flows from edges of pools
*
* Used in the <a href="../../projects/bpmn/BPMN.html">BPMN extension</a>.
*/
export class PoolLink extends go.Link {
/**
* @hidden @internal
*/
public getLinkPoint(node: go.Node, port: go.GraphObject, spot: go.Spot, from: boolean, ortho: boolean, othernode: go.Node, otherport: go.GraphObject): go.Point {
const r = new go.Rect(port.getDocumentPoint(go.Spot.TopLeft), port.getDocumentPoint(go.Spot.BottomRight));
const op = super.getLinkPoint(othernode, otherport, spot, from, ortho, node, port);
const below = op.y > r.centerY;
const y = below ? r.bottom : r.top;
if (node.category === 'privateProcess') {
if (op.x < r.left) return new go.Point(r.left, y);
if (op.x > r.right) return new go.Point(r.right, y);
return new go.Point(op.x, y);
} else { // otherwise get the standard link point by calling the base class method
return super.getLinkPoint(node, port, spot, from, ortho, othernode, otherport);
}
}
/**
* @hidden @internal
* If there are two links from & to same node... and pool is offset in X from node... the link toPoints collide on pool
*/
public computeOtherPoint(othernode: go.Node, otherport: go.GraphObject): go.Point {
const op = super.computeOtherPoint(othernode, otherport);
let node = this.toNode;
if (node === othernode) node = this.fromNode;
if (node !== null) {
if (othernode.category === 'privateProcess') {
op.x = node.getDocumentPoint(go.Spot.MiddleBottom).x;
} else {
if ((node === this.fromNode) !== (node.actualBounds.centerY < othernode.actualBounds.centerY)) {
op.x -= 1;
} else {
op.x += 1;
}
}
}
return op;
}
/**
* @hidden @internal
*/
public getLinkDirection(node: go.Node, port: go.GraphObject, linkpoint: go.Point, spot: go.Spot,
from: boolean, ortho: boolean, othernode: go.Node, otherport: go.GraphObject): number {
if (node.category === 'privateProcess') {
const p = port.getDocumentPoint(go.Spot.Center);
const op = otherport.getDocumentPoint(go.Spot.Center);
const below = op.y > p.y;
return below ? 90 : 270;
} else {
return super.getLinkDirection.call(this, node, port, linkpoint, spot, from, ortho, othernode, otherport);
}
}
}
/**
* BPMNLinkingTool, a custom linking tool to switch the class of the link created.
*
* Used in the <a href="../../projects/bpmn/BPMN.html">BPMN extension</a>.
* @category Extension
*/
export class BPMNLinkingTool extends go.LinkingTool {
constructor() {
super();
// don't allow user to create link starting on the To node
this.direction = go.LinkingTool.ForwardsOnly;
// orthogonal routing during linking
this.temporaryLink.routing = go.Link.Orthogonal;
// link validation using the validate methods defined below
this.linkValidation = (fromnode: go.Node, fromport: go.GraphObject, tonode: go.Node, toport: go.GraphObject) => {
return BPMNLinkingTool.validateSequenceLinkConnection(fromnode, fromport, tonode, toport) ||
BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport);
};
}
/**
* Override {@link LinkingTool#insertLink} to do some extra BPMN-specific processing.
*/
public insertLink(fromnode: go.Node, fromport: go.GraphObject, tonode: go.Node, toport: go.GraphObject): go.Link | null {
let lsave = null;
// maybe temporarily change the link data that is copied to create the new link
if (BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport)) {
lsave = this.archetypeLinkData;
this.archetypeLinkData = { category: 'msg' };
}
// create the link in the standard manner by calling the base method
const newlink = super.insertLink(fromnode, fromport, tonode, toport);
// maybe make the label visible
if (newlink !== null && fromnode.category === 'gateway') {
const label = newlink.findObject('Label');
if (label !== null) label.visible = true;
}
// maybe restore the original archetype link data
if (lsave !== null) this.archetypeLinkData = lsave;
return newlink;
}
// static utility validation routines for linking & relinking as well as insert link logic
/**
* Validate that sequence links don't cross subprocess or pool boundaries.
*/
public static validateSequenceLinkConnection(fromnode: go.Node, fromport: go.GraphObject, tonode: go.Node, toport: go.GraphObject): boolean {
if (fromnode.category === null || tonode.category === null) return true;
// if either node is in a subprocess, both nodes must be in same subprocess (even for Message Flows)
if ((fromnode.containingGroup !== null && fromnode.containingGroup.category === 'subprocess') ||
(tonode.containingGroup !== null && tonode.containingGroup.category === 'subprocess')) {
if (fromnode.containingGroup !== tonode.containingGroup) return false;
}
if (fromnode.containingGroup === tonode.containingGroup) return true; // a valid Sequence Flow
// also check for children in common pool
const common = fromnode.findCommonContainingGroup(tonode);
return common != null;
}
/**
* Validate that message links cross pool boundaries.
*/
public static validateMessageLinkConnection(fromnode: go.Node, fromport: go.GraphObject, tonode: go.Node, toport: go.GraphObject): boolean {
if (fromnode.category === null || tonode.category === null) return true;
if (fromnode.category === 'privateProcess' || tonode.category === 'privateProcess') return true;
// if either node is in a subprocess, both nodes must be in same subprocess (even for Message Flows)
if ((fromnode.containingGroup !== null && fromnode.containingGroup.category === 'subprocess') ||
(tonode.containingGroup !== null && tonode.containingGroup.category === 'subprocess')) {
if (fromnode.containingGroup !== tonode.containingGroup) return false;
}
if (fromnode.containingGroup === tonode.containingGroup) return false; // an invalid Message Flow
// also check if fromnode and tonode are in same pool
const common = fromnode.findCommonContainingGroup(tonode);
return common === null;
}
}
/**
* BPMNRelinkingTool, a custom relinking tool to switch the class of the link reconnected.
*
* Used in the <a href="../../projects/bpmn/BPMN.html">BPMN extension</a>.
*/
export class BPMNRelinkingTool extends go.RelinkingTool {
constructor() {
super();
// orthogonal routing during linking
this.temporaryLink.routing = go.Link.Orthogonal;
// link validation using the validate methods defined below
this.linkValidation = (fromnode: go.Node, fromport: go.GraphObject, tonode: go.Node, toport: go.GraphObject) => {
return BPMNLinkingTool.validateSequenceLinkConnection(fromnode, fromport, tonode, toport) ||
BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport);
};
}
/**
* Override {@link RelinkingTool#reconnectLink} to do some extra BPMN-specific processing.
*/
public reconnectLink(existinglink: go.Link, newnode: go.Node | null, newport: go.GraphObject | null, toend: boolean): boolean {
const diagram = existinglink.diagram;
if (diagram === null) return false;
const model = diagram.model as go.GraphLinksModel;
if (model === null) return false;
function recreateLinkData(data: any, cat: string) {
// Copy existing data, then set from, to, and category
const copy = model.copyLinkData(data) as any;
copy.from = data.from;
copy.to = data.to;
copy.category = cat;
copy.points = undefined; // don't keep points from existing link
model.removeLinkData(data);
model.addLinkData(copy);
}
if (super.reconnectLink(existinglink, newnode, newport, toend)) {
const data = existinglink.data;
const fromnode = existinglink.fromNode;
const fromport = existinglink.fromPort;
const tonode = existinglink.toNode;
const toport = existinglink.toPort;
if (fromnode !== null && fromport !== null && tonode !== null && toport !== null) {
diagram.startTransaction('Relink updates');
if (BPMNLinkingTool.validateMessageLinkConnection(fromnode, fromport, tonode, toport)) {
// Recreate the link if the category changed, since it is a different class
if (existinglink.category !== 'msg') {
recreateLinkData(data, 'msg');
}
}
// maybe make the label visible
if (fromnode.category === 'gateway') {
const label = existinglink.findObject('Label');
if (label !== null) label.visible = true;
}
diagram.commitTransaction('Relink updates');
}
return true;
}
return false;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
{ "class": "go.GraphLinksModel",
"linkFromPortIdProperty": "fromPort",
"linkToPortIdProperty": "toPort",
"modelData": {"position":"230 200"},
"nodeDataArray": [
{"category":"event", "item":"start", "key":101, "loc":"450 540", "text":"Start", "eventType":1, "eventDimension":1},
{"category":"event", "item":"End", "key":104, "loc":"1130 540", "text":"End", "eventType":1, "eventDimension":8},
{"category":"activity", "item":"generic task", "key":5, "loc":"1010 540", "text":"Send Invoice", "taskType":0, "boundaryEventArray":[ ]},
{"category":"activity", "item":"generic task", "key":-4, "loc":"860 540", "text":"Fulfill Order", "taskType":0, "boundaryEventArray":[ ]},
{"category":"activity", "item":"generic task", "key":-5, "loc":"710 540", "text":"Credit Check", "taskType":0, "boundaryEventArray":[ ]},
{"category":"activity", "item":"generic task", "key":-6, "loc":"560 540", "text":"Receive Order", "taskType":0, "boundaryEventArray":[ ]},
{"category":"annotation", "key":701, "loc":"494 434", "text":"Basic Order Process"}
],
"linkDataArray": [
{"from":101, "to":-6, "fromPort":"", "toPort":""},
{"from":-6, "to":-5, "fromPort":"", "toPort":""},
{"from":-5, "to":-4, "fromPort":"", "toPort":""},
{"from":-4, "to":5, "fromPort":"", "toPort":""},
{"from":5, "to":104, "fromPort":"", "toPort":""}
]}
Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

@@ -0,0 +1,618 @@
{
"class":"go.GraphLinksModel",
"copiesArrays":true,
"copiesArrayObjects":true,
"linkFromPortIdProperty":"fromPort",
"linkToPortIdProperty":"toPort",
"modelData":{
"position":"186.6328613281251 -77.5"
},
"nodeDataArray":[
{
"category":"event",
"item":"start",
"key":101,
"loc":"270 270",
"text":"Goods\nto Ship",
"eventType":1,
"eventDimension":1,
"group":-12
},
{
"category":"event",
"item":"End",
"key":104,
"loc":"1420 470",
"text":"End",
"eventType":1,
"eventDimension":8,
"group":-13
},
{
"category":"activity",
"item":"generic task",
"key":5,
"loc":"1290 470",
"text":"Add paperwork\nand move\npackage to\npick area",
"taskType":0,
"boundaryEventArray":[
],
"group":-13
},
{
"category":"activity",
"item":"generic task",
"key":-4,
"loc":"720 140",
"text":"Check if extra insurance is necessary",
"taskType":0,
"boundaryEventArray":[
],
"group":-12
},
{
"category":"activity",
"item":"generic task",
"key":-5,
"loc":"490 270",
"text":"Decide if \nnormal post or\nspecial\nshipment",
"taskType":0,
"boundaryEventArray":[
],
"group":-12
},
{
"category":"activity",
"item":"generic task",
"key":-6,
"loc":"540 470",
"text":"Package Goods",
"taskType":0,
"boundaryEventArray":[
],
"group":-13
},
{
"category":"annotation",
"key":701,
"loc":"556.9999999999995 -37.00000000000042",
"text":"OMG BPMN 2.0 by Example. \nFigure 5.1 Shipment Process of a Hardware Retailer",
"group":-11
},
{
"key":"501",
"text":"Hardware Retailer",
"isGroup":"true",
"category":"Pool",
"loc":"217.2106933593751 -72"
},
{
"category":"Lane",
"text":"Logistics\nManager",
"color":"white",
"isGroup":true,
"loc":"217.2106933593751 -72",
"group":"501",
"key":-11,
"size":"1299.992431640625 129"
},
{
"category":"Lane",
"text":"Clerk",
"color":"white",
"isGroup":true,
"loc":"217.2106933593751 58",
"group":"501",
"key":-12,
"size":"1299.992431640625 334"
},
{
"category":"Lane",
"text":"Warehouse\nWorker",
"color":"white",
"isGroup":true,
"loc":"217.2106933593751 393",
"group":"501",
"key":-13,
"size":"1299.992431640625 153.57783203124995"
},
{
"key":201,
"category":"gateway",
"text":"",
"gatewayType":1,
"group":-12,
"loc":"360 270"
},
{
"key":204,
"category":"gateway",
"text":"Mode of\nDelivery",
"gatewayType":4,
"group":-12,
"loc":"630 270"
},
{
"key":131,
"category":"activity",
"text":"Request Quotes from carriers",
"item":"generic task",
"taskType":0,
"group":-12,
"loc":"830 270"
},
{
"key":301,
"category":"gateway",
"gatewayType":2,
"text":"",
"group":-12,
"loc":"850 140"
},
{
"key":-16,
"category":"activity",
"text":"Take out extra\ninsurance",
"item":"generic task",
"taskType":0,
"group":-11,
"loc":"1000 -20"
},
{
"key":-17,
"category":"activity",
"text":"Fill in \nPost Label",
"item":"generic task",
"taskType":0,
"group":-12,
"loc":"1010 140"
},
{
"key":-19,
"category":"gateway",
"gatewayType":2,
"text":"",
"group":-12,
"loc":"1150 140"
},
{
"key":-20,
"category":"activity",
"text":"Assign a \ncarrier & prepare papperwork",
"item":"generic task",
"taskType":0,
"group":-12,
"loc":"1010 270"
},
{
"key":-21,
"category":"gateway",
"text":"",
"gatewayType":4,
"group":-12,
"loc":"1160 270"
},
{
"key":-22,
"category":"annotation",
"text":"insurance included",
"loc":"956.2031249999999 356.0389160156248",
"group":-12
},
{
"key":-23,
"category":"gateway",
"text":"",
"gatewayType":1,
"group":-13,
"loc":"1160 470"
}
],
"linkDataArray":[
{
"from":5,
"to":104,
"fromPort":"",
"toPort":"",
"points":[
1349.9999999999998,
470.0000000000001,
1359.9999999999998,
470.0000000000001,
1368.5,
470.0000000000001,
1368.5,
469.99999999999994,
1377,
469.99999999999994,
1397,
469.99999999999994
]
},
{
"from":101,
"to":201,
"fromPort":"",
"toPort":"",
"points":[
291.5,
270,
301.5,
270,
301.5,
270,
299.5,
270,
299.5,
270,
319.5,
270
]
},
{
"from":201,
"to":-6,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
360,
310.5,
360,
320.5,
360,
332,
360,
332,
360,
470,
460.0000000000002,
470,
480.0000000000002,
470
],
"text":""
},
{
"from":201,
"to":-5,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
400.5,
270,
410.5,
270,
410.5,
270,
409.99999999999983,
270,
409.99999999999983,
270,
429.99999999999983,
270
],
"text":""
},
{
"from":-5,
"to":204,
"fromPort":"",
"toPort":"",
"points":[
549.9999999999998,
270,
559.9999999999998,
270,
564.7499999999998,
270,
564.7499999999998,
270,
569.4999999999998,
270,
589.4999999999998,
270
]
},
{
"from":204,
"to":-4,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
629.9999999999998,
229.5,
629.9999999999998,
219.5,
629.9999999999998,
140.00000000000006,
635,
140.00000000000006,
640.0000000000001,
140.00000000000006,
660.0000000000001,
140.00000000000006
],
"text":"Normal\nPost"
},
{
"from":204,
"to":131,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
670.4999999999998,
270,
680.4999999999998,
270,
715.25,
270,
715.25,
270.00000000000006,
750.0000000000001,
270.00000000000006,
770.0000000000001,
270.00000000000006
],
"text":"Special\nCarrier"
},
{
"from":-4,
"to":301,
"fromPort":"",
"toPort":"",
"points":[
780.0000000000001,
140.00000000000006,
790.0000000000001,
140.00000000000006,
790.0000000000001,
140,
789.5,
140,
789.5,
139.99999999999997,
809.5,
139.99999999999997
]
},
{
"from":301,
"to":-16,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
850,
99.49999999999997,
850,
89.49999999999997,
850,
-20,
885,
-20,
919.9999999999999,
-20,
939.9999999999999,
-20
],
"text":"extra insurance\nrequired"
},
{
"from":301,
"to":-17,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
890.5,
139.99999999999997,
900.5,
139.99999999999997,
915.2499999999998,
139.99999999999997,
915.2499999999998,
140.00000000000006,
929.9999999999995,
140.00000000000006,
949.9999999999995,
140.00000000000006
],
"text":"Always"
},
{
"from":-17,
"to":-19,
"fromPort":"",
"toPort":"",
"points":[
1069.9999999999995,
140.00000000000006,
1079.9999999999995,
140.00000000000006,
1084.7499999999995,
140.00000000000006,
1084.7499999999995,
139.99999999999997,
1089.4999999999998,
139.99999999999997,
1109.4999999999998,
139.99999999999997
]
},
{
"from":-16,
"to":-19,
"fromPort":"",
"toPort":"",
"points":[
1060,
-20,
1070,
-20,
1149.9999999999998,
-20,
1149.9999999999998,
29.749999999999986,
1149.9999999999998,
79.49999999999997,
1149.9999999999998,
99.49999999999997
]
},
{
"from":131,
"to":-20,
"fromPort":"",
"toPort":"",
"points":[
890.0000000000001,
270.00000000000006,
900.0000000000001,
270.00000000000006,
914.9999999999999,
270.00000000000006,
914.9999999999999,
270,
929.9999999999997,
270,
949.9999999999997,
270
]
},
{
"from":-20,
"to":-21,
"fromPort":"",
"toPort":"",
"points":[
1069.9999999999995,
270,
1079.9999999999995,
270,
1089.7499999999998,
270,
1089.7499999999998,
270,
1099.5,
270,
1119.5,
270
]
},
{
"from":-19,
"to":-21,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
1149.9999999999998,
180.49999999999997,
1149.9999999999998,
190.49999999999997,
1149.9999999999998,
200,
1160,
200,
1160,
209.5,
1160,
229.5
],
"text":""
},
{
"from":-22,
"to":131,
"fromPort":"",
"toPort":"",
"category":"annotation",
"points":[
896.0004882812499,
356.0389160156248,
856.0004882812499,
356.0389160156248,
830.0000000000001,
330.00000000000006,
830.0000000000001,
310.00000000000006
]
},
{
"from":-23,
"to":5,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
1200.4999999999998,
469.99999999999994,
1210.4999999999998,
469.99999999999994,
1210.4999999999998,
470,
1209.9999999999998,
470,
1209.9999999999998,
470.0000000000001,
1229.9999999999998,
470.0000000000001
],
"text":""
},
{
"from":-6,
"to":-23,
"fromPort":"",
"toPort":"",
"points":[
600.0000000000002,
470,
610.0000000000002,
470,
854.75,
470,
854.75,
469.99999999999994,
1099.4999999999998,
469.99999999999994,
1119.4999999999998,
469.99999999999994
]
},
{
"from":-21,
"to":-23,
"fromPort":"",
"toPort":"",
"visible":true,
"points":[
1160,
310.5,
1160,
320.5,
1160,
332,
1160,
332,
1160,
348,
1159.9999999999998,
348,
1159.9999999999998,
409.49999999999994,
1159.9999999999998,
429.49999999999994
],
"text":""
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

+12
View File
@@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "umd",
"target": "es5",
"strict": true
}
// For ES6 modules you may wish to use a configuration like this instead:
// "compilerOptions": {
// "target": "es6",
// "strict": true
// }
}