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:
+204
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Multi-Node Path Links</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<meta name="description" content="A custom Link routing that goes smoothly through a sequence of Nodes." />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<script src="../release/go.js"></script>
|
||||
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
|
||||
|
||||
<script id="code">
|
||||
function init() {
|
||||
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
|
||||
var $ = go.GraphObject.make;
|
||||
|
||||
myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv", // the ID of the DIV HTML element
|
||||
{
|
||||
allowCopy: false, // would need to copy linkdata.path and update all of the refenced node keys
|
||||
allowDelete: false, // would need to update linkdata.path for all links going through that node
|
||||
"Changed": invalidateLinkRoutes,
|
||||
"undoManager.isEnabled": true
|
||||
});
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, go.Panel.Auto,
|
||||
{ locationSpot: go.Spot.Center },
|
||||
new go.Binding("location", "loc", go.Point.parse),
|
||||
$(go.Shape,
|
||||
{ figure: "Circle", fill: "white" },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ font: "bold 11pt sans-serif" },
|
||||
new go.Binding("text"))
|
||||
);
|
||||
|
||||
myDiagram.linkTemplate =
|
||||
$(MultiNodePathLink, // subclass of Link, defined below
|
||||
go.Link.Bezier,
|
||||
{ layerName: "Background", toShortLength: 4 },
|
||||
$(go.Shape, { strokeWidth: 4 },
|
||||
new go.Binding("stroke", "color")),
|
||||
$(go.Shape, { toArrow: "Standard", scale: 3, strokeWidth: 0 },
|
||||
new go.Binding("fill", "color"))
|
||||
);
|
||||
|
||||
function invalidateLinkRoutes(e) {
|
||||
// when a Node is moved, invalidate the route for all MultiNodePathLinks that go through it
|
||||
if (e.change === go.ChangedEvent.Property && e.propertyName === "location" && e.object instanceof go.Node) {
|
||||
var diagram = e.diagram;
|
||||
var node = e.object;
|
||||
if (node._PathLinks) {
|
||||
node._PathLinks.each(function(l) { l.invalidateRoute(); });
|
||||
}
|
||||
} else if (e.change === go.ChangedEvent.Remove && e.object instanceof go.Layer) {
|
||||
// when a Node is deleted that has MultiNodePathLinks going through it, invalidate those link routes
|
||||
if (e.oldValue instanceof go.Node) {
|
||||
var node = e.oldValue;
|
||||
if (node._PathLinks) {
|
||||
node._PathLinks.each(function(l) { l.invalidateRoute(); });
|
||||
}
|
||||
} else if (e.oldValue instanceof MultiNodePathLink) {
|
||||
// when deleting a MultiNodePathLink, remove all references to it in Node._PathLinks
|
||||
var link = e.oldValue;
|
||||
var diagram = e.diagram;
|
||||
var midkeys = link.data.path;
|
||||
if (Array.isArray(midkeys)) {
|
||||
for (var i = 0; i < midkeys.length; i++) {
|
||||
var node = diagram.findNodeForKey(midkeys[i]);
|
||||
if (node !== null && node._PathLinks) node._PathLinks.remove(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create a few nodes and links
|
||||
myDiagram.model = new go.GraphLinksModel([
|
||||
{ key: 1, text: "Alpha", color: "lightyellow", loc: "0 0" },
|
||||
{ key: 2, text: "Beta", color: "brown", loc: "200 0" },
|
||||
{ key: 3, text: "Gamma", color: "green", loc: "300 100" },
|
||||
{ key: 4, text: "Delta", color: "slateblue", loc: "100 200" },
|
||||
{ key: 5, text: "Epsilon", color: "aquamarine", loc: "300 350" },
|
||||
{ key: 6, text: "Zeta", color: "tomato", loc: "0 100" },
|
||||
{ key: 7, text: "Eta", color: "goldenrod", loc: "0 300" },
|
||||
{ key: 8, text: "Theta", color: "orange", loc: "300 200" },
|
||||
], [
|
||||
{ from: 1, to: 5, path: [2, 3, 4], color: "blue" },
|
||||
{ from: 6, to: 5, path: [7, 4, 8], color: "red" }
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
function MultiNodePathLink() {
|
||||
go.Link.call(this);
|
||||
}
|
||||
go.Diagram.inherit(MultiNodePathLink, go.Link);
|
||||
|
||||
// ignores this.routing, this.adjusting, this.corner, this.smoothness, this.curviness
|
||||
MultiNodePathLink.prototype.computePoints = function() {
|
||||
// get the list of Nodes that should be along the path
|
||||
var nodes = [];
|
||||
if (this.fromNode !== null && this.fromNode.location.isReal()) {
|
||||
nodes.push(this.fromNode);
|
||||
}
|
||||
var midkeys = this.data.path;
|
||||
if (Array.isArray(midkeys)) {
|
||||
var diagram = this.diagram;
|
||||
for (var i = 0; i < midkeys.length; i++) {
|
||||
var node = diagram.findNodeForKey(midkeys[i]);
|
||||
if (node instanceof go.Node && node.location.isReal()) {
|
||||
nodes.push(node);
|
||||
// Optimization?: remember on each path Node all of
|
||||
// the MultiNodePathLinks that go through it;
|
||||
// but this optimization requires maintaining this cache
|
||||
// in a Diagram Changed event listener.
|
||||
var set = node._PathLinks;
|
||||
if (!set) set = node._PathLinks = new go.Set(/*go.Link*/);
|
||||
set.add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.toNode !== null && this.toNode.location.isReal()) {
|
||||
nodes.push(this.toNode);
|
||||
}
|
||||
|
||||
// now do the routing
|
||||
this.clearPoints();
|
||||
var prevloc = null;
|
||||
var thisloc = null;
|
||||
var nextloc = null;
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
var node = nodes[i];
|
||||
thisloc = node.location;
|
||||
nextloc = (i < nodes.length - 1) ? nodes[i + 1].location : null;
|
||||
|
||||
var prevpt = null;
|
||||
var nextpt = null;
|
||||
if (this.curve === go.Link.Bezier) {
|
||||
if (prevloc !== null && nextloc !== null) {
|
||||
var prevang = thisloc.directionPoint(prevloc);
|
||||
var nextang = thisloc.directionPoint(nextloc);
|
||||
var avg = (prevang + nextang) / 2;
|
||||
var clockwise = prevang > nextang;
|
||||
if (Math.abs(prevang - nextang) > 180) {
|
||||
avg += 180;
|
||||
clockwise = !clockwise;
|
||||
}
|
||||
if (avg >= 360) avg -= 360;
|
||||
prevpt = new go.Point(Math.sqrt(thisloc.distanceSquaredPoint(prevloc)) / 4, 0);
|
||||
prevpt.rotate(avg + (clockwise ? 90 : -90));
|
||||
prevpt.add(thisloc);
|
||||
nextpt = new go.Point(Math.sqrt(thisloc.distanceSquaredPoint(nextloc)) / 4, 0);
|
||||
nextpt.rotate(avg - (clockwise ? 90 : -90));
|
||||
nextpt.add(thisloc);
|
||||
} else if (nextloc !== null) {
|
||||
prevpt = null;
|
||||
nextpt = thisloc; // fix this point after the loop
|
||||
} else if (prevloc !== null) {
|
||||
var lastpt = this.getPoint(this.pointsCount - 1);
|
||||
prevpt = thisloc; // fix this point after the loop
|
||||
nextpt = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (prevpt !== null) this.addPoint(prevpt);
|
||||
this.addPoint(thisloc);
|
||||
if (nextpt !== null) this.addPoint(nextpt);
|
||||
prevloc = thisloc;
|
||||
}
|
||||
|
||||
// fix up the end points when it's Bezier
|
||||
if (this.curve === go.Link.Bezier) {
|
||||
// fix up the first point and the first control point
|
||||
var start = this.getLinkPointFromPoint(this.fromNode, this.fromPort, this.fromPort.getDocumentPoint(go.Spot.Center), this.getPoint(3), true);
|
||||
var ctrl2 = this.getPoint(2);
|
||||
this.setPoint(0, start);
|
||||
this.setPoint(1, new go.Point((start.x * 3 + ctrl2.x) / 4, (start.y * 3 + ctrl2.y) / 4));
|
||||
// fix up the last point and the last control point
|
||||
var end = this.getLinkPointFromPoint(this.toNode, this.toPort, this.toPort.getDocumentPoint(go.Spot.Center), this.getPoint(this.pointsCount - 4), false);
|
||||
var ctrl1 = this.getPoint(this.pointsCount - 3);
|
||||
this.setPoint(this.pointsCount - 2, new go.Point((end.x * 3 + ctrl1.x) / 4, (end.y * 3 + ctrl1.y) / 4));
|
||||
this.setPoint(this.pointsCount - 1, end);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
// end MultiNodePathLink class
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<div id="sample">
|
||||
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:700px; min-width: 200px"></div>
|
||||
<p>
|
||||
This sample demonstrates customization of the <a>Link</a>'s routing to go through multiple Nodes.
|
||||
The nodes are specified by key in the link data's "path" property, which must be an Array of node keys.
|
||||
</p>
|
||||
<p>
|
||||
As the user drags around Nodes on the "path", the routing is automatically recomputed to maintain a smooth curve.
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user